修改微信扫码登录 access_token 问题
This commit is contained in:
10
go.mod
10
go.mod
@ -3,10 +3,15 @@ module server
|
|||||||
go 1.24.2
|
go 1.24.2
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.11
|
||||||
github.com/alibabacloud-go/dysmsapi-20170525/v4 v4.1.3
|
github.com/alibabacloud-go/dysmsapi-20170525/v4 v4.1.3
|
||||||
|
github.com/alibabacloud-go/tea v1.2.2
|
||||||
|
github.com/alibabacloud-go/tea-utils/v2 v2.0.6
|
||||||
github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible
|
github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible
|
||||||
|
github.com/aliyun/credentials-go v1.4.6
|
||||||
github.com/bwmarrin/snowflake v0.3.0
|
github.com/bwmarrin/snowflake v0.3.0
|
||||||
github.com/casbin/casbin/v2 v2.105.0
|
github.com/casbin/casbin/v2 v2.105.0
|
||||||
|
github.com/eclipse/paho.mqtt.golang v1.5.0
|
||||||
github.com/go-resty/resty/v2 v2.16.5
|
github.com/go-resty/resty/v2 v2.16.5
|
||||||
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.9.0
|
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.9.0
|
||||||
github.com/gogf/gf/contrib/nosql/redis/v2 v2.9.0
|
github.com/gogf/gf/contrib/nosql/redis/v2 v2.9.0
|
||||||
@ -20,14 +25,10 @@ require (
|
|||||||
require (
|
require (
|
||||||
github.com/BurntSushi/toml v1.4.0 // indirect
|
github.com/BurntSushi/toml v1.4.0 // indirect
|
||||||
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5 // indirect
|
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5 // indirect
|
||||||
github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.11 // indirect
|
|
||||||
github.com/alibabacloud-go/debug v1.0.1 // indirect
|
github.com/alibabacloud-go/debug v1.0.1 // indirect
|
||||||
github.com/alibabacloud-go/endpoint-util v1.1.0 // indirect
|
github.com/alibabacloud-go/endpoint-util v1.1.0 // indirect
|
||||||
github.com/alibabacloud-go/openapi-util v0.1.1 // indirect
|
github.com/alibabacloud-go/openapi-util v0.1.1 // indirect
|
||||||
github.com/alibabacloud-go/tea v1.2.2 // indirect
|
|
||||||
github.com/alibabacloud-go/tea-utils/v2 v2.0.6 // indirect
|
|
||||||
github.com/alibabacloud-go/tea-xml v1.1.3 // indirect
|
github.com/alibabacloud-go/tea-xml v1.1.3 // indirect
|
||||||
github.com/aliyun/credentials-go v1.4.6 // indirect
|
|
||||||
github.com/bmatcuk/doublestar/v4 v4.6.1 // indirect
|
github.com/bmatcuk/doublestar/v4 v4.6.1 // indirect
|
||||||
github.com/casbin/govaluate v1.3.0 // indirect
|
github.com/casbin/govaluate v1.3.0 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
@ -57,6 +58,7 @@ require (
|
|||||||
go.opentelemetry.io/otel/sdk v1.32.0 // indirect
|
go.opentelemetry.io/otel/sdk v1.32.0 // indirect
|
||||||
go.opentelemetry.io/otel/trace v1.32.0 // indirect
|
go.opentelemetry.io/otel/trace v1.32.0 // indirect
|
||||||
golang.org/x/net v0.33.0 // indirect
|
golang.org/x/net v0.33.0 // indirect
|
||||||
|
golang.org/x/sync v0.14.0 // indirect
|
||||||
golang.org/x/sys v0.33.0 // indirect
|
golang.org/x/sys v0.33.0 // indirect
|
||||||
golang.org/x/text v0.25.0 // indirect
|
golang.org/x/text v0.25.0 // indirect
|
||||||
golang.org/x/time v0.6.0 // indirect
|
golang.org/x/time v0.6.0 // indirect
|
||||||
|
|||||||
4
go.sum
4
go.sum
@ -77,6 +77,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
|||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||||
|
github.com/eclipse/paho.mqtt.golang v1.5.0 h1:EH+bUVJNgttidWFkLLVKaQPGmkTUfQQqjOsyvMGvD6o=
|
||||||
|
github.com/eclipse/paho.mqtt.golang v1.5.0/go.mod h1:du/2qNQVqJf/Sqs4MEL77kR8QTqANF7XU7Fk0aOTAgk=
|
||||||
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||||
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
@ -244,6 +246,8 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ
|
|||||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
|
||||||
|
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
|||||||
@ -15,3 +15,7 @@ const (
|
|||||||
WeChatLoginCache = "wx:login:cache:%s"
|
WeChatLoginCache = "wx:login:cache:%s"
|
||||||
WeChatLoginLimit = "wx:login:limit:%s"
|
WeChatLoginLimit = "wx:login:limit:%s"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
WechatAccessTokenKey = "wechat:access_token"
|
||||||
|
)
|
||||||
|
|||||||
@ -2,11 +2,14 @@ package storeDesktopSetting
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"github.com/gogf/gf/v2/errors/gerror"
|
"github.com/gogf/gf/v2/errors/gerror"
|
||||||
"server/internal/dao"
|
"server/internal/dao"
|
||||||
"server/internal/model"
|
"server/internal/model"
|
||||||
"server/internal/model/do"
|
"server/internal/model/do"
|
||||||
"server/internal/service"
|
"server/internal/service"
|
||||||
|
"server/utility/mqtt"
|
||||||
)
|
)
|
||||||
|
|
||||||
type sStoreDesktopSetting struct {
|
type sStoreDesktopSetting struct {
|
||||||
@ -60,6 +63,19 @@ func (s *sStoreDesktopSetting) Save(ctx context.Context, in model.SaveDesktopSet
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
client, b := mqtt.GetClient("emqx")
|
||||||
|
if !b {
|
||||||
|
return nil, gerror.New("获取MQTT客户端失败")
|
||||||
|
}
|
||||||
|
marshal, err := json.Marshal(in)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = client.Publish(fmt.Sprintf("/desktop/%d", in.StoreId), marshal)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return &model.SaveDesktopSettingOut{
|
return &model.SaveDesktopSettingOut{
|
||||||
Success: true,
|
Success: true,
|
||||||
}, nil
|
}, nil
|
||||||
|
|||||||
@ -131,7 +131,13 @@ type GiftResponse struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type gameRoleInfo struct {
|
type gameRoleInfo struct {
|
||||||
// FIXME
|
RoleIdx string `json:"roleIdx"`
|
||||||
|
RoleBaseInfo roleBaseInfo `json:"RoleBaseInfo"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type roleBaseInfo struct {
|
||||||
|
Gid int `json:"gid"`
|
||||||
|
RoleIdx string `json:"roleidx"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type userAddress struct {
|
type userAddress struct {
|
||||||
@ -139,13 +145,24 @@ type userAddress struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type waterExtraInfo struct {
|
type waterExtraInfo struct {
|
||||||
// FIXME
|
EchangeWaterLog echangeWaterLog `json:"echange_water_log"`
|
||||||
|
PremiumPrivInfo premiumPrivInfo `json:"premium_priv_info"`
|
||||||
|
SendOrderQuantity int `json:"send_order_quantity"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type goodsType struct {
|
type echangeWaterLog struct {
|
||||||
// FIXME
|
SrcChannel string `json:"src_channel"`
|
||||||
|
SrcModule string `json:"src_module"`
|
||||||
|
Source string `json:"source"`
|
||||||
|
CreateBrandId string `json:"create_brand_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type premiumPrivInfo struct {
|
||||||
|
CustomInfo string `json:"custom_info"` // 字符串 JSON,可视需要二次解析
|
||||||
|
}
|
||||||
|
|
||||||
|
type goodsType int64
|
||||||
|
|
||||||
type goodsDisplayType struct {
|
type goodsDisplayType struct {
|
||||||
// FIXME
|
// FIXME
|
||||||
}
|
}
|
||||||
@ -153,9 +170,44 @@ type goodsDisplayType struct {
|
|||||||
type merchantInfo struct {
|
type merchantInfo struct {
|
||||||
// FIXME
|
// FIXME
|
||||||
}
|
}
|
||||||
|
type olCouponCfg struct {
|
||||||
|
CouponReq couponReq `json:"coupon_req"`
|
||||||
|
}
|
||||||
|
type couponReq struct {
|
||||||
|
ReqContent reqContent `json:"reqContent"`
|
||||||
|
}
|
||||||
|
type reqContent struct {
|
||||||
|
CouponContent couponContent `json:"couponContent"`
|
||||||
|
}
|
||||||
|
type couponContent struct {
|
||||||
|
CouponNum string `json:"couponNum"`
|
||||||
|
}
|
||||||
|
type goodsBrandInfo struct {
|
||||||
|
BrandName string `json:"brand_name"`
|
||||||
|
JumpStatus int `json:"jump_status"`
|
||||||
|
BrandId string `json:"brand_id"`
|
||||||
|
BrandLogo string `json:"brand_logo"`
|
||||||
|
}
|
||||||
|
type expireConfig struct {
|
||||||
|
ExpireDays int `json:"expire_days"`
|
||||||
|
}
|
||||||
|
type privCoupon struct {
|
||||||
|
AppId string `json:"appid"`
|
||||||
|
PrizeChannelId string `json:"prize_channel_id"`
|
||||||
|
PrizeId string `json:"prize_id"`
|
||||||
|
PrizeType int `json:"prize_type"`
|
||||||
|
Num int `json:"num"`
|
||||||
|
Url string `json:"url"`
|
||||||
|
}
|
||||||
type goodsExtraInfo struct {
|
type goodsExtraInfo struct {
|
||||||
// FIXME
|
OlCouponCfg olCouponCfg `json:"olcoupon_cfg"`
|
||||||
|
GoodsBrandInfo goodsBrandInfo `json:"goods_brand_info"`
|
||||||
|
ExpireType int `json:"expire_type"`
|
||||||
|
ExpireConfig expireConfig `json:"expire_config"`
|
||||||
|
MprocJmpCfg map[string]any `json:"mproc_jmp_cfg"` // 空对象可用 map[string]any 表示
|
||||||
|
ApplyGoods string `json:"apply_goods"`
|
||||||
|
NewlyBuilt bool `json:"newly_built"`
|
||||||
|
PrivCoupon privCoupon `json:"priv_coupon"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type water struct {
|
type water struct {
|
||||||
|
|||||||
@ -19,9 +19,9 @@ type StoreGetDesktopSettingOut struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type SaveDesktopSettingIn struct {
|
type SaveDesktopSettingIn struct {
|
||||||
StoreId int64
|
StoreId int64 `json:"storeId"`
|
||||||
TopComponentVisible int // 1显示,2 隐藏
|
TopComponentVisible int `json:"topComponentVisible"` // 1显示,2 隐藏
|
||||||
RightComponentVisible int // 1显示,2 隐藏
|
RightComponentVisible int `json:"rightComponentVisible"` // 1显示,2 隐藏
|
||||||
}
|
}
|
||||||
type SaveDesktopSettingOut struct {
|
type SaveDesktopSettingOut struct {
|
||||||
Success bool
|
Success bool
|
||||||
|
|||||||
@ -3,11 +3,12 @@ package packed
|
|||||||
import (
|
import (
|
||||||
_ "github.com/gogf/gf/contrib/drivers/mysql/v2"
|
_ "github.com/gogf/gf/contrib/drivers/mysql/v2"
|
||||||
_ "github.com/gogf/gf/contrib/nosql/redis/v2"
|
_ "github.com/gogf/gf/contrib/nosql/redis/v2"
|
||||||
_ "server/utility/gamelife"
|
//_ "server/utility/gamelife"
|
||||||
|
//_ "server/utility/mqtt/emqx"
|
||||||
_ "server/utility/myCasbin"
|
_ "server/utility/myCasbin"
|
||||||
_ "server/utility/oss/aliyun"
|
//_ "server/utility/oss/aliyun"
|
||||||
_ "server/utility/rsa"
|
//_ "server/utility/rsa"
|
||||||
_ "server/utility/sms/aliyun"
|
//_ "server/utility/sms/aliyun"
|
||||||
_ "server/utility/snowid"
|
_ "server/utility/snowid"
|
||||||
_ "server/utility/wechat"
|
_ "server/utility/wechat"
|
||||||
)
|
)
|
||||||
|
|||||||
@ -48,3 +48,11 @@ gamelife:
|
|||||||
secret: "LqPQ2gbF"
|
secret: "LqPQ2gbF"
|
||||||
mode: "test"
|
mode: "test"
|
||||||
rsaKey: "./manifest/config/全游-测试环境密钥.txt"
|
rsaKey: "./manifest/config/全游-测试环境密钥.txt"
|
||||||
|
|
||||||
|
mqtt:
|
||||||
|
emqx:
|
||||||
|
host: "127.0.0.1"
|
||||||
|
clientId: "server"
|
||||||
|
port: 1883
|
||||||
|
username: "areanx_server"
|
||||||
|
password: "areanx_server"
|
||||||
|
|||||||
@ -178,7 +178,7 @@ func (s *gamelifeClient) GetUrl(ctx context.Context, popenID, appName, nickname
|
|||||||
if !isBound {
|
if !isBound {
|
||||||
rootURL = s.unBoundURLMap[s.config.Mode]
|
rootURL = s.unBoundURLMap[s.config.Mode]
|
||||||
}
|
}
|
||||||
cache, err := s.ensureUserCacheWithParams(ctx, popenID, appName, nickname, bindType)
|
cache, err := s.ensureUserCacheWithParams(ctx, popenID, appName, nickname, bindType, isBound)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@ -319,7 +319,7 @@ func (s *gamelifeClient) RequestActivity(ctx context.Context, in *model.QQNetbar
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, ecode.Fail.Sub("获取游戏编码失败")
|
return nil, ecode.Fail.Sub("获取游戏编码失败")
|
||||||
}
|
}
|
||||||
cache, err := s.ensureUserCacheWithParams(ctx, in.PopenId, value.String(), in.NickName, in.BindType)
|
cache, err := s.ensureUserCacheWithParams(ctx, in.PopenId, value.String(), in.NickName, in.BindType, true)
|
||||||
in.TaskParam.BrandId = s.config.BrandID
|
in.TaskParam.BrandId = s.config.BrandID
|
||||||
var result model.GameTaskResponse
|
var result model.GameTaskResponse
|
||||||
resp, err := client.R().
|
resp, err := client.R().
|
||||||
@ -332,11 +332,11 @@ func (s *gamelifeClient) RequestActivity(ctx context.Context, in *model.QQNetbar
|
|||||||
}
|
}
|
||||||
return &result, nil
|
return &result, nil
|
||||||
case consts.QueryUserRoleList:
|
case consts.QueryUserRoleList:
|
||||||
value, err := dao.Games.Ctx(ctx).Where(do.Games{GameId: in.QueryUserGoodsDetailParam.Gid}).Fields(dao.Games.Columns().GameCode).Value()
|
value, err := dao.Games.Ctx(ctx).Where(do.Games{GameId: in.UserRoleParam.Gid}).Fields(dao.Games.Columns().GameCode).Value()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, ecode.Fail.Sub("获取游戏编码失败")
|
return nil, ecode.Fail.Sub("获取游戏编码失败")
|
||||||
}
|
}
|
||||||
cache, err := s.ensureUserCacheWithParams(ctx, in.PopenId, value.String(), in.NickName, in.BindType)
|
cache, err := s.ensureUserCacheWithParams(ctx, in.PopenId, value.String(), in.NickName, in.BindType, true)
|
||||||
var result model.UserRoleListResponse
|
var result model.UserRoleListResponse
|
||||||
resp, err := client.R().
|
resp, err := client.R().
|
||||||
SetContext(ctx).
|
SetContext(ctx).
|
||||||
@ -346,13 +346,14 @@ func (s *gamelifeClient) RequestActivity(ctx context.Context, in *model.QQNetbar
|
|||||||
if err != nil || resp.IsError() {
|
if err != nil || resp.IsError() {
|
||||||
return nil, ecode.Fail.Sub("请求出现异常")
|
return nil, ecode.Fail.Sub("请求出现异常")
|
||||||
}
|
}
|
||||||
|
|
||||||
return &result.RoleList, nil
|
return &result.RoleList, nil
|
||||||
case consts.GetGift:
|
case consts.GetGift:
|
||||||
value, err := dao.Games.Ctx(ctx).Where(do.Games{GameId: in.QueryUserGoodsDetailParam.Gid}).Fields(dao.Games.Columns().GameCode).Value()
|
value, err := dao.Games.Ctx(ctx).Where(do.Games{GameId: in.QueryUserGoodsDetailParam.Gid}).Fields(dao.Games.Columns().GameCode).Value()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, ecode.Fail.Sub("获取游戏编码失败")
|
return nil, ecode.Fail.Sub("获取游戏编码失败")
|
||||||
}
|
}
|
||||||
cache, err := s.ensureUserCacheWithParams(ctx, in.PopenId, value.String(), in.NickName, in.BindType)
|
cache, err := s.ensureUserCacheWithParams(ctx, in.PopenId, value.String(), in.NickName, in.BindType, true)
|
||||||
var result model.GiftResponse
|
var result model.GiftResponse
|
||||||
resp, err := client.R().
|
resp, err := client.R().
|
||||||
SetContext(ctx).
|
SetContext(ctx).
|
||||||
@ -368,7 +369,7 @@ func (s *gamelifeClient) RequestActivity(ctx context.Context, in *model.QQNetbar
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, ecode.Fail.Sub("获取游戏编码失败")
|
return nil, ecode.Fail.Sub("获取游戏编码失败")
|
||||||
}
|
}
|
||||||
cache, err := s.ensureUserCacheWithParams(ctx, in.PopenId, value.String(), in.NickName, in.BindType)
|
cache, err := s.ensureUserCacheWithParams(ctx, in.PopenId, value.String(), in.NickName, in.BindType, true)
|
||||||
var result model.GoodsResponse
|
var result model.GoodsResponse
|
||||||
resp, err := client.R().
|
resp, err := client.R().
|
||||||
SetContext(ctx).
|
SetContext(ctx).
|
||||||
@ -384,7 +385,7 @@ func (s *gamelifeClient) RequestActivity(ctx context.Context, in *model.QQNetbar
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, ecode.Fail.Sub("获取游戏编码失败")
|
return nil, ecode.Fail.Sub("获取游戏编码失败")
|
||||||
}
|
}
|
||||||
cache, err := s.ensureUserCacheWithParams(ctx, in.PopenId, value.String(), in.NickName, in.BindType)
|
cache, err := s.ensureUserCacheWithParams(ctx, in.PopenId, value.String(), in.NickName, in.BindType, true)
|
||||||
var result model.ExchangeGoodsResponse
|
var result model.ExchangeGoodsResponse
|
||||||
resp, err := client.R().
|
resp, err := client.R().
|
||||||
SetContext(ctx).
|
SetContext(ctx).
|
||||||
@ -400,7 +401,7 @@ func (s *gamelifeClient) RequestActivity(ctx context.Context, in *model.QQNetbar
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, ecode.Fail.Sub("获取游戏编码失败")
|
return nil, ecode.Fail.Sub("获取游戏编码失败")
|
||||||
}
|
}
|
||||||
cache, err := s.ensureUserCacheWithParams(ctx, in.PopenId, value.String(), in.NickName, in.BindType)
|
cache, err := s.ensureUserCacheWithParams(ctx, in.PopenId, value.String(), in.NickName, in.BindType, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -421,7 +422,7 @@ func (s *gamelifeClient) RequestActivity(ctx context.Context, in *model.QQNetbar
|
|||||||
|
|
||||||
// ensureUserCacheWithParams ensures user cache exists and contains a valid Params string.
|
// ensureUserCacheWithParams ensures user cache exists and contains a valid Params string.
|
||||||
// It handles cache retrieval, fallback refresh, Params generation, and cache update.
|
// It handles cache retrieval, fallback refresh, Params generation, and cache update.
|
||||||
func (s *gamelifeClient) ensureUserCacheWithParams(ctx context.Context, popenId, appname, nickname string, bindType int) (*model.UserGamelifeCache, error) {
|
func (s *gamelifeClient) ensureUserCacheWithParams(ctx context.Context, popenId, appname, nickname string, bindType int, isBound bool) (*model.UserGamelifeCache, error) {
|
||||||
cacheKey := fmt.Sprintf(consts.GameLifeUserKey, popenId)
|
cacheKey := fmt.Sprintf(consts.GameLifeUserKey, popenId)
|
||||||
cacheData, err := g.Redis().Get(ctx, cacheKey)
|
cacheData, err := g.Redis().Get(ctx, cacheKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -441,7 +442,7 @@ func (s *gamelifeClient) ensureUserCacheWithParams(ctx context.Context, popenId,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if cache.Params == "" {
|
if cache.Params == "" {
|
||||||
cache.Params, err = s.buildQueryParams(ctx, popenId, cache, appname, nickname, bindType, true)
|
cache.Params, err = s.buildQueryParams(ctx, popenId, cache, appname, nickname, bindType, isBound)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
102
utility/mqtt/emqx/emqx.go
Normal file
102
utility/mqtt/emqx/emqx.go
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
package emqx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
mqttlib "github.com/eclipse/paho.mqtt.golang"
|
||||||
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
|
"github.com/gogf/gf/v2/os/glog"
|
||||||
|
"server/utility/mqtt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type emqxClient struct {
|
||||||
|
client mqttlib.Client
|
||||||
|
once sync.Once
|
||||||
|
}
|
||||||
|
|
||||||
|
// New 创建并连接 EMQX 客户端实例,连接成功才返回
|
||||||
|
func New(broker, clientID, username, password string) mqtt.MqttClient {
|
||||||
|
opts := mqttlib.NewClientOptions().
|
||||||
|
AddBroker(broker).
|
||||||
|
SetClientID(clientID).
|
||||||
|
SetUsername(username).
|
||||||
|
SetPassword(password).
|
||||||
|
SetAutoReconnect(true).
|
||||||
|
SetConnectTimeout(5 * time.Second)
|
||||||
|
|
||||||
|
c := &emqxClient{
|
||||||
|
client: mqttlib.NewClient(opts),
|
||||||
|
}
|
||||||
|
|
||||||
|
// 立即连接
|
||||||
|
err := c.connect()
|
||||||
|
if err != nil {
|
||||||
|
glog.Errorf(context.Background(), "连接EMQX失败: %v", err)
|
||||||
|
panic(fmt.Sprintf("连接EMQX失败: %v", err))
|
||||||
|
}
|
||||||
|
glog.Infof(context.Background(), "EMQX客户端连接成功")
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// connect 内部只调用一次连接
|
||||||
|
func (e *emqxClient) connect() error {
|
||||||
|
var err error
|
||||||
|
e.once.Do(func() {
|
||||||
|
token := e.client.Connect()
|
||||||
|
if token.Wait() && token.Error() != nil {
|
||||||
|
err = fmt.Errorf("EMQX连接失败: %w", token.Error())
|
||||||
|
glog.Errorf(context.Background(), err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
glog.Infof(context.Background(), "EMQX连接成功")
|
||||||
|
})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Publish 实现接口 Publish
|
||||||
|
func (e *emqxClient) Publish(topic string, payload []byte) error {
|
||||||
|
token := e.client.Publish(topic, 0, false, payload)
|
||||||
|
token.Wait()
|
||||||
|
err := token.Error()
|
||||||
|
if err != nil {
|
||||||
|
glog.Errorf(context.Background(), "发布消息失败,topic=%s,错误:%v", topic, err)
|
||||||
|
} else {
|
||||||
|
glog.Infof(context.Background(), "成功发布消息,topic=%s,消息大小=%d字节", topic, len(payload))
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subscribe 实现接口 Subscribe
|
||||||
|
func (e *emqxClient) Subscribe(topic string, handler func(topic string, payload []byte)) error {
|
||||||
|
token := e.client.Subscribe(topic, 0, func(client mqttlib.Client, msg mqttlib.Message) {
|
||||||
|
handler(msg.Topic(), msg.Payload())
|
||||||
|
})
|
||||||
|
token.Wait()
|
||||||
|
err := token.Error()
|
||||||
|
if err != nil {
|
||||||
|
glog.Errorf(context.Background(), "订阅失败,topic=%s,错误:%v", topic, err)
|
||||||
|
} else {
|
||||||
|
glog.Infof(context.Background(), "成功订阅主题,topic=%s", topic)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// init 注册emqx客户端
|
||||||
|
func init() {
|
||||||
|
ctx := context.Background()
|
||||||
|
cfg := g.Config()
|
||||||
|
host := cfg.MustGet(ctx, "mqtt.emqx.host").String()
|
||||||
|
port := cfg.MustGet(ctx, "mqtt.emqx.port").Int()
|
||||||
|
username := cfg.MustGet(ctx, "mqtt.emqx.username").String()
|
||||||
|
password := cfg.MustGet(ctx, "mqtt.emqx.password").String()
|
||||||
|
clientId := cfg.MustGet(ctx, "mqtt.emqx.clientId").String()
|
||||||
|
|
||||||
|
broker := fmt.Sprintf("tcp://%s:%d", host, port)
|
||||||
|
client := New(broker, clientId, username, password)
|
||||||
|
|
||||||
|
mqtt.Register("emqx", client)
|
||||||
|
glog.Infof(ctx, "EMQX客户端注册完成,broker=%s, clientID=%s", broker, clientId)
|
||||||
|
}
|
||||||
23
utility/mqtt/mqtt.go
Normal file
23
utility/mqtt/mqtt.go
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package mqtt
|
||||||
|
|
||||||
|
// MqttClient 定义了通用 MQTT 客户端接口
|
||||||
|
type MqttClient interface {
|
||||||
|
// Publish 发布消息到指定 topic
|
||||||
|
Publish(topic string, payload []byte) error
|
||||||
|
// Subscribe 订阅指定 topic,接收回调
|
||||||
|
Subscribe(topic string, handler func(topic string, payload []byte)) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// 全局注册表
|
||||||
|
var clients = make(map[string]MqttClient)
|
||||||
|
|
||||||
|
// Register 注册一个 MQTT 客户端实现
|
||||||
|
func Register(name string, client MqttClient) {
|
||||||
|
clients[name] = client
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetClient 获取已注册的客户端
|
||||||
|
func GetClient(name string) (MqttClient, bool) {
|
||||||
|
client, ok := clients[name]
|
||||||
|
return client, ok
|
||||||
|
}
|
||||||
@ -43,6 +43,7 @@ func init() {
|
|||||||
// 任务
|
// 任务
|
||||||
enforcer.AddPolicy("guest", "/x/task/ranking", "GET", "获取排行榜")
|
enforcer.AddPolicy("guest", "/x/task/ranking", "GET", "获取排行榜")
|
||||||
enforcer.AddPolicy("guest", "/x/task/getNonLoginTaskList", "GET", "未登录获取任务列表")
|
enforcer.AddPolicy("guest", "/x/task/getNonLoginTaskList", "GET", "未登录获取任务列表")
|
||||||
|
enforcer.AddPolicy("guest", "/x/reward/callback", "POST", "")
|
||||||
|
|
||||||
// 游戏列表
|
// 游戏列表
|
||||||
enforcer.AddPolicy("guest", "/x/game", "GET", "获取游戏列表")
|
enforcer.AddPolicy("guest", "/x/game", "GET", "获取游戏列表")
|
||||||
|
|||||||
@ -2,8 +2,10 @@ package wechat
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"github.com/gogf/gf/v2/encoding/gjson"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
"server/internal/consts"
|
||||||
"server/utility/ecode"
|
"server/utility/ecode"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@ -30,6 +32,35 @@ var (
|
|||||||
once sync.Once
|
once sync.Once
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (c *weChatClient) loadCachedToken(ctx context.Context) bool {
|
||||||
|
val, err := g.Redis().Get(ctx, consts.WechatAccessTokenKey)
|
||||||
|
if err != nil || val.IsEmpty() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
var data struct {
|
||||||
|
Token string `json:"token"`
|
||||||
|
ExpiresAt int64 `json:"expires_at"`
|
||||||
|
}
|
||||||
|
if err := gjson.DecodeTo(val.String(), &data); err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果当前时间超过过期时间 - 5分钟,则视为即将过期
|
||||||
|
if time.Now().Unix() >= data.ExpiresAt-300 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
c.mu.Lock()
|
||||||
|
c.accessToken = data.Token
|
||||||
|
c.expiresIn = int(data.ExpiresAt - time.Now().Unix())
|
||||||
|
c.lastUpdated = time.Now()
|
||||||
|
c.mu.Unlock()
|
||||||
|
|
||||||
|
glog.Infof(ctx, "[loadCachedToken] 成功加载 Redis 中的 access_token: %s", data.Token)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func GetWeChatClient() *weChatClient {
|
func GetWeChatClient() *weChatClient {
|
||||||
return instance
|
return instance
|
||||||
}
|
}
|
||||||
@ -48,11 +79,15 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *weChatClient) getAccessToken() error {
|
func (c *weChatClient) getAccessToken() error {
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
result := struct {
|
result := struct {
|
||||||
AccessToken string `json:"access_token"`
|
AccessToken string `json:"access_token"`
|
||||||
ExpiresIn int `json:"expires_in"`
|
ExpiresIn int `json:"expires_in"` // 一般为 7200 秒
|
||||||
}{}
|
}{}
|
||||||
ctx := context.Background()
|
|
||||||
|
url := "https://api.weixin.qq.com/cgi-bin/token"
|
||||||
|
|
||||||
resp, err := resty.New().R().
|
resp, err := resty.New().R().
|
||||||
SetQueryParams(g.MapStrStr{
|
SetQueryParams(g.MapStrStr{
|
||||||
"grant_type": "client_credential",
|
"grant_type": "client_credential",
|
||||||
@ -60,44 +95,79 @@ func (c *weChatClient) getAccessToken() error {
|
|||||||
"secret": c.AppSecret,
|
"secret": c.AppSecret,
|
||||||
}).
|
}).
|
||||||
SetResult(&result).
|
SetResult(&result).
|
||||||
Get("https://api.weixin.qq.com/cgi-bin/token")
|
Get(url)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf(ctx, "发起 get access_token 请求出现异常: %+v", err)
|
glog.Errorf(ctx, "[getAccessToken] 请求异常, URL: %s, err: %+v", url, err)
|
||||||
return ecode.Fail.Sub("发起 get access_token 请求出现异常")
|
return ecode.Fail.Sub("发起 get access_token 请求出现异常")
|
||||||
}
|
}
|
||||||
if resp.StatusCode() != 200 {
|
if resp.IsError() {
|
||||||
glog.Errorf(ctx, "获取微信 access_token 响应异常: %+v", resp.Status())
|
glog.Errorf(ctx, "[getAccessToken] 响应错误, 状态: %s, 内容: %s", resp.Status(), resp.String())
|
||||||
return ecode.Fail.Sub("获取微信 access_token 失败")
|
return ecode.Fail.Sub("获取 access_token 失败")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 写入内存
|
||||||
c.mu.Lock()
|
c.mu.Lock()
|
||||||
defer c.mu.Unlock()
|
|
||||||
|
|
||||||
c.accessToken = result.AccessToken
|
c.accessToken = result.AccessToken
|
||||||
c.expiresIn = result.ExpiresIn
|
c.expiresIn = result.ExpiresIn
|
||||||
c.lastUpdated = time.Now()
|
c.lastUpdated = time.Now()
|
||||||
glog.Infof(ctx, "获取微信 access_token 成功: %+v", c.accessToken)
|
c.mu.Unlock()
|
||||||
return nil
|
|
||||||
|
// 写入 Redis
|
||||||
|
expiresAt := time.Now().Unix() + int64(result.ExpiresIn)
|
||||||
|
cacheData := g.Map{
|
||||||
|
"token": result.AccessToken,
|
||||||
|
"expires_at": expiresAt,
|
||||||
}
|
}
|
||||||
func (c *weChatClient) autoRefreshToken(ctx context.Context) {
|
jsonStr, _ := gjson.Encode(cacheData)
|
||||||
for {
|
|
||||||
// 初次获取
|
ttl := result.ExpiresIn - 300
|
||||||
if err := c.getAccessToken(); err != nil {
|
if ttl < 60 {
|
||||||
time.Sleep(1 * time.Minute)
|
ttl = 60
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 等待 expiresIn - 300 秒(即提前 5 分钟刷新)
|
err = g.Redis().SetEX(ctx, consts.WechatAccessTokenKey, jsonStr, int64(ttl))
|
||||||
|
if err != nil {
|
||||||
|
glog.Warningf(ctx, "[getAccessToken] Redis 缓存失败: %+v", err)
|
||||||
|
} else {
|
||||||
|
glog.Infof(ctx, "[getAccessToken] 成功写入 Redis,expires_in: %ds", result.ExpiresIn)
|
||||||
|
}
|
||||||
|
|
||||||
|
glog.Infof(ctx, "[getAccessToken] 成功获取 access_token: %s,expires_in: %ds", result.AccessToken, result.ExpiresIn)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *weChatClient) autoRefreshToken(ctx context.Context) {
|
||||||
|
if c.loadCachedToken(ctx) {
|
||||||
|
glog.Infof(ctx, "[autoRefreshToken] 成功加载缓存 token")
|
||||||
|
} else {
|
||||||
|
if err := c.getAccessToken(); err != nil {
|
||||||
|
glog.Errorf(ctx, "[autoRefreshToken] 初次获取 token 失败: %+v", err)
|
||||||
|
time.Sleep(1 * time.Minute)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
c.mu.RLock()
|
c.mu.RLock()
|
||||||
expiresIn := c.expiresIn
|
expiresIn := c.expiresIn
|
||||||
c.mu.RUnlock()
|
c.mu.RUnlock()
|
||||||
|
|
||||||
refreshAfter := time.Duration(expiresIn-300) * time.Second
|
refreshAfter := time.Duration(expiresIn-300) * time.Second
|
||||||
|
if refreshAfter <= 0 {
|
||||||
|
refreshAfter = 5 * time.Minute
|
||||||
|
}
|
||||||
|
|
||||||
time.Sleep(refreshAfter)
|
time.Sleep(refreshAfter)
|
||||||
|
|
||||||
|
if err := c.getAccessToken(); err != nil {
|
||||||
|
glog.Errorf(ctx, "[autoRefreshToken] 刷新 token 失败: %+v", err)
|
||||||
|
time.Sleep(1 * time.Minute)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (c *weChatClient) GetTicket(sceneId string) (string, error) {
|
func (c *weChatClient) GetTicket(sceneId string) (string, error) {
|
||||||
|
ctx := context.Background()
|
||||||
body := map[string]interface{}{
|
body := map[string]interface{}{
|
||||||
"expire_seconds": c.TicketExpire,
|
"expire_seconds": c.TicketExpire,
|
||||||
"action_name": "QR_STR_SCENE",
|
"action_name": "QR_STR_SCENE",
|
||||||
@ -120,49 +190,51 @@ func (c *weChatClient) GetTicket(sceneId string) (string, error) {
|
|||||||
Post("https://api.weixin.qq.com/cgi-bin/qrcode/create")
|
Post("https://api.weixin.qq.com/cgi-bin/qrcode/create")
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf(context.Background(), "发起 get ticket 请求出现异常: %+v", err)
|
glog.Errorf(ctx, "[GetTicket] 请求异常: %+v", err)
|
||||||
return "", ecode.Fail.Sub("发起 get ticket 请求出现异常")
|
return "", ecode.Fail.Sub("发起 get ticket 请求出现异常")
|
||||||
}
|
}
|
||||||
if resp.StatusCode() != 200 {
|
if resp.IsError() {
|
||||||
glog.Errorf(context.Background(), "获取微信 ticket 响应异常: %+v", resp.Status())
|
glog.Errorf(ctx, "[GetTicket] 响应错误,状态: %s,内容: %s", resp.Status(), resp.String())
|
||||||
return "", ecode.Fail.Sub("获取微信 ticket 失败")
|
return "", ecode.Fail.Sub("获取微信 ticket 失败")
|
||||||
}
|
}
|
||||||
|
|
||||||
glog.Infof(context.Background(), "获取微信 ticket 成功: %+v", result.Ticket)
|
glog.Infof(ctx, "[GetTicket] 成功获取 ticket: %s, 过期时间: %ds", result.Ticket, result.ExpireSeconds)
|
||||||
return result.Ticket, nil
|
return result.Ticket, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *weChatClient) GetQrCode(ticket string) (imagePath string, err error) {
|
func (c *weChatClient) GetQrCode(ticket string) (string, error) {
|
||||||
qrCodeUrl := "https://mp.weixin.qq.com/cgi-bin/showqrcode"
|
ctx := context.Background()
|
||||||
|
url := "https://mp.weixin.qq.com/cgi-bin/showqrcode"
|
||||||
resp, err := resty.New().R().
|
resp, err := resty.New().R().
|
||||||
SetDoNotParseResponse(true).
|
SetDoNotParseResponse(true).
|
||||||
SetQueryParams(g.MapStrStr{"ticket": ticket}).
|
SetQueryParams(g.MapStrStr{"ticket": ticket}).
|
||||||
Get(qrCodeUrl)
|
Get(url)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf(context.Background(), "获取二维码图片请求异常: %+v", err)
|
glog.Errorf(ctx, "[GetQrCode] 请求失败: %+v", err)
|
||||||
return "", ecode.Fail.Sub("获取二维码图片请求失败")
|
return "", ecode.Fail.Sub("获取二维码图片请求失败")
|
||||||
}
|
}
|
||||||
if resp.StatusCode() != 200 {
|
if resp.IsError() {
|
||||||
glog.Errorf(context.Background(), "获取二维码图片响应异常: %+v", resp.Status())
|
glog.Errorf(ctx, "[GetQrCode] 响应异常, 状态: %s", resp.Status())
|
||||||
return "", ecode.Fail.Sub("获取二维码图片失败")
|
return "", ecode.Fail.Sub("获取二维码图片失败")
|
||||||
}
|
}
|
||||||
imagePath = uuid.New().String() + ".jpg"
|
|
||||||
|
|
||||||
|
imagePath := uuid.New().String() + ".jpg"
|
||||||
data, readErr := io.ReadAll(resp.RawBody())
|
data, readErr := io.ReadAll(resp.RawBody())
|
||||||
|
defer resp.RawBody().Close()
|
||||||
|
|
||||||
if readErr != nil {
|
if readErr != nil {
|
||||||
glog.Errorf(context.Background(), "读取二维码图片失败: %+v", readErr)
|
glog.Errorf(ctx, "[GetQrCode] 读取图片失败: %+v", readErr)
|
||||||
return "", ecode.Fail.Sub("读取二维码图片失败")
|
return "", ecode.Fail.Sub("读取二维码图片失败")
|
||||||
}
|
}
|
||||||
defer resp.RawBody().Close()
|
|
||||||
|
|
||||||
writeErr := os.WriteFile(imagePath, data, 0644)
|
writeErr := os.WriteFile(imagePath, data, 0644)
|
||||||
if writeErr != nil {
|
if writeErr != nil {
|
||||||
glog.Errorf(context.Background(), "保存二维码图片失败: %+v", writeErr)
|
glog.Errorf(ctx, "[GetQrCode] 保存图片失败: %+v", writeErr)
|
||||||
return "", ecode.Fail.Sub("保存二维码图片失败")
|
return "", ecode.Fail.Sub("保存二维码图片失败")
|
||||||
}
|
}
|
||||||
|
|
||||||
glog.Infof(context.Background(), "二维码图片保存成功: %s", imagePath)
|
glog.Infof(ctx, "[GetQrCode] 二维码保存成功: %s", imagePath)
|
||||||
return imagePath, nil
|
return imagePath, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user