accessToken

This commit is contained in:
yangduo 2024-12-25 10:58:35 +08:00
parent 1691d745c7
commit 90bb74a5f1
5 changed files with 190 additions and 62 deletions

View File

@ -3,6 +3,7 @@
"gameid": "1004",
"appid": "wx1e89277247304160",
"appkey": "CBP5uFcZP0S2PlcgkBTHxfZEXJft9wMK",
"appsecret": "5834607a498c3225b1d0a608d827c0d6",
"zoneid": "1",
"offerid": "1450310463"
},
@ -10,7 +11,8 @@
"gameid": "2004",
"appid": "wx327f44630205dcd2",
"appkey": "CrIjLw1wiExEnNBVqBQqWGMy0yToREC7",
"appsecret": "148509437b331acd15580b279e8511af",
"zoneid": "1",
"offerid": "1450318181"
}
]
]

View File

@ -12,7 +12,7 @@ import (
"github.com/gin-gonic/gin"
)
type InGameApi struct {
type InGameApi struct {
}
func (this *InGameApi) PreOrder(c *gin.Context) {
@ -172,7 +172,7 @@ func (this *InGameApi) PayDone(c *gin.Context) {
break
}
c.JSON(200, rspObj)
}
@ -187,15 +187,6 @@ func (this *InGameApi) OrderInfo(c *gin.Context) {
return
}
orderModel := new(model.InAppOrder)
if err, found := orderModel.Find(reqJson.AccountId, reqJson.OrderId); err != nil {
f5.RspErr(c, 500, "server internal error")
return
} else if !found {
f5.RspErr(c, 1, "not found")
return
}
strs := strings.Split(reqJson.AccountId, "_")
if len(strs) < 3 {
f5.RspErr(c, 401, "params error1")
@ -215,59 +206,70 @@ func (this *InGameApi) OrderInfo(c *gin.Context) {
return
}
status := orderModel.Status
sessionkeytime := q5.SafeToInt64(data["update_time"])
if service.Wxpay.CheckExpireCache(reqJson.AccountId, sessionkeytime) {
f5.RspErr(c, 402, "session expired")
return
}
orderModel := new(model.InAppOrder)
if err, found := orderModel.Find(reqJson.AccountId, reqJson.OrderId); err != nil {
f5.RspErr(c, 500, "server internal error")
return
} else if !found {
f5.RspErr(c, 1, "not found")
return
}
rspObj := struct {
ErrorCode int32 `json:"errcode"`
ErrMsg string `json:"errmsg"`
OrderId string `json:"order_id"`
GoodsId int32 `json:"goods_id"`
Status int32 `json:"status"`
}{}
for status == 0 {
}{
OrderId: orderModel.OrderId,
GoodsId: orderModel.ItemId,
Status: orderModel.Status,
}
c.JSON(200, rspObj)
if orderModel.Status == 0 {
gameid := q5.SafeToInt64(strs[1])
openid := strs[2]
sessionkey := q5.SafeToString(data["session_key"])
userip := this.getIP(c)
balance, errcode, err := service.Wxpay.QueryBalance(openid, gameid, userip, sessionkey)
if err != nil {
f5.RspErr(c, 500, "system busy")
return
}
if errcode == constant.WX_ERRCODE_OK {
count, err := service.Wxpay.GetGoodsCount(gameid, int64(orderModel.ItemId))
if err != nil {
f5.RspErr(c, 401, "goods error")
return
}
if balance < count {
break
}
errcode = service.Wxpay.QueryPay(openid, gameid, userip, sessionkey, int32(count), orderModel.OrderId)
if errcode == constant.WX_ERRCODE_OK {
status = 1
orderModel.Status = 2
orderModel.UpdateFields([]string{"status"})
if balance >= count {
errcode = service.Wxpay.QueryPay(openid, gameid, userip, sessionkey, int32(count), orderModel.OrderId)
if errcode == constant.WX_ERRCODE_OK {
orderModel.Status = 1
orderModel.UpdateFields([]string{"status"})
}
}
}
if errcode == constant.WX_ERRCODE_SESSIONERR || errcode == constant.WX_ERRCODE_SIGERR {
rspObj.ErrorCode = 402
rspObj.ErrMsg = "session overtime"
service.Wxpay.AddExpireInfo(reqJson.AccountId, sessionkeytime)
}
break
} else if orderModel.Status == 1 {
orderModel.Status = 2
orderModel.UpdateFields([]string{"status"})
}
rspObj.OrderId = orderModel.OrderId
rspObj.GoodsId = orderModel.ItemId
rspObj.Status = status
c.JSON(200, rspObj)
}
func (this *InGameApi) getIP(c *gin.Context) (ip string) {
func (iga *InGameApi) getIP(c *gin.Context) (ip string) {
ip = c.Request.Header.Get("X-Real-Ip")
if ip == "" {
ip = strings.Split(c.Request.Header.Get("X-Forwarded-For"), ",")[0]

View File

@ -116,6 +116,7 @@ type Wxconfig struct {
gameid int64
appid string
appkey string
appsecret string
zoneid string
offerid string
@ -543,12 +544,20 @@ func (this *Wxconfig) HasAppkey() bool {
return (this._flags1_ & (uint64(1) << 3)) > 0
}
func (this *Wxconfig) GetAppsecret() string {
return this.appsecret
}
func (this *Wxconfig) HasAppsecret() bool {
return (this._flags1_ & (uint64(1) << 4)) > 0
}
func (this *Wxconfig) GetZoneid() string {
return this.zoneid
}
func (this *Wxconfig) HasZoneid() bool {
return (this._flags1_ & (uint64(1) << 4)) > 0
return (this._flags1_ & (uint64(1) << 5)) > 0
}
func (this *Wxconfig) GetOfferid() string {
@ -556,7 +565,7 @@ func (this *Wxconfig) GetOfferid() string {
}
func (this *Wxconfig) HasOfferid() bool {
return (this._flags1_ & (uint64(1) << 5)) > 0
return (this._flags1_ & (uint64(1) << 6)) > 0
}
func (this *LoginRedis) GetHost() string {
@ -690,8 +699,9 @@ func (this *Wxconfig) LoadFromKv(kv map[string]interface{}) {
f5.ReadMetaTableField(&this.gameid, "gameid", &this._flags1_, 1, kv)
f5.ReadMetaTableField(&this.appid, "appid", &this._flags1_, 2, kv)
f5.ReadMetaTableField(&this.appkey, "appkey", &this._flags1_, 3, kv)
f5.ReadMetaTableField(&this.zoneid, "zoneid", &this._flags1_, 4, kv)
f5.ReadMetaTableField(&this.offerid, "offerid", &this._flags1_, 5, kv)
f5.ReadMetaTableField(&this.appsecret, "appsecret", &this._flags1_, 4, kv)
f5.ReadMetaTableField(&this.zoneid, "zoneid", &this._flags1_, 5, kv)
f5.ReadMetaTableField(&this.offerid, "offerid", &this._flags1_, 6, kv)
}
func (this *LoginRedis) LoadFromKv(kv map[string]interface{}) {

View File

@ -95,8 +95,9 @@ message Wxconfig
optional int64 gameid = 1;
optional string appid = 2;
optional string appkey = 3;
optional string zoneid = 4;
optional string offerid = 5;
optional string appsecret = 4;
optional string zoneid = 5;
optional string offerid = 6;
}
message LoginRedis

View File

@ -11,10 +11,23 @@ import (
"main/mt"
"q5"
"strings"
"time"
)
type tokenItem struct {
token string
expire int64
}
type expireSession struct {
SessionTime int64
Time int64
}
type wxpay struct {
gamesGoods q5.ConcurrentMap[int64, map[int64]int64]
gamesGoods q5.ConcurrentMap[int64, map[int64]int64] //[gameid, [goodsid]count]
accessTokens q5.ConcurrentMap[int64, tokenItem] //[gameid, tokenitem]
expireInfo q5.ConcurrentMap[string, *expireSession] //[accountid, expireSession]
}
type WxQuery struct {
@ -46,6 +59,9 @@ type WxPayRsp struct {
func (wp *wxpay) init() {
wp.gamesGoods = q5.ConcurrentMap[int64, map[int64]int64]{}
wp.accessTokens = q5.ConcurrentMap[int64, tokenItem]{}
wp.expireInfo = q5.ConcurrentMap[string, *expireSession]{}
mt.Table.Wxconfig.Traverse(func(w *mt.Wxconfig) bool {
filename := "../res/gamegoods/" + q5.SafeToString(w.GetGameid()) + ".json"
str, err := f5.ReadJsonFile(filename)
@ -61,14 +77,84 @@ func (wp *wxpay) init() {
gamegoods[q5.SafeToInt64(data["id"])] = q5.SafeToInt64(data["count"])
}
wp.gamesGoods.Store(w.GetGameid(), gamegoods)
wp.accessTokens.Store(w.GetGameid(), tokenItem{})
}
return true
})
wp.gamesGoods.Range(func(gameid int64, value map[int64]int64) bool {
wp.freshAccessToken(gameid)
return true
})
go wp.checkExpireInfo()
}
func (wp *wxpay) unInit() {
}
func (wp *wxpay) freshAccessToken(gameid int64) (token string) {
cfg := mt.Table.Wxconfig.GetById(gameid)
params := map[string]string{
"grant_type": "client_credential",
"appid": cfg.GetAppid(),
"secret": cfg.GetAppsecret(),
}
urls := mt.Table.Config.GetWxUrl()
queryuri := "cgi-bin/token"
for _, wxhost := range urls {
url := "https://" + wxhost + queryuri
sendok := false
f5.GetHttpCliMgr().SendGoStyleRequest(
url,
params,
func(hcr f5.HttpCliResponse) {
if hcr.GetErr() != nil {
return
}
rspObj := struct {
Token string `json:"access_token"`
Expire int64 `json:"expire_in"`
ErrCode int64 `json:"errcode"`
ErrMsg string `json:"errmsg"`
}{}
sendok = true
f5.GetSysLog().Debug("wx get access token rsp:%s", hcr.GetRawData())
if json.Unmarshal([]byte(hcr.GetRawData()), &rspObj) != nil {
return
}
if rspObj.ErrCode == 0 {
tokenitem, _ := wp.accessTokens.Load(gameid)
tokenitem.token = rspObj.Token
tokenitem.expire = rspObj.Expire + f5.GetApp().GetRealSeconds()
}
})
if sendok {
break
}
}
return token
}
func (wp *wxpay) getAccessToken(gameid int64) (token string) {
cfg, exist := wp.accessTokens.Load(gameid)
nowTime := f5.GetApp().GetRealSeconds()
if exist {
if cfg.expire > nowTime+60 {
return cfg.token
}
return wp.freshAccessToken(gameid)
}
return ""
}
func (wp *wxpay) GetGoodsCount(gameid int64, goodsid int64) (count int64, err error) {
goods, ok := wp.gamesGoods.Load(gameid)
if !ok {
@ -108,7 +194,7 @@ func (wp *wxpay) QueryBalance(openid string, gameid int64, userip string, sessio
queryuri := "/wxa/game/getbalance"
query := WxQuery{
AccessToken: "",
AccessToken: wp.getAccessToken(gameid),
Signature: wp.genSHA256Signature(poststr, sessionkey),
SigMethod: "hmac_sha256",
PaySig: wp.genSHA256Signature(queryuri+"&"+poststr, cfg.GetAppkey()),
@ -121,7 +207,7 @@ func (wp *wxpay) QueryBalance(openid string, gameid int64, userip string, sessio
sendRequest := false
urls := mt.Table.Config.GetWxUrl()
for _, wxhost := range urls {
url := "https://" + wxhost + "/" + queryuri
url := "https://" + wxhost + queryuri
f5.GetHttpCliMgr().SendGoStylePost(
url,
params,
@ -146,11 +232,7 @@ func (wp *wxpay) QueryBalance(openid string, gameid int64, userip string, sessio
balance = rspJson.Balance
case constant.WX_ERRCODE_BUSY:
sendRequest = false
case constant.WX_ERRCODE_SIGERR:
fallthrough
case constant.WX_ERRCODE_PAYSIGERR:
fallthrough
case constant.WX_ERRCODE_PARAMERR:
default:
f5.GetSysLog().Info("err msg:%s", rspJson.ErrMsg)
}
@ -192,7 +274,7 @@ func (wp *wxpay) QueryPay(openid string, gameid int64, userip string, sessionkey
queryuri := "/wxa/game/pay"
query := WxQuery{
AccessToken: "",
AccessToken: wp.getAccessToken(gameid),
Signature: wp.genSHA256Signature(poststr, sessionkey),
SigMethod: "hmac_sha256",
PaySig: wp.genSHA256Signature(queryuri+"&"+poststr, cfg.GetAppkey()),
@ -229,17 +311,7 @@ func (wp *wxpay) QueryPay(openid string, gameid int64, userip string, sessionkey
case constant.WX_ERRCODE_OK:
case constant.WX_ERRCODE_BUSY:
sendRequest = false
case constant.WX_ERRCODE_SIGERR:
fallthrough
case constant.WX_ERRCODE_PAYSIGERR:
fallthrough
case constant.WX_ERRCODE_SAMEBILLNO:
fallthrough
case constant.WX_ERRCODE_NOENOUGH:
fallthrough
case constant.WX_ERRCODE_SESSIONERR:
fallthrough
case constant.WX_ERRCODE_PARAMERR:
default:
f5.GetSysLog().Info("err msg:%s", rspJson.ErrMsg)
}
@ -252,8 +324,49 @@ func (wp *wxpay) QueryPay(openid string, gameid int64, userip string, sessionkey
return wxerrcode
}
func (wp *wxpay) AddExpireInfo(accountid string, sessiontime int64) {
info := expireSession{
SessionTime: sessiontime,
Time: f5.GetApp().GetRealSeconds(),
}
wp.expireInfo.Store(accountid, &info)
}
func (wp *wxpay) CheckExpireCache(accountid string, expire int64) bool {
info, exist := wp.expireInfo.Load(accountid)
if !exist {
return false
}
if (*info).SessionTime < expire {
wp.expireInfo.Delete(accountid)
return false
}
return true
}
func (wp *wxpay) genSHA256Signature(str string, key string) string {
mac := hmac.New(sha256.New, []byte(key))
_, _ = mac.Write([]byte(str))
return strings.ToLower(hex.EncodeToString(mac.Sum(nil)))
}
func (wp *wxpay) checkExpireInfo() {
for {
time.Sleep(time.Minute * 30)
nowTime := f5.GetApp().GetRealSeconds()
deletelist := map[string]int64{}
wp.expireInfo.Range(func(accountid string, value *expireSession) bool {
if value.Time+3600 < nowTime {
deletelist[accountid] = value.Time
}
return true
})
for accountid := range deletelist {
wp.expireInfo.Delete(accountid)
}
}
}