作者 yangfu

二维码

@@ -20,11 +20,6 @@ func MiniQrcodeInviteHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { @@ -20,11 +20,6 @@ func MiniQrcodeInviteHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
20 20
21 l := common.NewMiniQrcodeInviteLogic(r.Context(), svcCtx) 21 l := common.NewMiniQrcodeInviteLogic(r.Context(), svcCtx)
22 resp, err := l.MiniQrcodeInvite(&req) 22 resp, err := l.MiniQrcodeInvite(&req)
23 - if err != nil {  
24 result.HttpResult(r, w, resp, err) 23 result.HttpResult(r, w, resp, err)
25 } 24 }
26 - w.Header().Set("Content-Disposition", "attachment; filename="+"qrcode.png")  
27 - w.Header().Set("Content-Type", "application/octet-stream")  
28 - w.Write(resp)  
29 - }  
30 } 25 }
@@ -2,8 +2,12 @@ package common @@ -2,8 +2,12 @@ package common
2 2
3 import ( 3 import (
4 "context" 4 "context"
  5 + "encoding/json"
  6 + "fmt"
5 "github.com/samber/lo" 7 "github.com/samber/lo"
6 "github.com/silenceper/wechat/v2/miniprogram/qrcode" 8 "github.com/silenceper/wechat/v2/miniprogram/qrcode"
  9 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/gateway/openlib"
  10 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/tool"
7 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/xerr" 11 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/xerr"
8 12
9 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc" 13 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
@@ -26,8 +30,26 @@ func NewMiniQrcodeInviteLogic(ctx context.Context, svcCtx *svc.ServiceContext) * @@ -26,8 +30,26 @@ func NewMiniQrcodeInviteLogic(ctx context.Context, svcCtx *svc.ServiceContext) *
26 } 30 }
27 } 31 }
28 32
29 -func (l *MiniQrcodeInviteLogic) MiniQrcodeInvite(req *types.MiniQrCodeRequest) (resp []byte, err error) {  
30 - q := l.svcCtx.MiniProgram.GetQRCode() 33 +func (l *MiniQrcodeInviteLogic) MiniQrcodeInvite(req *types.MiniQrCodeRequest) (resp interface{}, err error) {
  34 + var (
  35 + q = l.svcCtx.MiniProgram.GetQRCode()
  36 + cacheData = fmt.Sprintf("%s?%s", req.Page, req.Scene)
  37 + cacheKey = fmt.Sprintf("%s:qrcode:%s", l.svcCtx.Config.Name, tool.Md5ByString(cacheData))
  38 + ok bool
  39 + qrcodeCache QrcodeCache
  40 + )
  41 + // 从缓存获取
  42 + if ok, err = l.svcCtx.Redis.ExistsCtx(l.ctx, cacheKey); ok && err == nil {
  43 + tmpCacheData, _ := l.svcCtx.Redis.Get(cacheKey)
  44 + if err = json.Unmarshal([]byte(tmpCacheData), &qrcodeCache); err == nil {
  45 + if qrcodeCache.CacheData == cacheData {
  46 + return MiniQrCodeResponse{
  47 + Path: qrcodeCache.QrcodeUrl,
  48 + }, nil
  49 + }
  50 + }
  51 + }
  52 +
31 var data []byte 53 var data []byte
32 data, err = q.GetWXACodeUnlimit(qrcode.QRCoder{ 54 data, err = q.GetWXACodeUnlimit(qrcode.QRCoder{
33 Page: req.Page, 55 Page: req.Page,
@@ -39,5 +61,34 @@ func (l *MiniQrcodeInviteLogic) MiniQrcodeInvite(req *types.MiniQrCodeRequest) ( @@ -39,5 +61,34 @@ func (l *MiniQrcodeInviteLogic) MiniQrcodeInvite(req *types.MiniQrCodeRequest) (
39 if err != nil { 61 if err != nil {
40 return nil, xerr.NewErr(err) 62 return nil, xerr.NewErr(err)
41 } 63 }
42 - return data, nil 64 + var result *openlib.DataPutFile
  65 + result, err = l.svcCtx.OpenApiService.PutFile(l.ctx, openlib.RequestPutFile{
  66 + File: data,
  67 + })
  68 + if err != nil {
  69 + return nil, xerr.NewErr(err)
  70 + }
  71 + if result == nil || len(*result) == 0 || (*result)[0].Path == "" {
  72 + return nil, xerr.NewErr(fmt.Errorf("上传失败"))
  73 + }
  74 +
  75 + // 设置缓存
  76 + jsonData, err := json.Marshal(QrcodeCache{
  77 + CacheData: cacheData,
  78 + QrcodeUrl: (*result)[0].Path,
  79 + })
  80 + l.svcCtx.Redis.Set(cacheKey, string(jsonData))
  81 +
  82 + return MiniQrCodeResponse{
  83 + Path: (*result)[0].Path,
  84 + }, err
  85 +}
  86 +
  87 +type MiniQrCodeResponse struct {
  88 + Path string `json:"path"`
  89 +}
  90 +
  91 +type QrcodeCache struct {
  92 + CacheData string
  93 + QrcodeUrl string
43 } 94 }
@@ -14,6 +14,7 @@ import ( @@ -14,6 +14,7 @@ import (
14 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain" 14 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
15 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/gateway" 15 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/gateway"
16 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/gateway/authlib" 16 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/gateway/authlib"
  17 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/gateway/openlib"
17 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/gateway/smslib" 18 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/gateway/smslib"
18 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/cache" 19 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/cache"
19 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/database" 20 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/database"
@@ -47,6 +48,7 @@ type ServiceContext struct { @@ -47,6 +48,7 @@ type ServiceContext struct {
47 48
48 ApiAuthService authlib.ApiAuthService 49 ApiAuthService authlib.ApiAuthService
49 SmsService smslib.SMSService 50 SmsService smslib.SMSService
  51 + OpenApiService openlib.OpenApiService
50 52
51 MiniProgram *miniprogram.MiniProgram 53 MiniProgram *miniprogram.MiniProgram
52 54
@@ -74,6 +76,7 @@ func NewServiceContext(c config.Config) *ServiceContext { @@ -74,6 +76,7 @@ func NewServiceContext(c config.Config) *ServiceContext {
74 Redis: redis, 76 Redis: redis,
75 ApiAuthService: apiAuth, 77 ApiAuthService: apiAuth,
76 SmsService: smslib.SMSService{Service: gateway.NewService("短信服务", "https://sms.fjmaimaimai.com:9897", time.Second*5)}, 78 SmsService: smslib.SMSService{Service: gateway.NewService("短信服务", "https://sms.fjmaimaimai.com:9897", time.Second*5)},
  79 + OpenApiService: openlib.OpenApiService{Service: gateway.NewService("开发接口服务", "https://mmm-open-api-test.fjmaimaimai.com", time.Second*5)},
77 LoginStatusCheck: middleware.NewLoginStatusCheckMiddleware(apiAuth).Handle, 80 LoginStatusCheck: middleware.NewLoginStatusCheckMiddleware(apiAuth).Handle,
78 LogRequest: middleware.NewLogRequestMiddleware(c.LogRequest).Handle, 81 LogRequest: middleware.NewLogRequestMiddleware(c.LogRequest).Handle,
79 MiniProgram: miniProgram, 82 MiniProgram: miniProgram,
@@ -14,7 +14,7 @@ import ( @@ -14,7 +14,7 @@ import (
14 14
15 type Service struct { 15 type Service struct {
16 Timeout time.Duration 16 Timeout time.Duration
17 - host string 17 + Host string
18 Interceptor func(msg string) 18 Interceptor func(msg string)
19 ServiceName string 19 ServiceName string
20 service httpc.Service 20 service httpc.Service
@@ -25,7 +25,7 @@ func NewService(name string, host string, timeout time.Duration, opts ...httpc.O @@ -25,7 +25,7 @@ func NewService(name string, host string, timeout time.Duration, opts ...httpc.O
25 //client.Timeout = timeout 25 //client.Timeout = timeout
26 26
27 service := Service{ 27 service := Service{
28 - host: host, 28 + Host: host,
29 service: httpc.NewServiceWithClient(name, client, opts...), 29 service: httpc.NewServiceWithClient(name, client, opts...),
30 } 30 }
31 return service 31 return service
@@ -37,7 +37,7 @@ func (gateway Service) Do(ctx context.Context, url string, method string, val in @@ -37,7 +37,7 @@ func (gateway Service) Do(ctx context.Context, url string, method string, val in
37 begin = time.Now() 37 begin = time.Now()
38 body []byte 38 body []byte
39 ) 39 )
40 - response, err := gateway.service.Do(ctx, method, gateway.host+url, val) 40 + response, err := gateway.service.Do(ctx, method, gateway.Host+url, val)
41 defer func() { 41 defer func() {
42 jsonParam, _ := json.Marshal(val) 42 jsonParam, _ := json.Marshal(val)
43 jsonData, _ := json.Marshal(result) 43 jsonData, _ := json.Marshal(result)
@@ -45,7 +45,7 @@ func (gateway Service) Do(ctx context.Context, url string, method string, val in @@ -45,7 +45,7 @@ func (gateway Service) Do(ctx context.Context, url string, method string, val in
45 result = err.Error() 45 result = err.Error()
46 } 46 }
47 if gateway.Interceptor != nil { 47 if gateway.Interceptor != nil {
48 - gateway.Interceptor(fmt.Sprintf("【网关】%v | %v%v | %v : %v \n-->> %v \n<<-- %v", time.Since(begin), gateway.host, url, strings.ToUpper(method), 48 + gateway.Interceptor(fmt.Sprintf("【网关】%v | %v%v | %v : %v \n-->> %v \n<<-- %v", time.Since(begin), gateway.Host, url, strings.ToUpper(method),
49 result, 49 result,
50 string(jsonParam), 50 string(jsonParam),
51 string(jsonData), 51 string(jsonData),
@@ -84,6 +84,62 @@ func (gateway Service) Do(ctx context.Context, url string, method string, val in @@ -84,6 +84,62 @@ func (gateway Service) Do(ctx context.Context, url string, method string, val in
84 return nil 84 return nil
85 } 85 }
86 86
  87 +func (gateway Service) HandlerResponse(ctx context.Context, request *http.Request, response *http.Response, val, result interface{}) error {
  88 + var (
  89 + baseResponse = Response{}
  90 + begin = time.Now()
  91 + body []byte
  92 + err error
  93 + )
  94 + defer func() {
  95 + jsonParam, _ := json.Marshal(val)
  96 + jsonData, _ := json.Marshal(result)
  97 + if err != nil {
  98 + result = err.Error()
  99 + }
  100 + if gateway.Interceptor != nil {
  101 + gateway.Interceptor(fmt.Sprintf("【网关】%v | %v%v | %v : %v \n-->> %v \n<<-- %v", time.Since(begin), gateway.Host, request.URL.Path, request.Method,
  102 + result,
  103 + string(jsonParam),
  104 + string(jsonData),
  105 + ))
  106 + }
  107 + }()
  108 + if err != nil {
  109 + return err
  110 + }
  111 + if response.StatusCode != http.StatusOK {
  112 + return HttpError{
  113 + Base: Response{
  114 + Code: response.StatusCode,
  115 + Msg: response.Status,
  116 + },
  117 + }
  118 + }
  119 + body, err = Bytes(response)
  120 + if err != nil {
  121 + return err
  122 + }
  123 + if err = json.Unmarshal(body, &baseResponse); err != nil {
  124 + return err
  125 + }
  126 + if baseResponse.Code != 0 {
  127 + return HttpError{
  128 + Base: Response{
  129 + Code: baseResponse.Code,
  130 + Msg: baseResponse.Msg,
  131 + },
  132 + }
  133 + }
  134 + if err = mapping.UnmarshalJsonBytes(baseResponse.Data, result); err != nil {
  135 + return err
  136 + }
  137 + return nil
  138 +}
  139 +
  140 +func (gateway Service) GetService() httpc.Service {
  141 + return gateway.service
  142 +}
87 func Bytes(resp *http.Response) ([]byte, error) { 143 func Bytes(resp *http.Response) ([]byte, error) {
88 var body []byte 144 var body []byte
89 if resp.Body == nil { 145 if resp.Body == nil {
  1 +package openlib
  2 +
  3 +import (
  4 + "bytes"
  5 + "context"
  6 + "encoding/json"
  7 + "github.com/zeromicro/go-zero/core/mapping"
  8 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/gateway"
  9 + "io"
  10 + "io/ioutil"
  11 + "mime/multipart"
  12 + "net/http"
  13 + "net/url"
  14 +)
  15 +
  16 +type OpenApiService struct {
  17 + gateway.Service
  18 +}
  19 +
  20 +func (svc *OpenApiService) PutFile(ctx context.Context, request RequestPutFile) (*DataPutFile, error) {
  21 + var result DataPutFile
  22 + r, _ := buildRequest(ctx, http.MethodPost, svc.Host+"/v1/vod/putObject", request)
  23 + response, err := svc.GetService().DoRequest(r)
  24 + if err != nil {
  25 + return nil, err
  26 + }
  27 + if err := svc.HandlerResponse(ctx, r, response, nil, &result); err != nil {
  28 + return nil, err
  29 + }
  30 + return &result, nil
  31 +}
  32 +
  33 +func buildRequest(ctx context.Context, method, tmpUrl string, data any) (*http.Request, error) {
  34 + u, err := url.Parse(tmpUrl)
  35 + if err != nil {
  36 + return nil, err
  37 + }
  38 +
  39 + var val map[string]map[string]any
  40 + if data != nil {
  41 + val, err = mapping.Marshal(data)
  42 + if err != nil {
  43 + return nil, err
  44 + }
  45 + }
  46 +
  47 + var reader io.Reader
  48 + jsonVars, hasJsonBody := val["json"]
  49 + if hasJsonBody {
  50 + var buf bytes.Buffer
  51 + enc := json.NewEncoder(&buf)
  52 + if err := enc.Encode(jsonVars); err != nil {
  53 + return nil, err
  54 + }
  55 +
  56 + reader = &buf
  57 + }
  58 +
  59 + req, err := http.NewRequestWithContext(ctx, method, u.String(), reader)
  60 + if err != nil {
  61 + return nil, err
  62 + }
  63 + fileVars, hasFile := val["file"]
  64 + if hasFile {
  65 + if err = fillFile(req, fileVars); err != nil {
  66 + return nil, err
  67 + }
  68 + }
  69 + if hasJsonBody {
  70 + req.Header.Set("Content-Type", "application/json; charset=utf-8")
  71 + }
  72 +
  73 + return req, nil
  74 +}
  75 +
  76 +func fillFile(req *http.Request, val map[string]any) error {
  77 + if len(val) == 0 {
  78 + return nil
  79 + }
  80 + pr, pw := io.Pipe()
  81 + bodyWriter := multipart.NewWriter(pw)
  82 + go func() {
  83 + for k, v := range val {
  84 + fileWriter, err := bodyWriter.CreateFormFile(k, k)
  85 + if err != nil {
  86 + return
  87 + }
  88 + //fh, err := os.Open(v.(string))
  89 + //if err != nil {
  90 + // return err
  91 + //}
  92 + fh := bytes.NewBuffer(v.([]byte))
  93 + // iocopy
  94 + _, err = io.Copy(fileWriter, fh)
  95 + if err != nil {
  96 + return
  97 + }
  98 + }
  99 + bodyWriter.Close()
  100 + pw.Close()
  101 + }()
  102 + req.Header.Set("Content-Type", bodyWriter.FormDataContentType())
  103 + req.Body = ioutil.NopCloser(pr)
  104 + req.Header.Set("Transfer-Encoding", "chunked")
  105 + return nil
  106 +}
  1 +package openlib
  2 +
  3 +type (
  4 + RequestPutFile struct {
  5 + File []byte `file:"file.png"`
  6 + }
  7 + DataPutFile []*DataUploadItem
  8 +
  9 + DataUploadItem struct {
  10 + Host string `json:"host"`
  11 + Key string `json:"key"`
  12 + Path string `json:"path"`
  13 + FileName string `json:"fileName"`
  14 + }
  15 +)