feat: analysis gen qrcode
This commit is contained in:
@@ -130,7 +130,7 @@ func main() {
|
||||
ctx := svc.NewServiceContext(c, db)
|
||||
|
||||
s := zrpc.MustNewServer(rpcConf, func(grpcServer *grpc.Server) {
|
||||
analysis.RegisterAnalysisServer(grpcServer, server.NewAnalysisServer(ctx))
|
||||
analysis.RegisterAnalysisAuthServer(grpcServer, server.NewAnalysisAuthServer(ctx))
|
||||
if mode == service.DevMode || mode == service.TestMode {
|
||||
reflection.Register(grpcServer)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
// Code generated by goctl. DO NOT EDIT.
|
||||
// goctl 1.10.1
|
||||
// Source: analysis.proto
|
||||
|
||||
package analysisauth
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"lone-services/rpc/analysis/pb"
|
||||
|
||||
"github.com/zeromicro/go-zero/zrpc"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
type (
|
||||
GenerateQrcodeRequest = analysis.GenerateQrcodeRequest
|
||||
Response = analysis.Response
|
||||
|
||||
AnalysisAuth interface {
|
||||
GenerateQrcode(ctx context.Context, in *GenerateQrcodeRequest, opts ...grpc.CallOption) (*Response, error)
|
||||
}
|
||||
|
||||
defaultAnalysisAuth struct {
|
||||
cli zrpc.Client
|
||||
}
|
||||
)
|
||||
|
||||
func NewAnalysisAuth(cli zrpc.Client) AnalysisAuth {
|
||||
return &defaultAnalysisAuth{
|
||||
cli: cli,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *defaultAnalysisAuth) GenerateQrcode(ctx context.Context, in *GenerateQrcodeRequest, opts ...grpc.CallOption) (*Response, error) {
|
||||
client := analysis.NewAnalysisAuthClient(m.cli.Conn())
|
||||
return client.GenerateQrcode(ctx, in, opts...)
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
// Code generated by goctl. DO NOT EDIT.
|
||||
// goctl 1.10.1
|
||||
// Source: analysis.proto
|
||||
|
||||
package analysisClient
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"lone-services/rpc/analysis/pb"
|
||||
|
||||
"github.com/zeromicro/go-zero/zrpc"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
type (
|
||||
Request = analysis.Request
|
||||
Response = analysis.Response
|
||||
|
||||
Analysis interface {
|
||||
Ping(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error)
|
||||
}
|
||||
|
||||
defaultAnalysis struct {
|
||||
cli zrpc.Client
|
||||
}
|
||||
)
|
||||
|
||||
func NewAnalysis(cli zrpc.Client) Analysis {
|
||||
return &defaultAnalysis{
|
||||
cli: cli,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *defaultAnalysis) Ping(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error) {
|
||||
client := analysis.NewAnalysisClient(m.cli.Conn())
|
||||
return client.Ping(ctx, in, opts...)
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"lone-services/pkg/utils"
|
||||
"lone-services/pkg/wechat/qrcode"
|
||||
)
|
||||
|
||||
type WechatQrcodeConfig struct {
|
||||
AppID string
|
||||
Secret string
|
||||
Page string
|
||||
Width int
|
||||
EnvVersion string
|
||||
}
|
||||
|
||||
func LoadWechatQrcodeConfig() (*WechatQrcodeConfig, error) {
|
||||
|
||||
appID := utils.GetConfigString("wechat.appid")
|
||||
secret := utils.GetConfigString("wechat.secret")
|
||||
if appID == utils.StringEmpty || secret == utils.StringEmpty {
|
||||
return nil, fmt.Errorf("wechat config missing")
|
||||
}
|
||||
|
||||
page := utils.GetConfigString("wechat.page")
|
||||
|
||||
width := utils.GetConfigInt("wechat.width")
|
||||
envVersion := utils.GetConfigString("wechat.env_version")
|
||||
if envVersion == utils.StringEmpty {
|
||||
envVersion = "trial"
|
||||
}
|
||||
|
||||
return &WechatQrcodeConfig{
|
||||
AppID: appID,
|
||||
Secret: secret,
|
||||
Page: page,
|
||||
Width: width,
|
||||
EnvVersion: envVersion,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *WechatQrcodeConfig) NewQrcodeClient() *qrcode.Client {
|
||||
return qrcode.NewClient(c.AppID, c.Secret)
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package dao
|
||||
|
||||
import "time"
|
||||
|
||||
const (
|
||||
RedisKeyQRSession = "qr:session:"
|
||||
|
||||
QrcodeSessionPending = 1 // 待扫码
|
||||
QrcodeSessionScanned = 2 // 已扫码未登录
|
||||
QrcodeSessionLogined = 3 // 已扫码已登录
|
||||
|
||||
QrcodeSessionTTL = 5 * time.Minute
|
||||
)
|
||||
|
||||
type QrcodeSessionStatus struct {
|
||||
Status int `json:"status"`
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
package logic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"lone-services/pkg/redis"
|
||||
"lone-services/pkg/utils"
|
||||
"lone-services/pkg/wechat/qrcode"
|
||||
analysis "lone-services/rpc/analysis/pb"
|
||||
chore "lone-services/rpc/chore/pb"
|
||||
"lone-services/services/analysis/internal/config"
|
||||
"lone-services/services/analysis/internal/dao"
|
||||
"lone-services/services/analysis/internal/svc"
|
||||
|
||||
"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 *analysis.GenerateQrcodeRequest) (*analysis.Response, error) {
|
||||
sessionID, err := l.createSession()
|
||||
if err != nil {
|
||||
l.Errorf("generate qrcode session: %v", err)
|
||||
return outResponse(utils.Fail, "create qrcode session failed"), nil
|
||||
}
|
||||
|
||||
wxCfg, err := config.LoadWechatQrcodeConfig()
|
||||
if err != nil {
|
||||
l.Errorf("generate qrcode wechat config: %v", err)
|
||||
return outResponse(utils.Fail, "wechat config missing"), 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() (string, error) {
|
||||
if redis.Client == nil {
|
||||
return "", fmt.Errorf("redis not initialized")
|
||||
}
|
||||
|
||||
sessionID := uuid.New().String()
|
||||
payload, err := jsoniter.MarshalToString(dao.QrcodeSessionStatus{Status: dao.QrcodeSessionPending})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
key := dao.RedisKeyQRSession + sessionID
|
||||
if err := redis.Client.Set(l.ctx, key, payload, dao.QrcodeSessionTTL).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
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
package logic
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"lone-services/services/analysis/analysis"
|
||||
"lone-services/services/analysis/internal/svc"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type PingLogic struct {
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
logx.Logger
|
||||
}
|
||||
|
||||
func NewPingLogic(ctx context.Context, svcCtx *svc.ServiceContext) *PingLogic {
|
||||
return &PingLogic{
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
Logger: logx.WithContext(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
func (l *PingLogic) Ping(in *analysis.Request) (*analysis.Response, error) {
|
||||
// todo: add your logic here and delete this line
|
||||
|
||||
return &analysis.Response{}, nil
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package logic
|
||||
|
||||
import (
|
||||
"lone-services/pkg/utils"
|
||||
analysis "lone-services/rpc/analysis/pb"
|
||||
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
)
|
||||
|
||||
func okResponse(data any) *analysis.Response {
|
||||
buf, _ := jsoniter.Marshal(data)
|
||||
return &analysis.Response{
|
||||
Code: utils.Ok.Code,
|
||||
Msg: utils.Ok.Msg,
|
||||
Data: string(buf),
|
||||
}
|
||||
}
|
||||
|
||||
func failResponse(status utils.Status) *analysis.Response {
|
||||
return &analysis.Response{
|
||||
Code: status.Code,
|
||||
Msg: status.Msg,
|
||||
}
|
||||
}
|
||||
|
||||
func outResponse(status utils.Status, msg string) *analysis.Response {
|
||||
return &analysis.Response{
|
||||
Code: status.Code,
|
||||
Msg: msg,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// Code generated by goctl. DO NOT EDIT.
|
||||
// goctl 1.10.1
|
||||
// Source: analysis.proto
|
||||
|
||||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"lone-services/rpc/analysis/pb"
|
||||
"lone-services/services/analysis/internal/logic"
|
||||
"lone-services/services/analysis/internal/svc"
|
||||
)
|
||||
|
||||
type AnalysisAuthServer struct {
|
||||
svcCtx *svc.ServiceContext
|
||||
analysis.UnimplementedAnalysisAuthServer
|
||||
}
|
||||
|
||||
func NewAnalysisAuthServer(svcCtx *svc.ServiceContext) *AnalysisAuthServer {
|
||||
return &AnalysisAuthServer{
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *AnalysisAuthServer) GenerateQrcode(ctx context.Context, in *analysis.GenerateQrcodeRequest) (*analysis.Response, error) {
|
||||
l := logic.NewGenerateQrcodeLogic(ctx, s.svcCtx)
|
||||
return l.GenerateQrcode(in)
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
// Code generated by goctl. DO NOT EDIT.
|
||||
// goctl 1.10.1
|
||||
// Source: analysis.proto
|
||||
|
||||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"lone-services/rpc/analysis/pb"
|
||||
"lone-services/services/analysis/internal/logic"
|
||||
"lone-services/services/analysis/internal/svc"
|
||||
)
|
||||
|
||||
type AnalysisServer struct {
|
||||
svcCtx *svc.ServiceContext
|
||||
analysis.UnimplementedAnalysisServer
|
||||
}
|
||||
|
||||
func NewAnalysisServer(svcCtx *svc.ServiceContext) *AnalysisServer {
|
||||
return &AnalysisServer{
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *AnalysisServer) Ping(ctx context.Context, in *analysis.Request) (*analysis.Response, error) {
|
||||
l := logic.NewPingLogic(ctx, s.svcCtx)
|
||||
return l.Ping(in)
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
[base]
|
||||
login_out_time=43200
|
||||
login_refresh_out_time=83200
|
||||
name = "analysis-service"
|
||||
listenOn = "0.0.0.0:11800"
|
||||
mode = "dev"
|
||||
|
||||
[log]
|
||||
path = "logs"
|
||||
serviceName = "analysis-service"
|
||||
mode = "file"
|
||||
encoding = "plain"
|
||||
level = "info"
|
||||
keepDays = 7
|
||||
maxSize = 50
|
||||
maxBackups = 5
|
||||
compress = false
|
||||
|
||||
[mysql]
|
||||
host = '39.106.171.204'
|
||||
port = 33066
|
||||
user = 'root'
|
||||
password = 'MOLXRZNOU4Y4'
|
||||
database = 'dms-analysis'
|
||||
charset = 'utf8mb4'
|
||||
prefix = ''
|
||||
debug = true
|
||||
|
||||
[mysql_read]
|
||||
host = '39.106.171.204'
|
||||
port = 33066
|
||||
user = 'root'
|
||||
password = 'MOLXRZNOU4Y4'
|
||||
database = 'dms-analysis'
|
||||
charset = 'utf8mb4'
|
||||
prefix = ''
|
||||
|
||||
[redis]
|
||||
host = '39.106.171.204'
|
||||
password = 'lLMLcuPpzSj'
|
||||
port = 6379
|
||||
db = 0
|
||||
|
||||
[log-redis]
|
||||
host = '39.106.171.204'
|
||||
password = 'lLMLcuPpzSj'
|
||||
port = 6379
|
||||
db = 3
|
||||
|
||||
[wechat]
|
||||
appid = 'wxa6f5d68dcbc955c7'
|
||||
secret = '657bc95ab1eb4462913c056802b677c1'
|
||||
login_page = 'pagesB/userLogin/index'
|
||||
width = 430
|
||||
env_version = 'trial'
|
||||
|
||||
[services]
|
||||
chore = "chore-service"
|
||||
|
||||
[encrypt]
|
||||
data_key = "u2t9T3luZtoRfhBstkFN6TiIMW38BA8a"
|
||||
Reference in New Issue
Block a user