Browse Source

新增微信公众号绑定

hongze 9 months ago
parent
commit
0d6e095700

+ 1 - 0
common/component/config/wechat_config.go

@@ -19,6 +19,7 @@ func (w *WechatConfig) GetAppid() string {
 func (w *WechatConfig) GetSecret() string {
 	return w.opts.Secret
 }
+
 func (w *WechatConfig) InitConfig() {
 	opts := WechatOpts{
 		Appid:  w.GetString("appid"),

+ 52 - 0
common/component/wechat/wechat_client.go

@@ -146,3 +146,55 @@ func code2url(appID, secret, code string) (string, error) {
 
 	return url.String(), nil
 }
+
+type WxUserInfo struct {
+	OpenId       string `json:"openid"`
+	AccessToken  string `json:"access_token"`
+	RefreshToken string `json:"refresh_token"`
+	Scope        string `json:"scope"`
+	ErrCode      int
+	ErrMsg       string
+}
+
+// Login 小程序登录
+func (cli *Client) GzhLogin(code string) (wxUser WxUser, err error) {
+	if code == "" {
+		err = exception.New(exception.WeChatCodeEmpty)
+		return
+	}
+	api, err := code2url(cli.appid, cli.secret, code)
+	if err != nil {
+		err = exception.New(exception.WeChatIllegalRequest)
+		return
+	}
+	//请求微信接口
+	res, err := cli.client.Get(api)
+	defer func(Body io.ReadCloser) {
+		Body.Close()
+	}(res.Body)
+	if err != nil || res.StatusCode != 200 {
+		logger.Error("获取微信用户信息失败:%v", res.Status)
+		err = exception.New(exception.WeChatServerError)
+		return
+	}
+	var data loginResponse
+	err = json.NewDecoder(res.Body).Decode(&data)
+	if err != nil {
+		logger.Error("解析微信应答失败:%v", err)
+		err = exception.New(exception.WeChatResponseError)
+		return
+	}
+
+	fmt.Println(data)
+
+	if data.Errcode != 0 {
+		logger.Error("获取用户信息失败:%v", data.Errmsg)
+		err = exception.New(exception.WechatUserInfoFailed)
+		return
+	}
+	wxUser = WxUser{
+		OpenId:  data.LoginResponse.OpenID,
+		UnionId: data.LoginResponse.UnionID,
+	}
+	return
+}

+ 32 - 0
controllers/user/wechat.go

@@ -0,0 +1,32 @@
+package user
+
+import (
+	logger "eta/eta_mini_ht_api/common/component/log"
+	"eta/eta_mini_ht_api/common/exception"
+	"eta/eta_mini_ht_api/controllers"
+	"eta/eta_mini_ht_api/service/auth"
+)
+
+// RefreshToken 绑定微信公众号
+// @Summary 绑定微信公众号
+// @Success 200 {object} controllers.BaseResponse
+// @Description 更新token
+// @router /bind_gzh [get]
+func (a *AuthController) BindGzh(code string) {
+	controllers.Wrap(&a.BaseController, func() (result *controllers.WrapData, err error) {
+		result = a.InitWrapData("刷新token失败")
+		if code == "" {
+			logger.Error("code不能为空")
+			return result, exception.New(exception.WeChatCodeEmpty)
+		}
+		//刷新token
+		err = auth.BindWxGzh(code)
+		if err != nil {
+			logger.Error("绑定公众号失败:%v", err)
+			a.FailedResult("绑定公众号失败", result)
+			return
+		}
+		a.SuccessResult("绑定成功", nil, result)
+		return
+	})
+}

+ 55 - 9
domian/user/user_serivce.go

@@ -8,11 +8,12 @@ import (
 )
 
 type UserDTO struct {
-	Id       int
-	Username string
-	Mobile   string
-	OpenId   string
-	UnionId  string
+	Id        int
+	Username  string
+	Mobile    string
+	OpenId    string
+	UnionId   string
+	GzhOpenId string
 }
 
 type FeedbackDTO struct {
@@ -73,10 +74,11 @@ func FeedBack(dto FeedbackDTO) (err error) {
 
 func convertToTemplateUser(dto *UserDTO) userDao.TemplateUser {
 	return userDao.TemplateUser{
-		Username: dto.Username,
-		Mobile:   dto.Mobile,
-		OpenId:   dto.OpenId,
-		UnionId:  dto.UnionId,
+		Username:  dto.Username,
+		Mobile:    dto.Mobile,
+		OpenId:    dto.OpenId,
+		UnionId:   dto.UnionId,
+		GzhOpenId: dto.GzhOpenId,
 	}
 }
 
@@ -111,3 +113,47 @@ func GetUserByOpenId(openId string) (UserDTO, error) {
 	dto = convertUserDTO(templateUser)
 	return dto, nil
 }
+
+func GetTemplateUserByUnionId(openId string) (user UserDTO, err error) {
+	templateUser, err := userDao.GetUserByUnionId(openId)
+	if err != nil {
+		logger.Error("获取用户信息失败:%v", err)
+		return
+	}
+	user = convertUserDTO(templateUser)
+	return
+}
+
+// 绑定小程序OpenId
+func BindUserXcxOpenId(userId int, openId string) (err error) {
+	err = userDao.BindXcxOpenId(userId, openId)
+	if err != nil {
+		if !errors.Is(err, gorm.ErrRecordNotFound) {
+			logger.Error("绑定小程序openId失败:%v", err)
+		}
+		return
+	}
+	return
+}
+
+// 绑定公众号OpenId
+func BindUserGzhOpenId(userId int, openId string) (err error) {
+	err = userDao.BindGzhOpenId(userId, openId)
+	if err != nil {
+		if !errors.Is(err, gorm.ErrRecordNotFound) {
+			logger.Error("绑定公众号openId失败:%v", err)
+		}
+		return
+	}
+	return
+}
+
+func GetTemplateUserByGzhOpenId(openId string) (user UserDTO, err error) {
+	templateUser, err := userDao.GetUserByGzhOpenId(openId)
+	if err != nil {
+		logger.Error("获取用户信息失败:%v", err)
+		return
+	}
+	user = convertUserDTO(templateUser)
+	return
+}

+ 8 - 0
go.mod

@@ -9,6 +9,7 @@ require (
 	github.com/go-redis/redis/v8 v8.11.5
 	github.com/google/uuid v1.6.0
 	github.com/gorilla/websocket v1.5.3
+	github.com/silenceper/wechat/v2 v2.1.6
 	gorm.io/driver/mysql v1.5.7
 	gorm.io/gorm v1.25.11
 )
@@ -16,8 +17,10 @@ require (
 require (
 	filippo.io/edwards25519 v1.1.0 // indirect
 	github.com/beorn7/perks v1.0.1 // indirect
+	github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d // indirect
 	github.com/cespare/xxhash/v2 v2.2.0 // indirect
 	github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
+	github.com/fatih/structs v1.1.0 // indirect
 	github.com/go-sql-driver/mysql v1.8.1 // indirect
 	github.com/hashicorp/golang-lru v0.5.4 // indirect
 	github.com/jinzhu/inflection v1.0.0 // indirect
@@ -29,6 +32,11 @@ require (
 	github.com/prometheus/common v0.48.0 // indirect
 	github.com/prometheus/procfs v0.12.0 // indirect
 	github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18 // indirect
+	github.com/sirupsen/logrus v1.9.0 // indirect
+	github.com/spf13/cast v1.4.1 // indirect
+	github.com/tidwall/gjson v1.14.1 // indirect
+	github.com/tidwall/match v1.1.1 // indirect
+	github.com/tidwall/pretty v1.2.0 // indirect
 	golang.org/x/crypto v0.24.0 // indirect
 	golang.org/x/net v0.23.0 // indirect
 	golang.org/x/sys v0.21.0 // indirect

+ 119 - 0
go.sum

@@ -1,12 +1,23 @@
 filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
 filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
+github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a h1:HbKu58rmZpUGpz5+4FfNmIU+FmZg2P3Xaj2v2bfNWmk=
+github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
+github.com/alicebob/miniredis/v2 v2.30.0 h1:uA3uhDbCxfO9+DI/DuGeAMr9qI+noVWwGPNTFuKID5M=
+github.com/alicebob/miniredis/v2 v2.30.0/go.mod h1:84TWKZlxYkfgMucPBf5SOQBYJceZeQRFIaQgNMiCX6Q=
 github.com/beego/beego/v2 v2.3.0 h1:iECVwzm6egw6iw6tkWrEDqXG4NQtKLQ6QBSYqlM6T/I=
 github.com/beego/beego/v2 v2.3.0/go.mod h1:Ob/5BJ9fIKZLd4s9ZV3o9J6odkkIyL83et+p98gyYXo=
 github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
 github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
+github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d h1:pVrfxiGfwelyab6n21ZBkbkmbevaf+WvMIiR7sr97hw=
+github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
+github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
 github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
 github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
+github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
+github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
 github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
@@ -17,6 +28,9 @@ github.com/elastic/go-elasticsearch/v7 v7.17.10 h1:TCQ8i4PmIJuBunvBS6bwT2ybzVFxx
 github.com/elastic/go-elasticsearch/v7 v7.17.10/go.mod h1:OJ4wdbtDNk5g503kvlHLyErCgQwwzmDtaFC4XyOxXA4=
 github.com/elazarl/go-bindata-assetfs v1.0.1 h1:m0kkaHRKEu7tUIUFVwhGGGYClXvyl4RE03qmvRTNfbw=
 github.com/elazarl/go-bindata-assetfs v1.0.1/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
+github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
+github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
+github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
 github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
 github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
 github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
@@ -24,14 +38,33 @@ github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq
 github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
 github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
 github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
+github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
+github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
+github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
+github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
+github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
 github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
 github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
 github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
 github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
+github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
 github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
 github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
+github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
+github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
 github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
 github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
 github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
@@ -42,10 +75,19 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
 github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
 github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
+github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
+github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
 github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
 github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
+github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
+github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
 github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
 github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
+github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
+github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
+github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
+github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
 github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
 github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@@ -62,25 +104,102 @@ github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjR
 github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
 github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18 h1:DAYUYH5869yV94zvCES9F51oYtN5oGlwjxJJz7ZCnik=
 github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg=
+github.com/silenceper/wechat/v2 v2.1.6 h1:2br2DxNzhksmvIBJ+PfMqjqsvoZmd/5BnMIfjKYUBgc=
+github.com/silenceper/wechat/v2 v2.1.6/go.mod h1:7Iu3EhQYVtDUJAj+ZVRy8yom75ga7aDWv8RurLkVm0s=
+github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
+github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
+github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA=
+github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
 github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/tidwall/gjson v1.14.1 h1:iymTbGkQBhveq21bEvAQ81I0LEBork8BFe1CUZXdyuo=
+github.com/tidwall/gjson v1.14.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
+github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
+github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
+github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
+github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/gopher-lua v0.0.0-20220504180219-658193537a64 h1:5mLPGnFdSsevFRFc9q3yYbBkB6tsm4aCwwQV/j1JQAQ=
+github.com/yuin/gopher-lua v0.0.0-20220504180219-658193537a64/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
 golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
+golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
 golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
 golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
 golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
+google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
+google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
+google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
+google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
 google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
 google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
+gopkg.in/h2non/gock.v1 v1.1.2 h1:jBbHXgGBK/AoPVfJh5x4r/WxIrElvbLel8TCZkkZJoY=
+gopkg.in/h2non/gock.v1 v1.1.2/go.mod h1:n7UGz/ckNChHiK05rDoiC4MYSunEC/lyaUm2WWaDva0=
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
 gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo=

+ 3 - 0
middleware/auth_middleware.go

@@ -39,12 +39,15 @@ func rd() *cache.RedisCache {
 
 var publicRoutes = []string{
 	"/auth/refreshToken",
+	"/auth/bind_gzh",
 }
 
 func AuthMiddleware() web.FilterFunc {
 	return func(ctx *context.Context) {
 		path := ctx.Input.URL()
 		logger.Info("请求路径:%v", path)
+		f := allowed(path)
+		fmt.Println(f)
 		if !allowed(path) {
 			rep := unAuthorized()
 			auth := ctx.Input.Header(authorization)

+ 21 - 0
models/user/template_user.go

@@ -16,6 +16,7 @@ type TemplateUser struct {
 	Username    string    `gorm:"column:username;type:varchar(20);comment:用户名"`
 	Mobile      string    `gorm:"column:mobile;type:varchar(15);comment:手机号"`
 	OpenId      string    `gorm:"column:open_id;type:varchar(50);comment:open_id"`
+	GzhOpenId   string    `gorm:"column:gzh_open_id;type:varchar(255);comment:gzh_open_id"`
 	UnionId     string    `gorm:"column:union_id;type:varchar(50);comment:union_id"`
 	IsDeleted   int       `gorm:"column:is_deleted;type:int(11);comment:是否删除"`
 	CreatedTime time.Time `gorm:"column:created_time;type:timestamps;comment:创建时间"`
@@ -27,13 +28,19 @@ func (t *TemplateUser) BeforeCreate(tx *gorm.DB) (err error) {
 	t.IsDeleted = NotDeleted
 	return
 }
+
 func GetUserByMobile(mobile string) (user TemplateUser, err error) {
 	return queryByColumn("mobile", mobile)
 }
+
 func GetUserByOpenId(openId string) (user TemplateUser, err error) {
 	return queryByColumn("open_id", openId)
 }
 
+func GetUserByUnionId(unionId string) (user TemplateUser, err error) {
+	return queryByColumn("union_id", unionId)
+}
+
 func queryByColumn(column string, value string) (user TemplateUser, err error) {
 	err = models.Main().Unscoped().Where(column, value).First(&user).Error
 	return
@@ -47,3 +54,17 @@ func BindMobile(userId int, mobile string) (err error) {
 	err = models.Main().Table("template_users").Where("id = ?", userId).Updates(map[string]interface{}{"mobile": mobile, "updated_time": time.Now()}).Error
 	return
 }
+
+func BindXcxOpenId(userId int, xcxOpenId string) (err error) {
+	err = models.Main().Table("template_users").Where("id = ?", userId).Updates(map[string]interface{}{"open_id": xcxOpenId, "updated_time": time.Now()}).Error
+	return
+}
+
+func BindGzhOpenId(userId int, gzhOpenId string) (err error) {
+	err = models.Main().Table("template_users").Where("id = ?", userId).Updates(map[string]interface{}{"gzh_open_id": gzhOpenId, "updated_time": time.Now()}).Error
+	return
+}
+
+func GetUserByGzhOpenId(gzhOpenId string) (user TemplateUser, err error) {
+	return queryByColumn("gzh_open_id", gzhOpenId)
+}

+ 23 - 0
models/wx_token.go

@@ -0,0 +1,23 @@
+package models
+
+type WxToken struct {
+	Id          int    `gorm:"column:id;primaryKey;autoIncrement:'id'"`
+	AccessToken string `gorm:"column:access_token;type:varchar(512);comment:微信token"`
+	ExpiresIn   int64  `gorm:"column:expires_in;type:timestamps;comment:过期时间"` // 过期时间
+}
+
+func RegisterWxToken(wxToken *WxToken) (err error) {
+	err = Main().Create(&wxToken).Error
+	return
+}
+
+func UpdateWxToken(accessToken string, expiresIn int64) (err error) {
+	err = Main().Table("wx_token").Where("id = ?", 0).Updates(map[string]interface{}{"access_token": accessToken, "expires_in": expiresIn}).Error
+	return
+}
+
+// GetById 根据id获取accessToken信息
+func GetWxTokenById() (info WxToken, err error) {
+	err = Main().Unscoped().Where("id", 0).First(&info).Error
+	return
+}

+ 11 - 0
routers/commentsRouter.go

@@ -170,6 +170,17 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_mini_ht_api/controllers/user:AuthController"] = append(beego.GlobalControllerRouter["eta/eta_mini_ht_api/controllers/user:AuthController"],
+        beego.ControllerComments{
+            Method: "BindGzh",
+            Router: `/bind_gzh`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(
+				param.New("code"),
+			),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_mini_ht_api/controllers/user:AuthController"] = append(beego.GlobalControllerRouter["eta/eta_mini_ht_api/controllers/user:AuthController"],
         beego.ControllerComments{
             Method: "Disclaimer",

+ 86 - 1
service/auth/auth_service.go

@@ -204,10 +204,28 @@ func RefreshToken(code string) (token string, isBindMobile int, err error) {
 	if isAdd {
 		user.OpenId = wechatInfo.OpenId
 		user.UnionId = wechatInfo.UnionId
-		err = userService.RegisterTemplateUser(&user)
+		var isRegister bool
+
+		//判断unionid是否存在
+		wxUser, unionErr := userService.GetTemplateUserByUnionId(wechatInfo.UnionId)
+
+		if unionErr == nil {
+			if unionErr == gorm.ErrRecordNotFound { //注册用户
+				isRegister = true
+			} else {
+				err = exception.New(exception.TemplateUserNotFound)
+				return
+			}
+		}
+		if isRegister {
+			err = userService.RegisterTemplateUser(&user)
+		} else { //修改微信小程序openid
+			err = userService.BindUserXcxOpenId(wxUser.Id, user.OpenId)
+		}
 	}
 	return
 }
+
 func GetAreaCodes() (list []userService.AreaCodeDTO, err error) {
 	list, err = userService.GetAreaCodes()
 	if err != nil {
@@ -273,3 +291,70 @@ func rd() *cache.RedisCache {
 	}
 	return redisCache
 }
+
+func BindXcxOpenId(userId int, openId string) (err error) {
+	err = userService.BindUserXcxOpenId(userId, openId)
+	return
+}
+
+// 绑定微信公众号
+func BindWxGzh(code string) (err error) {
+	//注册用户
+	wxUser, err := GetWxUserInfo(code)
+	if err != nil {
+		logger.Error("获取微信公众号用户信息失败" + err.Error())
+		err = exception.New(exception.TemplateUserNotFound)
+		return
+	}
+
+	if wxUser.ErrCode != 0 {
+		logger.Error("获取微信公众号用户信息失败" + wxUser.ErrMsg)
+		err = exception.New(exception.TemplateUserNotFound)
+		return
+	}
+
+	openId := wxUser.OpenId
+	wxUserDetail, er := GetWxUserDetail(openId)
+	if er != nil {
+		logger.Error("获取微信公众号用户详细信息失败" + wxUserDetail.ErrMsg)
+		err = exception.New(exception.TemplateUserNotFound)
+		return
+	}
+
+	unionId := wxUserDetail.UnionID
+
+	user, err := userService.GetTemplateUserByGzhOpenId(openId)
+	var isAdd bool
+	if err != nil {
+		if err == gorm.ErrRecordNotFound {
+			isAdd = true
+		} else {
+			err = exception.New(exception.TemplateUserNotFound)
+			return
+		}
+	}
+
+	if isAdd {
+		user.GzhOpenId = openId
+		user.UnionId = unionId
+		var isRegister bool
+
+		//判断unionid是否存在
+		wxUser, unionErr := userService.GetTemplateUserByUnionId(unionId)
+
+		if unionErr == nil {
+			if unionErr == gorm.ErrRecordNotFound { //注册用户
+				isRegister = true
+			} else {
+				err = exception.New(exception.TemplateUserNotFound)
+				return
+			}
+		}
+		if isRegister {
+			err = userService.RegisterTemplateUser(&user)
+		} else { //修改微信小程序openid
+			err = userService.BindUserXcxOpenId(wxUser.Id, openId)
+		}
+	}
+	return
+}

+ 166 - 0
service/auth/wechat.go

@@ -0,0 +1,166 @@
+package auth
+
+import (
+	"encoding/json"
+	"eta/eta_mini_ht_api/models"
+	"fmt"
+	"github.com/silenceper/wechat/v2"
+	"github.com/silenceper/wechat/v2/cache"
+	"gorm.io/gorm"
+	"io"
+	"net/http"
+	"time"
+
+	"github.com/silenceper/wechat/v2/credential"
+	"github.com/silenceper/wechat/v2/officialaccount"
+	"github.com/silenceper/wechat/v2/officialaccount/config"
+	"github.com/silenceper/wechat/v2/officialaccount/js"
+	"github.com/silenceper/wechat/v2/officialaccount/user"
+)
+
+var (
+	WxAppId     string
+	WxAppSecret string
+)
+
+// 海通公众号配置
+const (
+	HT_WX_APPID      = "wxf0dfb65c325fee66"
+	HT_WX_APP_SECRET = "4f2a6c4f9b0a9dee08d1b3b316f33228"
+)
+
+type WechatAccessToken struct {
+}
+
+var DefaultKey = "zcmRedis"
+
+// GetAccessToken 获取accessToken
+func (wechat WechatAccessToken) GetAccessToken() (accessToken string, err error) {
+	wxToken, err := models.GetWxTokenById()
+
+	var isRegister bool
+	if err != nil && err != gorm.ErrRecordNotFound {
+		if err == gorm.ErrRecordNotFound {
+			isRegister = true
+		} else {
+			return
+		}
+	}
+	if isRegister {
+		tmpAccessToken, expires, tmpErr := getTokenFromServer(HT_WX_APPID, HT_WX_APP_SECRET)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		token := new(models.WxToken)
+		token.AccessToken = tmpAccessToken
+		token.ExpiresIn = expires
+		err = models.RegisterWxToken(token)
+		if err != nil {
+			return "", err
+		}
+		accessToken = tmpAccessToken
+		return
+	}
+
+	//如果300s就要过期了,那么就去刷新accessToken
+	if wxToken.ExpiresIn < time.Now().Unix()+300 {
+		tmpAccessToken, expires, tmpErr := getTokenFromServer(HT_WX_APPID, HT_WX_APP_SECRET)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		expiresIn := time.Now().Unix() + expires - 600 //快过期前10分钟就刷新掉
+		models.UpdateWxToken(tmpAccessToken, expiresIn)
+		accessToken = tmpAccessToken
+	}
+	accessToken = wxToken.AccessToken
+	return
+}
+
+// getTokenFromServer 服务端获取accessToken
+func getTokenFromServer(appid, wxSecret string) (accessToken string, expires int64, err error) {
+	apiUrl := "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s"
+	resAccessToken, err := credential.GetTokenFromServer(fmt.Sprintf(apiUrl, appid, wxSecret))
+	if err != nil {
+		return
+	}
+
+	expires = resAccessToken.ExpiresIn
+	accessToken = resAccessToken.AccessToken
+	return
+}
+
+func GetWxChat() (officialAccount *officialaccount.OfficialAccount) {
+	wc := wechat.NewWechat()
+	memory := cache.NewMemory()
+	conf := &config.Config{
+		AppID:          HT_WX_APPID,
+		AppSecret:      HT_WX_APP_SECRET,
+		Token:          "",
+		EncodingAESKey: "",
+		Cache:          memory,
+	}
+	officialAccount = wc.GetOfficialAccount(conf)
+	wechatAccessToken := &WechatAccessToken{}
+	officialAccount.SetAccessTokenHandle(wechatAccessToken)
+	return
+}
+
+// GetUserInfo 获取微信用户详情
+func GetUserInfo(openid string) (userInfo *user.Info, err error) {
+	wechatClient := GetWxChat()
+	userClient := wechatClient.GetUser()
+	userInfo, err = userClient.GetUserInfo(openid)
+	return
+}
+
+// GetJsConfig 获取公众号jsConfig
+func GetJsConfig(signUrl string) (jsConf *js.Config, err error) {
+	wechatClient := GetWxChat()
+	j := wechatClient.GetJs()
+	jsConf, err = j.GetConfig(signUrl)
+	return
+}
+
+type WxUserInfo struct {
+	OpenId       string `json:"openid"`
+	AccessToken  string `json:"access_token"`
+	RefreshToken string `json:"refresh_token"`
+	Scope        string `json:"scope"`
+	ErrCode      int
+	ErrMsg       string
+}
+
+func GetWxUserInfo(code string) (info *WxUserInfo, err error) {
+	httpUrl := `https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code`
+
+	httpUrl = fmt.Sprintf(httpUrl, HT_WX_APPID, HT_WX_APP_SECRET, code)
+
+	client := http.Client{}
+	wxReq, err := http.NewRequest("GET", httpUrl, nil)
+	if err != nil {
+		return
+	}
+	response, err := client.Do(wxReq)
+	if err != nil {
+		return
+	}
+	defer response.Body.Close()
+	body, err := io.ReadAll(response.Body)
+	if err != nil {
+		return
+	}
+	if err = json.Unmarshal(body, &info); err != nil {
+		return
+	}
+	return
+}
+
+// GetUserInfo 获取微信用户详情
+func GetWxUserDetail(openid string) (userInfo *user.Info, err error) {
+	wechatClient := GetWxChat()
+	userClient := wechatClient.GetUser()
+	userInfo, err = userClient.GetUserInfo(openid)
+	return
+}