Prechádzať zdrojové kódy

Merge branch 'v2' of https://git.qianqiusoft.com/qianqiusoft/light-apiengine into v2

huangyh 6 rokov pred
rodič
commit
448fa85c71

+ 0 - 48
controllers/gen/PayCallbackController_gen.go

@@ -1,48 +0,0 @@
-
-package gen
-
-import (
-	"git.qianqiusoft.com/qianqiusoft/light-apiengine/entitys"
-	"github.com/gin-gonic/gin"
-	
-	"git.qianqiusoft.com/qianqiusoft/light-apiengine/controllers/partial"
-	
-	"git.qianqiusoft.com/qianqiusoft/light-apiengine/engine"
-)
-
-// PayCallbackController operations for PayCallback
-type PayCallbackController struct {
-	apiengine *engine.ApiEngine
-}
-
-func NewPayCallbackController(e *engine.ApiEngine) *PayCallbackController {
-	controller := &PayCallbackController{e}
-	return controller
-}
-
-
-
-// Wxpay
-// @Title Wxpay
-// @Description 微信支付回调         
-// @Success 200 {object} sysReturn
-// @Failure 403 :id is empty
-// @router /wxpay  [post]
-func (c *PayCallbackController) Wxpay(ctx *gin.Context) {
-	//
-	db:=c.apiengine.BusinessOrmEngine[ctx.GetString("domain")]
-	partial.PayCallback_Wxpay(&entitys.CtrlContext{c.apiengine, ctx, db, c.apiengine.PlatformOrmEngine})
-}
-
-// Alipay
-// @Title Alipay
-// @Description 支付宝支付回调         
-// @Success 200 {object} sysReturn
-// @Failure 403 :id is empty
-// @router /alipay  [post]
-func (c *PayCallbackController) Alipay(ctx *gin.Context) {
-	//
-	db:=c.apiengine.BusinessOrmEngine[ctx.GetString("domain")]
-	partial.PayCallback_Alipay(&entitys.CtrlContext{c.apiengine, ctx, db, c.apiengine.PlatformOrmEngine})
-}
-

+ 73 - 0
controllers/gen/SysPublicController_gen.go

@@ -0,0 +1,73 @@
+
+package gen
+
+import (
+	"git.qianqiusoft.com/qianqiusoft/light-apiengine/entitys"
+	"github.com/gin-gonic/gin"
+	
+	"git.qianqiusoft.com/qianqiusoft/light-apiengine/controllers/partial"
+	
+	"git.qianqiusoft.com/qianqiusoft/light-apiengine/engine"
+)
+
+// SysPublicController operations for SysPublic
+type SysPublicController struct {
+	apiengine *engine.ApiEngine
+}
+
+func NewSysPublicController(e *engine.ApiEngine) *SysPublicController {
+	controller := &SysPublicController{e}
+	return controller
+}
+
+
+
+// WxpayCallback
+// @Title WxpayCallback
+// @Description 微信支付回调         
+// @Success 200 {object} sysReturn
+// @Failure 403 :id is empty
+// @router /wxpay_callback  [post]
+func (c *SysPublicController) WxpayCallback(ctx *gin.Context) {
+	//
+	db:=c.apiengine.BusinessOrmEngine[ctx.GetString("domain")]
+	partial.SysPublic_WxpayCallback(&entitys.CtrlContext{c.apiengine, ctx, db, c.apiengine.PlatformOrmEngine})
+}
+
+// WxoauthParams
+// @Title WxoauthParams
+// @Description 获取微信oauth配置         
+// @Success 200 {object} sysReturn
+// @Failure 403 :id is empty
+// @router /wxoauth_params  [get]
+func (c *SysPublicController) WxoauthParams(ctx *gin.Context) {
+	//
+	db:=c.apiengine.BusinessOrmEngine[ctx.GetString("domain")]
+	partial.SysPublic_WxoauthParams(&entitys.CtrlContext{c.apiengine, ctx, db, c.apiengine.PlatformOrmEngine})
+}
+
+// WxjssdkParams
+// @Title WxjssdkParams
+// @Description 获取微信jssdk配置         
+// @Param	url      false  "当前页面url"  
+// @Success 200 {object} sysReturn
+// @Failure 403 :id is empty
+// @router /wxjssdk_params  [get]
+func (c *SysPublicController) WxjssdkParams(ctx *gin.Context) {
+	//
+	db:=c.apiengine.BusinessOrmEngine[ctx.GetString("domain")]
+	partial.SysPublic_WxjssdkParams(&entitys.CtrlContext{c.apiengine, ctx, db, c.apiengine.PlatformOrmEngine})
+}
+
+// AlipayCallback
+// @Title AlipayCallback
+// @Description 支付宝支付回调         
+// @Success 200 {object} sysReturn
+// @Failure 403 :id is empty
+// @router /alipay_callback  [post]
+func (c *SysPublicController) AlipayCallback(ctx *gin.Context) {
+	//
+	db:=c.apiengine.BusinessOrmEngine[ctx.GetString("domain")]
+	partial.SysPublic_AlipayCallback(&entitys.CtrlContext{c.apiengine, ctx, db, c.apiengine.PlatformOrmEngine})
+}
+

+ 0 - 54
controllers/partial/PayCallbackController.go

@@ -1,54 +0,0 @@
-
-package partial
-
-import (
-	"git.qianqiusoft.com/qianqiusoft/light-apiengine/entitys"
-	"git.qianqiusoft.com/qianqiusoft/light-apiengine/third/wx"
-	"github.com/silenceper/wechat/pay"
-
-	//sysmodel "git.qianqiusoft.com/qianqiusoft/light-apiengine/models"
-	//sysutils "git.qianqiusoft.com/qianqiusoft/light-apiengine/utils"
-	//"git.qianqiusoft.com/qianqiusoft/light-apiengine/models"
-	//__import_packages__
-)
-
-
-
-
-// _Wxpay
-// @Title _Wxpay
-// @Description 微信支付回调
-// @Success 200 {object} Account
-// @Failure 403 :id is empty
-func PayCallback_Wxpay(c *entitys.CtrlContext) {
-
-	r := wx.CallWxPayCallbackHandler(c)
-
-	if r.Code != 200{
-		c.Ctx.JSON(500, r)
-	}else{
-		res := pay.NotifyResponse{}
-		res.ReturnCode = "SUCCESS"
-		res.ReturnMsg = "OK"
-
-		c.Ctx.XML(200,&res)
-	}
-}
-
-// _Alipay
-// @Title _Alipay
-// @Description 支付宝支付回调
-// @Success 200 {object} Account
-// @Failure 403 :id is empty
-func PayCallback_Alipay(c *entitys.CtrlContext) {
-
-	ret := __none_func_pay_callback__()
-	if ret{
-		c.Ctx.String(200,"")
-	}
-}
-
-
-func __none_func_pay_callback__(params ... interface{}) bool{
-	return true
-}

+ 104 - 0
controllers/partial/SysPublicController.go

@@ -0,0 +1,104 @@
+
+package partial
+
+import (
+	"encoding/json"
+	"fmt"
+	"git.qianqiusoft.com/qianqiusoft/light-apiengine/entitys"
+	"git.qianqiusoft.com/qianqiusoft/light-apiengine/models"
+	"git.qianqiusoft.com/qianqiusoft/light-apiengine/third/wx"
+	"github.com/silenceper/wechat/pay"
+	"io/ioutil"
+
+	//sysmodel "git.qianqiusoft.com/qianqiusoft/light-apiengine/models"
+    //sysutils "git.qianqiusoft.com/qianqiusoft/light-apiengine/utils"
+	//"git.qianqiusoft.com/qianqiusoft/light-apiengine/models"
+	//__import_packages__
+)
+
+
+
+
+// _WxpayCallback
+// @Title _WxpayCallback
+// @Description 微信支付回调
+// @Success 200 {object} Account
+// @Failure 403 :id is empty
+func SysPublic_WxpayCallback(c *entitys.CtrlContext) {
+	r := wx.CallWxPayCallbackHandler(c)
+
+	if r.Code != 200{
+		c.Ctx.JSON(500, r)
+	}else{
+		res := pay.NotifyResponse{}
+		res.ReturnCode = "SUCCESS"
+		res.ReturnMsg = "OK"
+
+		c.Ctx.XML(200,&res)
+	}
+}
+
+// _WxoauthParams
+// @Title _WxoauthParams
+// @Description 获取微信oauth配置
+// @Success 200 {object} Account
+// @Failure 403 :id is empty
+func SysPublic_WxoauthParams(c *entitys.CtrlContext) {
+	contentBody, err := ioutil.ReadAll(c.Ctx.Request.Body)
+	if err != nil{
+		fmt.Println("读取body错误", err.Error())
+		c.Ctx.JSON(500, models.SysReturn{500, err.Error(), ""})
+		return
+	}
+	bmap := make(map[string]string)
+	err = json.Unmarshal(contentBody, &bmap)
+	if err != nil{
+		fmt.Println("Unmarshal错误", err.Error())
+		c.Ctx.JSON(500, models.SysReturn{500, err.Error(), ""})
+		return
+	}
+
+	param, err := wx.GetOAuthParams(bmap)
+	if err != nil{
+		c.Ctx.JSON(500, models.SysReturn{500, "", ""})
+	}else{
+		c.Ctx.JSON(200, models.SysReturn{200, "", param})
+	}
+}
+
+// _WxjssdkParams
+// @Title _WxjssdkParams
+// @Description 获取微信jssdk配置
+// @Success 200 {object} Account
+// @Failure 403 :id is empty
+func SysPublic_WxjssdkParams(c *entitys.CtrlContext) {
+	url := c.Ctx.DefaultQuery("url", "")
+	if url == ""{
+		c.Ctx.JSON(200, models.SysReturn{500, "参数rul为空", ""})
+		return
+	}
+	config, err := wx.GetJSSDKRarams(url)
+	if err != nil{
+		c.Ctx.JSON(200, models.SysReturn{500, err.Error(), ""})
+	}else{
+		c.Ctx.JSON(200, models.SysReturn{200, "", config})
+	}
+}
+
+// _AlipayCallback
+// @Title _AlipayCallback
+// @Description 支付宝支付回调
+// @Success 200 {object} Account
+// @Failure 403 :id is empty
+func SysPublic_AlipayCallback(c *entitys.CtrlContext) {
+
+	ret := __none_func_sys_public__()
+	if ret{
+		c.Ctx.String(200,"")
+	}
+}
+
+
+func __none_func_sys_public__(params ... interface{}) bool{
+	return true
+}

+ 3 - 1
godep.yaml

@@ -33,4 +33,6 @@ import:
   - package: github.com/xormplus/core
     repo: https://git.qianqiusoft.com/github.com/xormplus__core.git
   - package: github.com/dchest/captcha
-    repo: https://github.com/dchest/captcha.git
+    repo: https://github.com/dchest/captcha.git
+  - package: github.com/go-playground/validator/v10
+    repo: https://git.qianqiusoft.com/public/go-playground__validator.v10.git

+ 9 - 3
light-apiengine.xml

@@ -791,10 +791,16 @@
                 </return>
             </api>
         </controller>
-        <controller name="pay_callback" desc="微信或支付宝支付回调相关接口" skip_login="true">
-            <api name="wxpay" desc="微信支付回调" method="post">
+        <controller name="sys_public" desc="开放接口" skip_login="true">
+            <api name="wxpay_callback" desc="微信支付回调" method="post">
             </api>
-            <api name="alipay" desc="支付宝支付回调" method="post">
+            <api name="wxoauth_params" desc="获取微信oauth配置" method="post">
+                <param name="body" desc="微信回调回传的参数"></param>
+            </api>
+            <api name="wxjssdk_params" desc="获取微信jssdk配置" method="get">
+                <param name="url" desc="当前页面url"></param>
+            </api>
+            <api name="alipay_callback" desc="支付宝支付回调" method="post">
             </api>
         </controller>
     </controllers>

+ 0 - 32
routers/pay_callback_gen.go

@@ -1,32 +0,0 @@
-
-package routers
-
-import (
-	"git.qianqiusoft.com/qianqiusoft/light-apiengine/engine"
-	
-	"git.qianqiusoft.com/qianqiusoft/light-apiengine/controllers/gen"
-)
-
-func init(){
-	addRegisterHandler(registerPayCallbackRouter)
-}
-
-func registerPayCallbackRouter(e *engine.ApiEngine){
-	api:=e.GinEngine.Group("/api")
-	v1:=api.Group("/v1/pay_callback")
-	
-	if len(_router["pay_callback"]) >0 {
-		v1.Use(_router["pay_callback"]...)
-	}
-	ctrler := gen.NewPayCallbackController(e)
-
-
-
-	//v1.GET("/wxpay",ctrler.Wxpay)
-	v1.POST("/wxpay",ctrler.Wxpay)
-
-	//v1.GET("/alipay",ctrler.Alipay)
-	v1.POST("/alipay",ctrler.Alipay)
-
-}
-

+ 38 - 0
routers/sys_public_gen.go

@@ -0,0 +1,38 @@
+
+package routers
+
+import (
+	"git.qianqiusoft.com/qianqiusoft/light-apiengine/engine"
+	
+	"git.qianqiusoft.com/qianqiusoft/light-apiengine/controllers/gen"
+)
+
+func init(){
+	addRegisterHandler(registerSysPublicRouter)
+}
+
+func registerSysPublicRouter(e *engine.ApiEngine){
+	api:=e.GinEngine.Group("/api")
+	v1:=api.Group("/v1/sys_public")
+	
+	if len(_router["sys_public"]) >0 {
+		v1.Use(_router["sys_public"]...)
+	}
+	ctrler := gen.NewSysPublicController(e)
+
+
+
+	//v1.GET("/wxpay_callback",ctrler.WxpayCallback)
+	v1.POST("/wxpay_callback",ctrler.WxpayCallback)
+
+	//v1.GET("/wxoauth_params",ctrler.WxoauthParams)
+	v1.POST("/wxoauth_params",ctrler.WxoauthParams)
+
+	v1.GET("/wxjssdk_params",ctrler.WxjssdkParams)
+	//v1.POST("/wxjssdk_params",ctrler.WxjssdkParams)
+
+	//v1.GET("/alipay_callback",ctrler.AlipayCallback)
+	v1.POST("/alipay_callback",ctrler.AlipayCallback)
+
+}
+

+ 76 - 32
third/wx/global.go

@@ -3,63 +3,94 @@ package wx
 import (
 	"git.qianqiusoft.com/qianqiusoft/light-apiengine/config"
 	"git.qianqiusoft.com/qianqiusoft/light-apiengine/entitys"
-	"strconv"
+	"sync"
 	"time"
 
 	"github.com/silenceper/wechat"
 	"github.com/silenceper/wechat/cache"
+	"github.com/silenceper/wechat/oauth"
 )
 
 var wc *wechat.Wechat
+var wxoauth *oauth.Oauth
+
+var wxConfig struct {
+	WxPayCallback  string // 完整微信支付回调url,
+	AppId          string // 公众号appid
+	AppSecret      string // 公众号appsecret
+	Token          string // 设置token
+	EncodingAseKey string // ase key
+	PayMchId       string // 商户号id
+	PayKey         string // 商户支付设置的key
+	RedirectUrl    string // 微信Oauth完整跳转uri
+	Scope          string // 微信Oauth的scope
+	ResponseType   string // 微信oauth的response type
+	State          string // 微信oauth的state
+}
 
 func init() {
-	c := &LocalCache{}
-	wxpayCallback := config.AppConfig.GetKey("wxpay_callback") // 完整微信回调url,
-	appId := config.AppConfig.GetKey("app_id")					// 公众号appid
-	appSecret := config.AppConfig.GetKey("app_secret")			// 公众号app secret
-	token := config.AppConfig.GetKey("token")
-	encodingAseKey := config.AppConfig.GetKey("encoding_aes_key")
-	payMchId := config.AppConfig.GetKey("mch_id")				// 商户号id
-	payKey := config.AppConfig.GetKey("pay_key")				// 商户支付设置的key
-
-	config := &wechat.Config{appId, appSecret, token, encodingAseKey, payMchId, wxpayCallback, payKey, c}
+	c := getLocalCache()
+	wxConfig.WxPayCallback = config.AppConfig.GetKey("wxpay_callback") // 完整微信回调url,
+	wxConfig.AppId = config.AppConfig.GetKey("appid")					// 公众号appid
+	wxConfig.AppSecret = config.AppConfig.GetKey("appsecret")			// 公众号appsecret
+	wxConfig.Token = config.AppConfig.GetKey("token")
+	wxConfig.EncodingAseKey = config.AppConfig.GetKey("encoding_aes_key")
+	wxConfig.PayMchId = config.AppConfig.GetKey("mch_id")				// 商户号id
+	wxConfig.PayKey = config.AppConfig.GetKey("pay_key")				// 商户支付设置的key
+	wxConfig.RedirectUrl = config.AppConfig.GetKey("redirect_url")
+	wxConfig.Scope = config.AppConfig.GetKey("scope")
+	wxConfig.ResponseType = config.AppConfig.GetKey("response_type")
+	wxConfig.State = config.AppConfig.GetKey("state")
+
+	config := &wechat.Config{wxConfig.AppId, wxConfig.AppSecret, wxConfig.Token, wxConfig.EncodingAseKey, wxConfig.PayMchId, wxConfig.WxPayCallback, wxConfig.PayKey, c}
 	wc = wechat.NewWechat(config)
+	wxoauth = wc.GetOauth()
 }
 
 /*********************local cache*************************/
 type LocalCache struct {
 	cache.Cache
-	m map[string]string
+	m map[string]interface{}
+	mutex sync.Mutex
 }
 
-func (this *LocalCache) Get(key string) interface{} {
-	if this.m == nil {
-		return nil
-	}
-
-	tokenTime := this.m["timeout"]
-	if tokenTime == "" {
-		return nil
-	}
+func getLocalCache()*LocalCache{
+	lc := &LocalCache{}
+	lc.m = make(map[string]interface{})
 
-	tInt64, _ := strconv.ParseInt(tokenTime, 10, 64)
+	return lc
+}
+func (lc *LocalCache)Get(key string) interface{}{
+	lc.mutex.Lock()
+	defer lc.mutex.Unlock()
 
-	if time.Now().After(time.Unix(tInt64, 0)) {
+	if o, e := lc.m[key]; !e{
 		return nil
+	}else{
+		return o
 	}
-
-	return this.m[key]
 }
+func (lc *LocalCache)Set(key string, val interface{}, timeout time.Duration) error{
+	lc.mutex.Lock()
+	defer lc.mutex.Unlock()
 
-func (this *LocalCache) Set(key string, val interface{}, timeout time.Duration) error {
-	if this.m == nil {
-		this.m = make(map[string]string)
-	}
+	lc.m[key] = val
+	return nil
+}
+func (lc *LocalCache)IsExist(key string) bool{
+	lc.mutex.Lock()
+	defer lc.mutex.Unlock()
 
-	t := time.Now().Add(timeout).Unix()
+	_, e := lc.m[key]
+	return e
+}
+func (lc *LocalCache)Delete(key string) error {
+	lc.mutex.Lock()
+	defer lc.mutex.Unlock()
 
-	this.m["timeout"] = strconv.FormatInt(t, 10)
-	this.m[key] = val.(string)
+	if _, e := lc.m[key]; e {
+		delete(lc.m, key)
+	}
 	return nil
 }
 /*********************************************************/
@@ -89,3 +120,16 @@ type PayParams struct{
 	PaySign   string `json:"paySign"`
 	OutTradeNo   string `json:"outTradeNo"`
 }
+
+// 微信oauth跳转信息,
+type WxOAuthConfig struct {
+	AuthUrl          string `json:"auth_url"`
+	AppId            string `json:"app_id"`
+	// 给微信跳转的url
+	RedirectUrl      string `json:"redirect_url"`
+	ResponseType     string `json:"response_type"`
+	Scope            string `json:"scope"`
+	State            string `json:"state"`
+	// 完整的微信Oauth的url
+	OAuthRedirectUrl string `json:"oauth_redirect_url"`
+}

+ 84 - 0
third/wx/token.go

@@ -0,0 +1,84 @@
+package wx
+
+import (
+	"github.com/silenceper/wechat/oauth"
+	"sync"
+	"time"
+)
+
+type tokenTiming struct {
+	Token *oauth.ResAccessToken
+	Timing time.Time
+}
+
+var tokenMap map[string]*tokenTiming
+var mutex sync.Mutex
+
+func init(){
+	tokenMap = make(map[string]*tokenTiming)
+	tokenCheckLoop()
+}
+
+func addToken(openId string, token *oauth.ResAccessToken) {
+	mutex.Lock()
+	defer mutex.Unlock()
+
+	// 无则添加,有则更新
+	tokenMap[openId] = &tokenTiming{
+		Token:  token,
+		Timing: time.Now(),
+	}
+}
+
+func getToken(openId string) *oauth.ResAccessToken{
+	mutex.Lock()
+	defer mutex.Unlock()
+
+	if t, exists := tokenMap[openId]; !exists{
+		return nil
+	}else{
+		return t.Token
+	}
+}
+
+func removeToken(openId string){
+	mutex.Lock()
+	defer mutex.Unlock()
+
+	if _, exists := tokenMap[openId]; exists{
+		delete(tokenMap, openId)
+	}
+}
+
+func tokenCheckLoop(){
+	go func(){
+		t:=time.NewTicker(10 * 60 * time.Second)
+		for {
+			select {
+			case <-t.C:
+				mutex.Lock()
+				ks := make([]string, 0)
+				for k, v := range tokenMap{
+					if time.Now().Sub(v.Timing) > 90 * time.Minute{
+						ks = append(ks, k)
+					}
+				}
+				for i := range ks{
+					//t, err := wxoauth.RefreshAccessToken(tokenMap[ks[i]].Token.RefreshToken)
+					//if err != nil{
+					//	delete(tokenMap, ks[i])
+					//	continue
+					//}else{
+					//	tokenMap[ks[i]] = t
+					//}
+					// 暂时删除不刷新
+					delete(tokenMap, ks[i])
+				}
+				mutex.Unlock()
+			}
+		}
+	}()
+}
+
+
+

+ 65 - 1
third/wx/wx.go

@@ -1,14 +1,18 @@
 package wx
 
 import (
+	"errors"
 	"fmt"
 	"git.qianqiusoft.com/qianqiusoft/light-apiengine/entitys"
 	"git.qianqiusoft.com/qianqiusoft/light-apiengine/models"
 	"git.qianqiusoft.com/qianqiusoft/light-apiengine/utils"
-	"errors"
+	"github.com/silenceper/wechat/js"
+	"github.com/silenceper/wechat/oauth"
 	"github.com/silenceper/wechat/pay"
 	"github.com/silenceper/wechat/util"
+	"net/url"
 	"strconv"
+	"strings"
 )
 
 var wxPayCallbackHandler func(result *pay.NotifyResult)models.SysReturn = nil
@@ -105,3 +109,63 @@ func PayJSAPI(params *PayParams)(*JSAPIPayConfig, error){
 		return nil, err
 	}
 }
+
+// 获取微信OAuth认证参数
+func GetOAuthParams(paramMap map[string]string)(*WxOAuthConfig, error){
+	config := WxOAuthConfig{}
+	urlstr := wxConfig.RedirectUrl
+	paramstr := ""
+	for k, v := range paramMap{
+		paramstr += fmt.Sprintf("%s=%s", k, url.QueryEscape(v))
+	}
+	if strings.Index(urlstr, "%s") > 0{
+		urlstr = fmt.Sprintf(urlstr, paramstr)
+	}
+
+	url, err := wxoauth.GetRedirectURL(urlstr, wxConfig.Scope, url.QueryEscape(wxConfig.State))
+	if err != nil{
+		return nil, err
+	}
+	config.OAuthRedirectUrl = url
+	config.AppId = wxConfig.AppId
+	config.State = wxConfig.State
+	config.Scope = wxConfig.Scope
+	config.ResponseType = wxConfig.ResponseType
+	config.AuthUrl = "https://open.weixin.qq.com/connect/oauth2/authorize"
+	config.RedirectUrl = wxConfig.RedirectUrl
+
+	return &config, nil
+}
+
+// 获取jssdk配置参数
+func GetJSSDKRarams(url string)(*js.Config, error){
+	return wc.GetJs().GetConfig(url)
+}
+
+// 获取token
+func GetOpenId(code string)(string, error){
+	resToken, err := wxoauth.GetUserAccessToken(code)
+	if err == nil{
+		addToken(resToken.OpenID, &resToken)
+	}
+	return resToken.OpenID, err
+}
+
+// 根据code获取用户信息(需scope为 snsapi_userinfo)
+func GetUserInfoByCode(code string)(*oauth.UserInfo, error){
+	openId, err := GetOpenId(code)
+	if err != nil{
+		return nil, err
+	}
+	return GetUserInfo(openId)
+}
+
+// 获取用户信息(需scope为 snsapi_userinfo)
+func GetUserInfo(openId string)(*oauth.UserInfo, error){
+	token := getToken(openId)
+	if token == nil{
+		return nil, errors.New("token of openid " + openId + "does not exist")
+	}
+	userInfo, err := wxoauth.GetUserInfo(token.AccessToken, openId)
+	return &userInfo, err
+}

+ 113 - 0
utils/aes128.go

@@ -0,0 +1,113 @@
+package utils
+
+import (
+	"bytes"
+	"crypto/aes"
+	"crypto/cipher"
+	"encoding/base64"
+)
+
+const (
+	sKey        = "dde4b1f8a9e6b814"
+	ivParameter     = "d690b1f8a957b834"
+)
+
+//加密
+func PswEncrypt(src, skey, ivParam string)(string){
+	if skey == ""{
+		skey = sKey
+	}
+	if ivParam == ""{
+		ivParam = ivParameter
+	}
+
+	key := []byte(skey)
+	iv := []byte(ivParam)
+
+	result, err := Aes128Encrypt([]byte(src), key, iv)
+	if err != nil {
+		panic(err)
+	}
+	return  base64.RawStdEncoding.EncodeToString(result)
+}
+
+//解密
+func PswDecrypt(src, skey, ivParam string)(string) {
+	if skey == ""{
+		skey = sKey
+	}
+	if ivParam == ""{
+		ivParam = ivParameter
+	}
+
+	key := []byte(skey)
+	iv := []byte(ivParam)
+
+	var result []byte
+	var err error
+
+	result,err=base64.RawStdEncoding.DecodeString(src)
+	if err != nil {
+		panic(err)
+	}
+	origData, err := Aes128Decrypt(result, key, iv)
+	if err != nil {
+		panic(err)
+	}
+	return string(origData)
+
+}
+
+func Aes128Encrypt(origData, key []byte,IV []byte) ([]byte, error) {
+	if key == nil || len(key) != 16 {
+		return nil, nil
+	}
+	if IV != nil && len(IV) != 16 {
+		return nil, nil
+	}
+
+	block, err := aes.NewCipher(key)
+	if err != nil {
+		return nil, err
+	}
+	blockSize := block.BlockSize()
+	origData = PKCS5Padding(origData, blockSize)
+	blockMode := cipher.NewCBCEncrypter(block, IV[:blockSize])
+	crypted := make([]byte, len(origData))
+	// 根据CryptBlocks方法的说明,如下方式初始化crypted也可以
+	blockMode.CryptBlocks(crypted, origData)
+	return crypted, nil
+}
+
+func Aes128Decrypt(crypted, key []byte,IV []byte) ([]byte, error) {
+	if key == nil || len(key) != 16 {
+		return nil, nil
+	}
+	if IV != nil && len(IV) != 16 {
+		return nil, nil
+	}
+
+	block, err := aes.NewCipher(key)
+	if err != nil {
+		return nil, err
+	}
+	blockSize := block.BlockSize()
+	blockMode := cipher.NewCBCDecrypter(block,IV[:blockSize])
+	origData := make([]byte, len(crypted))
+	blockMode.CryptBlocks(origData, crypted)
+	origData = PKCS5UnPadding(origData)
+	return origData, nil
+}
+
+func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
+	padding := blockSize - len(ciphertext)%blockSize
+	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
+	return append(ciphertext, padtext...)
+}
+
+func PKCS5UnPadding(origData []byte) []byte {
+	length := len(origData)
+	// 去掉最后一个字节 unpadding 次
+	unpadding := int(origData[length-1])
+	return origData[:(length - unpadding)]
+}