package logic import ( "context" "fmt" "lone-services/pkg/redis" "lone-services/pkg/utils" "lone-services/pkg/validate" "lone-services/pkg/wechat/qrcode" pkgws "lone-services/pkg/ws" chore "lone-services/rpc/chore/pb" user "lone-services/rpc/user/pb" userconfig "lone-services/services/user/internal/config" "lone-services/services/user/internal/svc" "lone-services/services/user/validator" "github.com/google/uuid" jsoniter "github.com/json-iterator/go" "github.com/zeromicro/go-zero/core/logx" ) type GenerateQrcodeLogic struct { ctx context.Context svcCtx *svc.ServiceContext logx.Logger } func NewGenerateQrcodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GenerateQrcodeLogic { return &GenerateQrcodeLogic{ ctx: ctx, svcCtx: svcCtx, Logger: logx.WithContext(ctx), } } func (l *GenerateQrcodeLogic) GenerateQrcode(in *user.GenerateQrcodeReq) (*user.Response, error) { var req validator.GenerateQrcodeValidator if msg := validate.ValidateFromProto(in, &req); msg != utils.StringEmpty { return outResponse(utils.ErrorParams, msg), nil } if _, err := loadEnabledClient(req.ClientCode); err != nil { l.Errorf("generate qrcode load client: %v", err) return outResponse(utils.ErrorParams, "端配置不存在或已禁用"), nil } wxCfg, err := userconfig.LoadWechatConfig(req.ClientCode) if err != nil { l.Errorf("generate qrcode wechat config: %v", err) return outResponse(utils.Fail, "微信配置缺失"), nil } sessionID, err := l.createSession(req.ClientCode) if err != nil { l.Errorf("generate qrcode session: %v", err) return outResponse(utils.Fail, "create qrcode session failed"), nil } img, err := wxCfg.NewQrcodeClient().CreateWxaCode(l.ctx, &qrcode.WxaCodeRequest{ Path: qrcode.BuildPath(wxCfg.Page, map[string]string{ "session_id": sessionID, }), Width: wxCfg.Width, EnvVersion: wxCfg.EnvVersion, AutoColor: false, LineColor: &qrcode.LineColor{R: 255, G: 255, B: 255}, IsHyaline: true, }) if err != nil { l.Errorf("generate qrcode wechat: %v", err) return outResponse(utils.Fail, err.Error()), nil } qrURL, err := l.uploadQrcode(img) if err != nil { l.Errorf("generate qrcode upload: %v", err) return outResponse(utils.Fail, "upload qrcode failed"), nil } return okResponse(map[string]string{ "session_id": sessionID, "qrcode": qrURL, }), nil } func (l *GenerateQrcodeLogic) createSession(clientCode string) (string, error) { if redis.Client == nil { return "", fmt.Errorf("redis not initialized") } sessionID := uuid.New().String() payload, err := jsoniter.MarshalToString(pkgws.Session{ Status: pkgws.StatusPending, ClientCode: clientCode, }) if err != nil { return "", err } key := pkgws.RedisKeyQRSession + sessionID if err := redis.Client.Set(l.ctx, key, payload, pkgws.SessionTTL).Err(); err != nil { return "", err } return sessionID, nil } func (l *GenerateQrcodeLogic) uploadQrcode(content []byte) (string, error) { if l.svcCtx.ChoreSvcName == utils.StringEmpty { return "", fmt.Errorf("chore service name empty") } cli, err := svc.GetRpcClient(l.svcCtx.ChoreSvcName) if err != nil { return "", err } res, err := chore.NewChoreClient(cli.Conn()).InternalUpload(l.ctx, &chore.InternalUploadReq{ Filename: uuid.New().String() + ".png", Content: content, }) if err != nil { return "", err } if res == nil || res.Url == utils.StringEmpty { return "", fmt.Errorf("chore upload empty url") } return res.Url, nil }