作者 yangfu

二维码

... ... @@ -20,11 +20,6 @@ func MiniQrcodeInviteHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
l := common.NewMiniQrcodeInviteLogic(r.Context(), svcCtx)
resp, err := l.MiniQrcodeInvite(&req)
if err != nil {
result.HttpResult(r, w, resp, err)
}
w.Header().Set("Content-Disposition", "attachment; filename="+"qrcode.png")
w.Header().Set("Content-Type", "application/octet-stream")
w.Write(resp)
}
}
... ...
... ... @@ -2,8 +2,12 @@ package common
import (
"context"
"encoding/json"
"fmt"
"github.com/samber/lo"
"github.com/silenceper/wechat/v2/miniprogram/qrcode"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/gateway/openlib"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/tool"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/xerr"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
... ... @@ -26,8 +30,26 @@ func NewMiniQrcodeInviteLogic(ctx context.Context, svcCtx *svc.ServiceContext) *
}
}
func (l *MiniQrcodeInviteLogic) MiniQrcodeInvite(req *types.MiniQrCodeRequest) (resp []byte, err error) {
q := l.svcCtx.MiniProgram.GetQRCode()
func (l *MiniQrcodeInviteLogic) MiniQrcodeInvite(req *types.MiniQrCodeRequest) (resp interface{}, err error) {
var (
q = l.svcCtx.MiniProgram.GetQRCode()
cacheData = fmt.Sprintf("%s?%s", req.Page, req.Scene)
cacheKey = fmt.Sprintf("%s:qrcode:%s", l.svcCtx.Config.Name, tool.Md5ByString(cacheData))
ok bool
qrcodeCache QrcodeCache
)
// 从缓存获取
if ok, err = l.svcCtx.Redis.ExistsCtx(l.ctx, cacheKey); ok && err == nil {
tmpCacheData, _ := l.svcCtx.Redis.Get(cacheKey)
if err = json.Unmarshal([]byte(tmpCacheData), &qrcodeCache); err == nil {
if qrcodeCache.CacheData == cacheData {
return MiniQrCodeResponse{
Path: qrcodeCache.QrcodeUrl,
}, nil
}
}
}
var data []byte
data, err = q.GetWXACodeUnlimit(qrcode.QRCoder{
Page: req.Page,
... ... @@ -39,5 +61,34 @@ func (l *MiniQrcodeInviteLogic) MiniQrcodeInvite(req *types.MiniQrCodeRequest) (
if err != nil {
return nil, xerr.NewErr(err)
}
return data, nil
var result *openlib.DataPutFile
result, err = l.svcCtx.OpenApiService.PutFile(l.ctx, openlib.RequestPutFile{
File: data,
})
if err != nil {
return nil, xerr.NewErr(err)
}
if result == nil || len(*result) == 0 || (*result)[0].Path == "" {
return nil, xerr.NewErr(fmt.Errorf("上传失败"))
}
// 设置缓存
jsonData, err := json.Marshal(QrcodeCache{
CacheData: cacheData,
QrcodeUrl: (*result)[0].Path,
})
l.svcCtx.Redis.Set(cacheKey, string(jsonData))
return MiniQrCodeResponse{
Path: (*result)[0].Path,
}, err
}
type MiniQrCodeResponse struct {
Path string `json:"path"`
}
type QrcodeCache struct {
CacheData string
QrcodeUrl string
}
... ...
... ... @@ -14,6 +14,7 @@ import (
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/gateway"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/gateway/authlib"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/gateway/openlib"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/gateway/smslib"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/cache"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/database"
... ... @@ -47,6 +48,7 @@ type ServiceContext struct {
ApiAuthService authlib.ApiAuthService
SmsService smslib.SMSService
OpenApiService openlib.OpenApiService
MiniProgram *miniprogram.MiniProgram
... ... @@ -74,6 +76,7 @@ func NewServiceContext(c config.Config) *ServiceContext {
Redis: redis,
ApiAuthService: apiAuth,
SmsService: smslib.SMSService{Service: gateway.NewService("短信服务", "https://sms.fjmaimaimai.com:9897", time.Second*5)},
OpenApiService: openlib.OpenApiService{Service: gateway.NewService("开发接口服务", "https://mmm-open-api-test.fjmaimaimai.com", time.Second*5)},
LoginStatusCheck: middleware.NewLoginStatusCheckMiddleware(apiAuth).Handle,
LogRequest: middleware.NewLogRequestMiddleware(c.LogRequest).Handle,
MiniProgram: miniProgram,
... ...
... ... @@ -14,7 +14,7 @@ import (
type Service struct {
Timeout time.Duration
host string
Host string
Interceptor func(msg string)
ServiceName string
service httpc.Service
... ... @@ -25,7 +25,7 @@ func NewService(name string, host string, timeout time.Duration, opts ...httpc.O
//client.Timeout = timeout
service := Service{
host: host,
Host: host,
service: httpc.NewServiceWithClient(name, client, opts...),
}
return service
... ... @@ -37,7 +37,7 @@ func (gateway Service) Do(ctx context.Context, url string, method string, val in
begin = time.Now()
body []byte
)
response, err := gateway.service.Do(ctx, method, gateway.host+url, val)
response, err := gateway.service.Do(ctx, method, gateway.Host+url, val)
defer func() {
jsonParam, _ := json.Marshal(val)
jsonData, _ := json.Marshal(result)
... ... @@ -45,7 +45,7 @@ func (gateway Service) Do(ctx context.Context, url string, method string, val in
result = err.Error()
}
if gateway.Interceptor != nil {
gateway.Interceptor(fmt.Sprintf("【网关】%v | %v%v | %v : %v \n-->> %v \n<<-- %v", time.Since(begin), gateway.host, url, strings.ToUpper(method),
gateway.Interceptor(fmt.Sprintf("【网关】%v | %v%v | %v : %v \n-->> %v \n<<-- %v", time.Since(begin), gateway.Host, url, strings.ToUpper(method),
result,
string(jsonParam),
string(jsonData),
... ... @@ -84,6 +84,62 @@ func (gateway Service) Do(ctx context.Context, url string, method string, val in
return nil
}
func (gateway Service) HandlerResponse(ctx context.Context, request *http.Request, response *http.Response, val, result interface{}) error {
var (
baseResponse = Response{}
begin = time.Now()
body []byte
err error
)
defer func() {
jsonParam, _ := json.Marshal(val)
jsonData, _ := json.Marshal(result)
if err != nil {
result = err.Error()
}
if gateway.Interceptor != nil {
gateway.Interceptor(fmt.Sprintf("【网关】%v | %v%v | %v : %v \n-->> %v \n<<-- %v", time.Since(begin), gateway.Host, request.URL.Path, request.Method,
result,
string(jsonParam),
string(jsonData),
))
}
}()
if err != nil {
return err
}
if response.StatusCode != http.StatusOK {
return HttpError{
Base: Response{
Code: response.StatusCode,
Msg: response.Status,
},
}
}
body, err = Bytes(response)
if err != nil {
return err
}
if err = json.Unmarshal(body, &baseResponse); err != nil {
return err
}
if baseResponse.Code != 0 {
return HttpError{
Base: Response{
Code: baseResponse.Code,
Msg: baseResponse.Msg,
},
}
}
if err = mapping.UnmarshalJsonBytes(baseResponse.Data, result); err != nil {
return err
}
return nil
}
func (gateway Service) GetService() httpc.Service {
return gateway.service
}
func Bytes(resp *http.Response) ([]byte, error) {
var body []byte
if resp.Body == nil {
... ...
package openlib
import (
"bytes"
"context"
"encoding/json"
"github.com/zeromicro/go-zero/core/mapping"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/gateway"
"io"
"io/ioutil"
"mime/multipart"
"net/http"
"net/url"
)
type OpenApiService struct {
gateway.Service
}
func (svc *OpenApiService) PutFile(ctx context.Context, request RequestPutFile) (*DataPutFile, error) {
var result DataPutFile
r, _ := buildRequest(ctx, http.MethodPost, svc.Host+"/v1/vod/putObject", request)
response, err := svc.GetService().DoRequest(r)
if err != nil {
return nil, err
}
if err := svc.HandlerResponse(ctx, r, response, nil, &result); err != nil {
return nil, err
}
return &result, nil
}
func buildRequest(ctx context.Context, method, tmpUrl string, data any) (*http.Request, error) {
u, err := url.Parse(tmpUrl)
if err != nil {
return nil, err
}
var val map[string]map[string]any
if data != nil {
val, err = mapping.Marshal(data)
if err != nil {
return nil, err
}
}
var reader io.Reader
jsonVars, hasJsonBody := val["json"]
if hasJsonBody {
var buf bytes.Buffer
enc := json.NewEncoder(&buf)
if err := enc.Encode(jsonVars); err != nil {
return nil, err
}
reader = &buf
}
req, err := http.NewRequestWithContext(ctx, method, u.String(), reader)
if err != nil {
return nil, err
}
fileVars, hasFile := val["file"]
if hasFile {
if err = fillFile(req, fileVars); err != nil {
return nil, err
}
}
if hasJsonBody {
req.Header.Set("Content-Type", "application/json; charset=utf-8")
}
return req, nil
}
func fillFile(req *http.Request, val map[string]any) error {
if len(val) == 0 {
return nil
}
pr, pw := io.Pipe()
bodyWriter := multipart.NewWriter(pw)
go func() {
for k, v := range val {
fileWriter, err := bodyWriter.CreateFormFile(k, k)
if err != nil {
return
}
//fh, err := os.Open(v.(string))
//if err != nil {
// return err
//}
fh := bytes.NewBuffer(v.([]byte))
// iocopy
_, err = io.Copy(fileWriter, fh)
if err != nil {
return
}
}
bodyWriter.Close()
pw.Close()
}()
req.Header.Set("Content-Type", bodyWriter.FormDataContentType())
req.Body = ioutil.NopCloser(pr)
req.Header.Set("Transfer-Encoding", "chunked")
return nil
}
... ...
package openlib
type (
RequestPutFile struct {
File []byte `file:"file.png"`
}
DataPutFile []*DataUploadItem
DataUploadItem struct {
Host string `json:"host"`
Key string `json:"key"`
Path string `json:"path"`
FileName string `json:"fileName"`
}
)
... ...