Browse Source

wechat: 微信小程序

Yi 1 year ago
parent
commit
2f409567a1

+ 4 - 0
backend/operation/system.proto

@@ -17,6 +17,10 @@ message Success {
   bool success = 1;
 }
 
+message WxOpenId {
+  string openid = 1;
+}
+
 // 用户角色
 message AddRoleRequest {
   uint32 id = 1;

+ 7 - 0
config/app.go

@@ -30,6 +30,13 @@ type AppConfig struct {
 	JwtSecret    string       `json:"jwtSecret" yaml:"jwt_secret"`
 
 	ExcelSetting ExcelSetting `json:"excelSetting" yaml:"excel_setting"`
+
+	WechatSetting WechatSetting `json:"wechatSetting" yaml:"wechat_setting"`
+}
+
+type WechatSetting struct {
+	Appid  string `yaml:"appid"`
+	Secret string `yaml:"secret"`
 }
 
 type ExcelSetting struct {

+ 5 - 1
config/app.test.yaml

@@ -21,4 +21,8 @@ jwt_secret: "sUd7j%UfJMt59ywh"
 
 excel_setting:
   sheet_name: "Sheet1"
-  height: 25.0
+  height: 25.0
+
+wechat_setting:
+  appid: wxd6e17d5709ce9c80
+  secret: 13b93e6c1cda8b6e46adb358a04f9f8f

+ 2 - 0
dep/dep.go

@@ -5,6 +5,7 @@ import (
 	"kpt-tmr-group/module/backend"
 	"kpt-tmr-group/pkg/di"
 	"kpt-tmr-group/service/sso"
+	"kpt-tmr-group/service/wechat"
 	"kpt-tmr-group/store/kptstore"
 )
 
@@ -25,5 +26,6 @@ func Options() []di.HubOption {
 		kptstore.Module,
 		backend.Module,
 		sso.Module,
+		wechat.Module,
 	}
 }

+ 15 - 0
http/handler/system/user.go

@@ -36,6 +36,21 @@ func Auth(c *gin.Context) {
 	ginutil.JSONResp(c, res)
 }
 
+func GetWxAppletOpenId(c *gin.Context) {
+	jsCode := c.Param("js_code")
+	if err := valid.Validate(jsCode, valid.Required, valid.Length(1, 100)); err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+	res, err := middleware.BackendOperation(c).OpsService.GetOpenId(c, jsCode)
+	if err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+
+	ginutil.JSONResp(c, res)
+}
+
 // AddSystemUser 创建系统用户
 func AddSystemUser(c *gin.Context) {
 	var req operationPb.AddSystemUser

+ 1 - 0
http/route/app_api.go

@@ -22,6 +22,7 @@ func AppAPI(opts ...func(engine *gin.Engine)) func(s *gin.Engine) {
 		s.GET("/check", handler.Health)
 
 		s.POST("/auth", system.Auth)
+		s.GET("/wx_applet/openid/:js_code", system.GetWxAppletOpenId)
 
 		// system API 组
 		// 系统用户

+ 9 - 0
model/wechat.go

@@ -0,0 +1,9 @@
+package model
+
+type JsCode struct {
+	SessionKey string `json:"session_key"`
+	UnionId    string `json:"unionid"`
+	ErrMsg     string `json:"errmsg"`
+	OpenId     string `json:"openid"`
+	ErrCode    int32  `json:"errcode"`
+}

+ 7 - 0
module/backend/interface.go

@@ -7,6 +7,7 @@ import (
 	"kpt-tmr-group/config"
 	"kpt-tmr-group/pkg/di"
 	operationPb "kpt-tmr-group/proto/go/backend/operation"
+	"kpt-tmr-group/service/wechat"
 	"kpt-tmr-group/store/kptstore"
 
 	"go.uber.org/dig"
@@ -27,6 +28,7 @@ type StoreEntry struct {
 	//SSO *sso.Cache
 	// AsynqClient asynqsvc.Client
 	// Cache *redis.Client
+	WxClient *wechat.ClientService
 }
 
 func NewStore(store StoreEntry) KptService {
@@ -36,6 +38,7 @@ func NewStore(store StoreEntry) KptService {
 type KptService interface {
 	Operation
 	SystemOperation
+	WxAppletService
 }
 
 type Operation interface {
@@ -115,3 +118,7 @@ type SystemOperation interface {
 	// SearchMobileList 移动端
 	SearchMobileList(ctx context.Context, req *operationPb.SearchMobileRequest) (*operationPb.SearchMobileResponse, error)
 }
+
+type WxAppletService interface {
+	GetOpenId(ctx context.Context, jsCode string) (*operationPb.WxOpenId, error)
+}

+ 34 - 0
module/backend/wx_applet_service.go

@@ -0,0 +1,34 @@
+package backend
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"kpt-tmr-group/model"
+	"kpt-tmr-group/pkg/logger/zaplog"
+	"kpt-tmr-group/pkg/xerr"
+	operationPb "kpt-tmr-group/proto/go/backend/operation"
+
+	"go.uber.org/zap"
+)
+
+const (
+	GRANT_TYPE = "authorization_code"
+	OPENID_URL = "https://api.weixin.qq.com/sns/jscode2session"
+)
+
+func (s *StoreEntry) GetOpenId(ctx context.Context, jsCode string) (*operationPb.WxOpenId, error) {
+	url := fmt.Sprintf("%s?appid=%s&secret=%s&js_code=%s&grant_type=%s", OPENID_URL, s.WxClient.AppID, s.WxClient.Secret, jsCode, GRANT_TYPE)
+	res, err := s.WxClient.DoGet(url)
+	if err != nil {
+		zaplog.Error("GetOpenId", zap.Any("DoGet", err), zap.String("url", url))
+		return nil, xerr.WithStack(err)
+	}
+	data := &model.JsCode{}
+	if err = json.Unmarshal(res, data); err != nil {
+		zaplog.Error("GetOpenId", zap.Any("Unmarshal", err), zap.String("url", url))
+		return nil, xerr.WithStack(err)
+	}
+	zaplog.Info("GetOpenId", zap.Any("ok", data))
+	return &operationPb.WxOpenId{Openid: data.OpenId}, nil
+}

File diff suppressed because it is too large
+ 362 - 313
proto/go/backend/operation/system.pb.go


+ 80 - 0
service/wechat/http.go

@@ -0,0 +1,80 @@
+package wechat
+
+import (
+	"bytes"
+	"encoding/json"
+	"io/ioutil"
+	"kpt-tmr-group/pkg/logger/zaplog"
+	"kpt-tmr-group/pkg/xerr"
+	"net/http"
+	"time"
+
+	"go.uber.org/zap"
+)
+
+type ClientService struct {
+	AppID      string
+	Secret     string
+	authClient *http.Client
+}
+
+func NewClientService(appid, secret string) *ClientService {
+	return &ClientService{
+		AppID:  appid,
+		Secret: secret,
+		authClient: &http.Client{
+			/*Transport: &http.Transport{
+				MaxIdleConnsPerHost: 50,
+			},*/
+			Timeout: time.Duration(5) * time.Second,
+		},
+	}
+}
+
+func (c *ClientService) doRequest(req *http.Request) ([]byte, error) {
+	resp, err := c.authClient.Do(req)
+	if err != nil {
+		zaplog.Error("ClientService", zap.Any("authClient.Do", err))
+		return nil, xerr.WithStack(err)
+	}
+	b, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		zaplog.Error("ClientService", zap.Any("ioutil.ReadAll", err))
+		return nil, xerr.WithStack(err)
+	}
+	if resp.StatusCode != http.StatusOK {
+		if len(b) > 0 {
+			return nil, xerr.Customf("err:%v,body:%s", err, string(b))
+		} else {
+			return nil, xerr.Customf("err:%v", err)
+		}
+	}
+	return b, nil
+}
+
+func (c *ClientService) DoGet(url string) ([]byte, error) {
+	req, err := http.NewRequest(http.MethodGet, url, nil)
+	if err != nil {
+		zaplog.Error("ClientService", zap.Any("DoGet", err))
+		return nil, err
+	}
+	req.Header.Add("Accept", "application/json")
+	req.Header.Add("Content-Type", "application/json")
+	return c.doRequest(req)
+}
+
+func (c *ClientService) DoPost(url string, body interface{}) ([]byte, error) {
+	b, err := json.Marshal(body)
+	if err != nil {
+		zaplog.Error("ClientService", zap.Any("DoPost-Marshal", err))
+		return nil, xerr.WithStack(err)
+	}
+	req, err := http.NewRequest(http.MethodPost, url, bytes.NewReader(b))
+	if err != nil {
+		zaplog.Error("ClientService", zap.Any("NewRequest", err))
+		return nil, xerr.WithStack(err)
+	}
+	req.Header.Add("Accept", "application/json")
+	req.Header.Add("Content-Type", "application/json")
+	return c.doRequest(req)
+}

+ 19 - 0
service/wechat/interface.go

@@ -0,0 +1,19 @@
+package wechat
+
+import (
+	"kpt-tmr-group/config"
+	"kpt-tmr-group/pkg/di"
+	"net/http"
+)
+
+type Service interface {
+	doRequest(req *http.Request) ([]byte, error)
+	DoGet(url string) ([]byte, error)
+	DoPost(url string, body interface{}) ([]byte, error)
+}
+
+var Module = di.Provide(NewService)
+
+func NewService(cfg *config.AppConfig) *ClientService {
+	return NewClientService(cfg.WechatSetting.Appid, cfg.WechatSetting.Secret)
+}

Some files were not shown because too many files changed in this diff