huawei pay
This commit is contained in:
parent
52178e17da
commit
5e40d7287f
@ -4,5 +4,7 @@
|
|||||||
"wx_merchant_id": "1509252791",
|
"wx_merchant_id": "1509252791",
|
||||||
"wx_certificate_sn": "3490963E4E2767E6D8EC99CFE406A2CBEB3CD195",
|
"wx_certificate_sn": "3490963E4E2767E6D8EC99CFE406A2CBEB3CD195",
|
||||||
"wx_merchant_api_key": "fgRnUvC5Zu04ir9HQPHWesrsh49ZnfpC",
|
"wx_merchant_api_key": "fgRnUvC5Zu04ir9HQPHWesrsh49ZnfpC",
|
||||||
"wx_merchant_public_key_id": "PUB_KEY_ID_0115092527912025021200388000001392"
|
"wx_merchant_public_key_id": "PUB_KEY_ID_0115092527912025021200388000001392",
|
||||||
|
"hw_at_url": "https://oauth-login.cloud.huawei.com/oauth2/v3/token",
|
||||||
|
"hw_order_host": "orders-drcn.iap.cloud.huawei.com.cn|orders-dra.iap.cloud.huawei.asia|orders-dre.iap.cloud.huawei.eu"
|
||||||
}
|
}
|
9
bin/payserver/res/hwconfig@hwconfig.json
Normal file
9
bin/payserver/res/hwconfig@hwconfig.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"gameid": "2004",
|
||||||
|
"clientid": "114061151",
|
||||||
|
"clientsecret": "bb6ebce4982201802507ac20affdaa084e3b27d30ce4cc85c9e3423349489333",
|
||||||
|
"notifyurl": "https://game2004api-test.kingsome.cn/6001/webapp/index.php",
|
||||||
|
"publickey": "MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEA9wju3RCKPKMG9DXmHiOFJuyjdW8/senrHH/VcFhyWZawpsozF1MeGY83pIE/pqf/lRaQ9+BoN/MJdLwVUJBtjVN6ndAjFejWchGd6PvG+C1MCSdRrJH+V5CT97BS6K3tMHuSlt+jE8iAwFhcc9t63IqfDXAJLBlMLCkp9b2RHX7rTbzTdIBsYFQYMmAAi1LB5mLIk+TECTd7rHMKVztw45X+IO6tkXVgARnI0QCdx3eeRc7yfGdiDg4GGwqBHdP9jYty9bhCw4cFhFhWeG2+E03XsTWQ0t27xHIPf1fET9oawm0GttxFScZsgOGWHpHlBnG0oS9uZ1JkAg1lxp7t3Wn7nF04Qe/jnpoCYwXw++poSDtqyfN3M4eGJemkjwhDBK/cO3/fohQW/jfcmyHMjo5uzd12RETn3iChONqT0l3t5O0RWqP/Cr/1QQY50c4rGGb+gLbD2EWUHP61Gu+QXG4knClg3tcOy8l80imVo7ZoXH8KUdXJJXvphio5EtkvAgMBAAE="
|
||||||
|
}
|
||||||
|
]
|
@ -3,6 +3,7 @@ package ingame
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"f5"
|
"f5"
|
||||||
|
"fmt"
|
||||||
"main/constant"
|
"main/constant"
|
||||||
"main/model"
|
"main/model"
|
||||||
"main/service"
|
"main/service"
|
||||||
@ -332,7 +333,7 @@ func (iga *InGameApi) OrderInfo(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if errcode == constant.WX_ERRCODE_OK {
|
if errcode == constant.WX_ERRCODE_OK {
|
||||||
count, err := service.Wxpay.GetGoodsCount(gameid, int64(orderModel.ItemId))
|
count, err := service.GetGoodsCount(gameid, int64(orderModel.ItemId))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -531,3 +532,61 @@ func (iga *InGameApi) isNopayChannel(accountId string) (ret bool) {
|
|||||||
|
|
||||||
return strs[0] == "6000"
|
return strs[0] == "6000"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (iga *InGameApi) HwPayDone(c *gin.Context) {
|
||||||
|
accountId := c.Query("account_id")
|
||||||
|
goodsid := c.Query("goods_id")
|
||||||
|
sessionid := c.Query("session_id")
|
||||||
|
orderid := c.Query("order_id")
|
||||||
|
token := c.Query("token")
|
||||||
|
sign := c.Query("sign")
|
||||||
|
if !strings.EqualFold(q5.Md5Str(accountId+goodsid+constant.GLOBAL_SALT+sessionid+orderid+token), strings.ToLower(sign)) {
|
||||||
|
f5.RspErr(c, 401, "sign err")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
orderModel := new(model.InAppOrder)
|
||||||
|
if err, found := orderModel.Find(accountId, orderid); err != nil {
|
||||||
|
f5.RspErr(c, 500, "server internal error")
|
||||||
|
return
|
||||||
|
} else if !found {
|
||||||
|
f5.RspErr(c, 1, "order not found")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if orderModel.AccountId != accountId ||
|
||||||
|
orderModel.ItemId != q5.SafeToInt32(goodsid) {
|
||||||
|
f5.RspErr(c, 1, "order not found 2")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rspObj := struct {
|
||||||
|
ErrorCode int32 `json:"errcode"`
|
||||||
|
ErrMsg string `json:"errmsg"`
|
||||||
|
OrderId string `json:"order_id"`
|
||||||
|
State int32 `json:"state"` // 0 未支付;1 已支付;2 已发货
|
||||||
|
}{
|
||||||
|
OrderId: orderid,
|
||||||
|
}
|
||||||
|
|
||||||
|
oldstate := orderModel.Status
|
||||||
|
updatefields := []string{"status"}
|
||||||
|
if orderModel.Status > 0 {
|
||||||
|
rspObj.State = orderModel.Status
|
||||||
|
if orderModel.Status == 1 {
|
||||||
|
orderModel.Status = 2
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
productid := fmt.Sprintf("hw%s", goodsid) // hw productid="hw"+shopid
|
||||||
|
price := int64(0)
|
||||||
|
orderModel.Status, orderModel.SpOrderId, price = service.Hwpay.QueryOrder(int64(orderModel.GameId), token, productid, &orderid)
|
||||||
|
orderModel.Price = int32(price)
|
||||||
|
updatefields = append(updatefields, []string{"sp_orderid", "price"}...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if oldstate != orderModel.Status {
|
||||||
|
orderModel.UpdateFields(updatefields)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(0, rspObj)
|
||||||
|
}
|
||||||
|
@ -21,6 +21,10 @@ import (
|
|||||||
type MainServiceApi struct {
|
type MainServiceApi struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *MainServiceApi) Self(c *gin.Context) {
|
||||||
|
c.String(200, c.Param("gameid"))
|
||||||
|
}
|
||||||
|
|
||||||
func (this *MainServiceApi) RefreshToken(c *gin.Context) {
|
func (this *MainServiceApi) RefreshToken(c *gin.Context) {
|
||||||
reqtime := q5.SafeToInt64(c.Query("time"))
|
reqtime := q5.SafeToInt64(c.Query("time"))
|
||||||
reqsign := c.Query("sign")
|
reqsign := c.Query("sign")
|
||||||
@ -42,7 +46,13 @@ func (this *MainServiceApi) RefreshToken(c *gin.Context) {
|
|||||||
ErrMsg string `json:"errmsg"`
|
ErrMsg string `json:"errmsg"`
|
||||||
}{}
|
}{}
|
||||||
|
|
||||||
|
reftype := q5.SafeToInt64(c.Query("type"))
|
||||||
|
switch reftype {
|
||||||
|
case 0:
|
||||||
service.Wxpay.GetAccessTokenList(&rspObj.Data)
|
service.Wxpay.GetAccessTokenList(&rspObj.Data)
|
||||||
|
case 1:
|
||||||
|
service.Hwpay.GetAccessTokenList(&rspObj.Data)
|
||||||
|
}
|
||||||
c.JSON(200, rspObj)
|
c.JSON(200, rspObj)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,7 +213,7 @@ func (this *MainServiceApi) WxNotifyPurchase(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if orderModel.Status > 1 {
|
if orderModel.Status > 0 {
|
||||||
rspObj.ErrorCode = 0
|
rspObj.ErrorCode = 0
|
||||||
rspObj.ErrMsg = "Success"
|
rspObj.ErrMsg = "Success"
|
||||||
c.JSON(200, rspObj)
|
c.JSON(200, rspObj)
|
||||||
@ -395,7 +405,7 @@ func (this *MainServiceApi) WxMsgNotify(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
thumburl := service.Wxpay.GenThumburl(int64(orderModel.GameId))
|
thumburl := service.Wxpay.GenThumburl(int64(orderModel.GameId))
|
||||||
itemname, _ := service.Wxpay.GetGoodsName(int64(orderModel.GameId), int64(orderModel.ItemId))
|
itemname, _ := service.GetGoodsName(int64(orderModel.GameId), int64(orderModel.ItemId))
|
||||||
|
|
||||||
// 发给客服系统的clicklink
|
// 发给客服系统的clicklink
|
||||||
clickurl := fmt.Sprintf("https://%s/wx/clicknotify?orderid=%s", cfg.GetWxPayNotifyHost(), orderid)
|
clickurl := fmt.Sprintf("https://%s/wx/clicknotify?orderid=%s", cfg.GetWxPayNotifyHost(), orderid)
|
||||||
@ -703,7 +713,7 @@ func (this *MainServiceApi) WxPayNotify(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if orderModel.Status > 1 {
|
if orderModel.Status > 0 {
|
||||||
c.String(200, "")
|
c.String(200, "")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -774,7 +784,136 @@ func (this *MainServiceApi) WxPayNotify(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
count, _ := service.Wxpay.GetGoodsCount(gameid, int64(orderModel.ItemId))
|
count, _ := service.GetGoodsCount(gameid, int64(orderModel.ItemId))
|
||||||
|
orderModel.SpAmount = int32(count)
|
||||||
|
fields = append(fields, "sp_amount")
|
||||||
|
}
|
||||||
|
orderModel.UpdateFields(fields)
|
||||||
|
|
||||||
|
c.String(200, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *MainServiceApi) HwPayNotify(c *gin.Context) {
|
||||||
|
gameid := q5.SafeToInt64(c.Param("gameid"))
|
||||||
|
if gameid == 0 {
|
||||||
|
c.String(501, "")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg := mt.Table.Hwconfig.GetById(gameid)
|
||||||
|
if cfg == nil {
|
||||||
|
f5.GetSysLog().Warning("error gameid cfg :%d", gameid)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rawdata, err := c.GetRawData()
|
||||||
|
if err != nil {
|
||||||
|
c.String(501, "")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
f5.GetSysLog().Debug("hw pay notify post data:%s", rawdata)
|
||||||
|
rsp := service.HwpayNotifyObj{}
|
||||||
|
if json.Unmarshal(rawdata, &rsp) != nil {
|
||||||
|
c.String(501, "")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if rsp.AppId != cfg.GetClientid() ||
|
||||||
|
rsp.ET != "ORDER" {
|
||||||
|
c.String(200, "")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
orderrspobj := service.HwpayOrderNotifyObj{}
|
||||||
|
if json.Unmarshal(rawdata, &orderrspobj) != nil {
|
||||||
|
c.String(501, "")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if orderrspobj.Type != 1 {
|
||||||
|
c.String(200, "")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
orderid := ""
|
||||||
|
state, sporderid, orderprice := service.Hwpay.QueryOrder(gameid, orderrspobj.PT, orderrspobj.PId, &orderid)
|
||||||
|
if state != 1 {
|
||||||
|
c.String(200, "")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
orderModel := new(model.InAppOrder)
|
||||||
|
if err, found := orderModel.FindByOrderId(orderid); err != nil || !found {
|
||||||
|
c.String(200, "")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if orderModel.Status > 0 {
|
||||||
|
c.String(200, "")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
productid := fmt.Sprintf("hw%d", orderModel.ItemId)
|
||||||
|
if productid != orderrspobj.PId {
|
||||||
|
c.String(200, "")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !service.Hwpay.ConfirmOrder(gameid, orderrspobj.PT, orderrspobj.PId) {
|
||||||
|
c.String(501, "")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
notifyurl := cfg.GetNotifyurl()
|
||||||
|
f5.GetSysLog().Debug("hw notify game url:%d, %s", gameid, notifyurl)
|
||||||
|
fields := []string{"status", "sp_orderid"}
|
||||||
|
orderModel.SpOrderId = sporderid
|
||||||
|
orderModel.Status = 1
|
||||||
|
if len(notifyurl) > 0 {
|
||||||
|
goodsidstr := q5.SafeToString(orderModel.ItemId)
|
||||||
|
totalamountstr := q5.SafeToString(orderprice)
|
||||||
|
|
||||||
|
nowtimestr := q5.SafeToString(f5.GetApp().GetRealSeconds())
|
||||||
|
originstr := "account_id=" + orderModel.AccountId
|
||||||
|
originstr += "&goodsid=" + goodsidstr
|
||||||
|
originstr += "&orderid=" + orderModel.OrderId
|
||||||
|
originstr += "&amount=" + totalamountstr
|
||||||
|
originstr += ":" + nowtimestr + constant.NOFITY_GAMESERVER_SALT
|
||||||
|
params := map[string]string{
|
||||||
|
"c": "Recharge",
|
||||||
|
"a": "purchaseNotify",
|
||||||
|
"account_id": orderModel.AccountId,
|
||||||
|
"orderid": orderModel.OrderId,
|
||||||
|
"timestamp": nowtimestr,
|
||||||
|
"goodsid": goodsidstr,
|
||||||
|
"amount": totalamountstr,
|
||||||
|
"sign": q5.Md5Str(originstr),
|
||||||
|
}
|
||||||
|
f5.GetHttpCliMgr().SendGoStyleRequest(
|
||||||
|
notifyurl,
|
||||||
|
params,
|
||||||
|
func(hcr f5.HttpCliResponse) {
|
||||||
|
if hcr.GetErr() != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
gamerspObj := struct {
|
||||||
|
ErrCode int64 `json:"errcode"`
|
||||||
|
ErrMsg string `json:"errmsg"`
|
||||||
|
}{}
|
||||||
|
|
||||||
|
f5.GetSysLog().Debug("get game rsp:%s", hcr.GetRawData())
|
||||||
|
if json.Unmarshal([]byte(hcr.GetRawData()), &gamerspObj) != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if gamerspObj.ErrCode == 0 {
|
||||||
|
orderModel.Status = 2
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
count, _ := service.GetGoodsCount(gameid, int64(orderModel.ItemId))
|
||||||
orderModel.SpAmount = int32(count)
|
orderModel.SpAmount = int32(count)
|
||||||
fields = append(fields, "sp_amount")
|
fields = append(fields, "sp_amount")
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,14 @@ func (ct *ConfigTable) GetWxMerchantPublicKeyId() string {
|
|||||||
return ct.selfConf.GetWxMerchantPublicKeyId()
|
return ct.selfConf.GetWxMerchantPublicKeyId()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ct *ConfigTable) GetHwAtUrl() string {
|
||||||
|
return ct.selfConf.GetHwAtUrl()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct *ConfigTable) GetHwOrderHosts() []string {
|
||||||
|
return strings.Split(ct.selfConf.GetHwOrderHost(), "|")
|
||||||
|
}
|
||||||
|
|
||||||
func (ct *ConfigTable) PostInit1() {
|
func (ct *ConfigTable) PostInit1() {
|
||||||
ct.selfConf = ct.GetById(int64(0))
|
ct.selfConf = ct.GetById(int64(0))
|
||||||
if ct.selfConf == nil {
|
if ct.selfConf == nil {
|
||||||
|
14
server/payserver/mt/Hwconfig.go
Normal file
14
server/payserver/mt/Hwconfig.go
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package mt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"f5"
|
||||||
|
"main/mtb"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Hwconfig struct {
|
||||||
|
mtb.Hwconfig
|
||||||
|
}
|
||||||
|
|
||||||
|
type HwconfigTable struct {
|
||||||
|
f5.IdMetaTable[Hwconfig]
|
||||||
|
}
|
@ -13,6 +13,7 @@ type table struct {
|
|||||||
ConfDb *ConfDbTable
|
ConfDb *ConfDbTable
|
||||||
Wxconfig *WxconfigTable
|
Wxconfig *WxconfigTable
|
||||||
LoginRedis *LoginRedisTable
|
LoginRedis *LoginRedisTable
|
||||||
|
Hwconfig *HwconfigTable
|
||||||
}
|
}
|
||||||
|
|
||||||
var Table = f5.New(func(this *table) {
|
var Table = f5.New(func(this *table) {
|
||||||
@ -55,4 +56,9 @@ var Table = f5.New(func(this *table) {
|
|||||||
this.FileName = "../config/login.redis.json"
|
this.FileName = "../config/login.redis.json"
|
||||||
this.PrimKey = ""
|
this.PrimKey = ""
|
||||||
})
|
})
|
||||||
|
|
||||||
|
this.Hwconfig = f5.New(func(this *HwconfigTable) {
|
||||||
|
this.FileName = "../res/hwconfig@hwconfig.json"
|
||||||
|
this.PrimKey = "gameid"
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -72,6 +72,8 @@ type Config struct {
|
|||||||
wx_certificate_sn string
|
wx_certificate_sn string
|
||||||
wx_merchant_api_key string
|
wx_merchant_api_key string
|
||||||
wx_merchant_public_key_id string
|
wx_merchant_public_key_id string
|
||||||
|
hw_at_url string
|
||||||
|
hw_order_host string
|
||||||
|
|
||||||
_flags1_ uint64
|
_flags1_ uint64
|
||||||
_flags2_ uint64
|
_flags2_ uint64
|
||||||
@ -148,6 +150,17 @@ type LoginRedis struct {
|
|||||||
_flags2_ uint64
|
_flags2_ uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Hwconfig struct {
|
||||||
|
gameid int64
|
||||||
|
clientid string
|
||||||
|
clientsecret string
|
||||||
|
notifyurl string
|
||||||
|
publickey string
|
||||||
|
|
||||||
|
_flags1_ uint64
|
||||||
|
_flags2_ uint64
|
||||||
|
}
|
||||||
|
|
||||||
func (this *PayServerCluster) GetInstanceId() int32 {
|
func (this *PayServerCluster) GetInstanceId() int32 {
|
||||||
return this.instance_id
|
return this.instance_id
|
||||||
}
|
}
|
||||||
@ -441,7 +454,23 @@ func (this *Config) GetWxMerchantPublicKeyId() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (this *Config) HasWxMerchantPublicKeyId() bool {
|
func (this *Config) HasWxMerchantPublicKeyId() bool {
|
||||||
return (this._flags1_ & (uint64(1) << 13)) > 0
|
return (this._flags1_ & (uint64(1) << 8)) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Config) GetHwAtUrl() string {
|
||||||
|
return this.hw_at_url
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Config) HasHwAtUrl() bool {
|
||||||
|
return (this._flags1_ & (uint64(1) << 9)) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Config) GetHwOrderHost() string {
|
||||||
|
return this.hw_order_host
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Config) HasHwOrderHost() bool {
|
||||||
|
return (this._flags1_ & (uint64(1) << 10)) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *RechargeCurrency) GetCurrencyName() string {
|
func (this *RechargeCurrency) GetCurrencyName() string {
|
||||||
@ -724,6 +753,46 @@ func (this *LoginRedis) HasMaxIdleConns() bool {
|
|||||||
return (this._flags1_ & (uint64(1) << 6)) > 0
|
return (this._flags1_ & (uint64(1) << 6)) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *Hwconfig) GetGameid() int64 {
|
||||||
|
return this.gameid
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Hwconfig) HasGameid() bool {
|
||||||
|
return (this._flags1_ & (uint64(1) << 1)) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Hwconfig) GetClientid() string {
|
||||||
|
return this.clientid
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Hwconfig) HasClientid() bool {
|
||||||
|
return (this._flags1_ & (uint64(1) << 2)) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Hwconfig) GetClientsecret() string {
|
||||||
|
return this.clientsecret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Hwconfig) HasClientsecret() bool {
|
||||||
|
return (this._flags1_ & (uint64(1) << 3)) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Hwconfig) GetNotifyurl() string {
|
||||||
|
return this.notifyurl
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Hwconfig) HasNotifyurl() bool {
|
||||||
|
return (this._flags1_ & (uint64(1) << 4)) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Hwconfig) GetPublickey() string {
|
||||||
|
return this.publickey
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Hwconfig) HasPublickey() bool {
|
||||||
|
return (this._flags1_ & (uint64(1) << 5)) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
func (this *PayServerCluster) LoadFromKv(kv map[string]interface{}) {
|
func (this *PayServerCluster) LoadFromKv(kv map[string]interface{}) {
|
||||||
f5.ReadMetaTableField(&this.instance_id, "instance_id", &this._flags1_, 1, kv)
|
f5.ReadMetaTableField(&this.instance_id, "instance_id", &this._flags1_, 1, kv)
|
||||||
@ -777,7 +846,9 @@ func (this *Config) LoadFromKv(kv map[string]interface{}) {
|
|||||||
f5.ReadMetaTableField(&this.wx_merchant_id, "wx_merchant_id", &this._flags1_, 5, kv)
|
f5.ReadMetaTableField(&this.wx_merchant_id, "wx_merchant_id", &this._flags1_, 5, kv)
|
||||||
f5.ReadMetaTableField(&this.wx_certificate_sn, "wx_certificate_sn", &this._flags1_, 6, kv)
|
f5.ReadMetaTableField(&this.wx_certificate_sn, "wx_certificate_sn", &this._flags1_, 6, kv)
|
||||||
f5.ReadMetaTableField(&this.wx_merchant_api_key, "wx_merchant_api_key", &this._flags1_, 7, kv)
|
f5.ReadMetaTableField(&this.wx_merchant_api_key, "wx_merchant_api_key", &this._flags1_, 7, kv)
|
||||||
f5.ReadMetaTableField(&this.wx_merchant_public_key_id, "wx_merchant_public_key_id", &this._flags1_, 13, kv)
|
f5.ReadMetaTableField(&this.wx_merchant_public_key_id, "wx_merchant_public_key_id", &this._flags1_, 8, kv)
|
||||||
|
f5.ReadMetaTableField(&this.hw_at_url, "hw_at_url", &this._flags1_, 9, kv)
|
||||||
|
f5.ReadMetaTableField(&this.hw_order_host, "hw_order_host", &this._flags1_, 10, kv)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *RechargeCurrency) LoadFromKv(kv map[string]interface{}) {
|
func (this *RechargeCurrency) LoadFromKv(kv map[string]interface{}) {
|
||||||
@ -832,3 +903,11 @@ func (this *LoginRedis) LoadFromKv(kv map[string]interface{}) {
|
|||||||
f5.ReadMetaTableField(&this.max_open_conns, "max_open_conns", &this._flags1_, 5, kv)
|
f5.ReadMetaTableField(&this.max_open_conns, "max_open_conns", &this._flags1_, 5, kv)
|
||||||
f5.ReadMetaTableField(&this.max_idle_conns, "max_idle_conns", &this._flags1_, 6, kv)
|
f5.ReadMetaTableField(&this.max_idle_conns, "max_idle_conns", &this._flags1_, 6, kv)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *Hwconfig) LoadFromKv(kv map[string]interface{}) {
|
||||||
|
f5.ReadMetaTableField(&this.gameid, "gameid", &this._flags1_, 1, kv)
|
||||||
|
f5.ReadMetaTableField(&this.clientid, "clientid", &this._flags1_, 2, kv)
|
||||||
|
f5.ReadMetaTableField(&this.clientsecret, "clientsecret", &this._flags1_, 3, kv)
|
||||||
|
f5.ReadMetaTableField(&this.notifyurl, "notifyurl", &this._flags1_, 4, kv)
|
||||||
|
f5.ReadMetaTableField(&this.publickey, "publickey", &this._flags1_, 5, kv)
|
||||||
|
}
|
||||||
|
@ -60,7 +60,9 @@ message Config
|
|||||||
optional string wx_merchant_id = 5;
|
optional string wx_merchant_id = 5;
|
||||||
optional string wx_certificate_sn = 6;
|
optional string wx_certificate_sn = 6;
|
||||||
optional string wx_merchant_api_key = 7;
|
optional string wx_merchant_api_key = 7;
|
||||||
optional string wx_merchant_public_key_id = 13;
|
optional string wx_merchant_public_key_id = 8;
|
||||||
|
optional string hw_at_url = 9;
|
||||||
|
optional string hw_order_host = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
message RechargeCurrency
|
message RechargeCurrency
|
||||||
@ -121,3 +123,12 @@ message LoginRedis
|
|||||||
optional int32 max_open_conns = 5;
|
optional int32 max_open_conns = 5;
|
||||||
optional int32 max_idle_conns = 6;
|
optional int32 max_idle_conns = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message Hwconfig
|
||||||
|
{
|
||||||
|
optional int64 gameid = 1;
|
||||||
|
optional string clientid = 2;
|
||||||
|
optional string clientsecret = 3;
|
||||||
|
optional string notifyurl = 4;
|
||||||
|
optional string publickey = 5;
|
||||||
|
}
|
@ -25,4 +25,6 @@ func (this *IngameRouter) InitRouter() {
|
|||||||
api.InGameApi.PreOrder)
|
api.InGameApi.PreOrder)
|
||||||
f5.GetApp().GetGinEngine().POST("/api/ingame/querypay",
|
f5.GetApp().GetGinEngine().POST("/api/ingame/querypay",
|
||||||
api.InGameApi.QueryPay)
|
api.InGameApi.QueryPay)
|
||||||
|
f5.GetApp().GetGinEngine().POST("/api/ingame/hwpaid",
|
||||||
|
api.InGameApi.HwPayDone)
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,8 @@ type MainServiceRouter struct{}
|
|||||||
|
|
||||||
func (this *MainServiceRouter) InitRouter() {
|
func (this *MainServiceRouter) InitRouter() {
|
||||||
api := v1.ApiGroupApp.MainServiceApiGroup
|
api := v1.ApiGroupApp.MainServiceApiGroup
|
||||||
|
f5.GetApp().GetGinEngine().GET("/self/:gameid",
|
||||||
|
api.Self)
|
||||||
f5.GetApp().GetGinEngine().GET("/api/service/refresh",
|
f5.GetApp().GetGinEngine().GET("/api/service/refresh",
|
||||||
api.RefreshToken)
|
api.RefreshToken)
|
||||||
f5.GetApp().GetGinEngine().GET("/wx/purnotify/:gameid",
|
f5.GetApp().GetGinEngine().GET("/wx/purnotify/:gameid",
|
||||||
@ -23,4 +25,6 @@ func (this *MainServiceRouter) InitRouter() {
|
|||||||
api.WxClickNotify)
|
api.WxClickNotify)
|
||||||
f5.GetApp().GetGinEngine().POST("/wx/paynotify/:gameid",
|
f5.GetApp().GetGinEngine().POST("/wx/paynotify/:gameid",
|
||||||
api.WxPayNotify)
|
api.WxPayNotify)
|
||||||
|
f5.GetApp().GetGinEngine().POST("/hw/paynotify/:gameid",
|
||||||
|
api.HwPayNotify)
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
var _serviceMgr = new(serviceMgr)
|
var _serviceMgr = new(serviceMgr)
|
||||||
var Wxpay = new(wxpay)
|
var Wxpay = new(wxpay)
|
||||||
var Redis = new(redisMap)
|
var Redis = new(redisMap)
|
||||||
|
var Hwpay = new(hwpay)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
global.RegModule(constant.SERVICE_MGR_MODULE_IDX, _serviceMgr)
|
global.RegModule(constant.SERVICE_MGR_MODULE_IDX, _serviceMgr)
|
||||||
|
413
server/payserver/service/hwpay.go
Normal file
413
server/payserver/service/hwpay.go
Normal file
@ -0,0 +1,413 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto"
|
||||||
|
"crypto/rsa"
|
||||||
|
"crypto/sha256"
|
||||||
|
"crypto/tls"
|
||||||
|
"crypto/x509"
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"f5"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"main/mt"
|
||||||
|
"net/http"
|
||||||
|
"q5"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type hwpay struct {
|
||||||
|
accessTokens q5.ConcurrentMap[int64, TokenInfo] //[gameid, TokenInfo]
|
||||||
|
refreshflag bool
|
||||||
|
client http.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
type HwVerifyOrderRsp struct {
|
||||||
|
RspCode string `json:"responseCode"` //"0":OK;其它,错误
|
||||||
|
RspMsg string `json:"responseMessage"`
|
||||||
|
PTokenData string `json:"purchaseTokenData"` //支付信息
|
||||||
|
Sig string `json:"dataSignature"` //签名
|
||||||
|
SigAlg string `json:"signatureAlgorithm"` //签名算法
|
||||||
|
}
|
||||||
|
|
||||||
|
type InappPurchaseDetails struct {
|
||||||
|
AppId int64 `json:"applicationId"` //应用id
|
||||||
|
AutoRenew bool `json:"autoRenewing"` //是否自动更新,非订阅型始终为false
|
||||||
|
OrderId string `json:"orderId"` //订单id
|
||||||
|
Kind int64 `json:"kind"` //商品类别
|
||||||
|
PKGName string `json:"packageName"` //包名
|
||||||
|
ProdId string `json:"productId"` //商品id
|
||||||
|
ProdName string `json:"productName"` //商品名
|
||||||
|
PurTime int64 `json:"purchaseTime"` //购买时间
|
||||||
|
State int64 `json:"purchaseState"` //订单状态 0 已购买
|
||||||
|
PayLoad string `json:"developerPayload"` //保留信息,约定为游戏内orderid
|
||||||
|
ConsumeState int64 `json:"consumptionState"` //消耗状态 0 未消耗 1 已消耗
|
||||||
|
Price int64 `json:"price"` //商品价格 分
|
||||||
|
}
|
||||||
|
|
||||||
|
type HwpayNotifyObj struct {
|
||||||
|
V string `json:"version"` //"0":OK;其它,错误
|
||||||
|
ET string `json:"eventType"` //"ORDER" "SUBSCRIPTION"
|
||||||
|
Time int64 `json:"notifyTime"` //ms
|
||||||
|
AppId string `json:"applicationId"` //appid
|
||||||
|
}
|
||||||
|
|
||||||
|
type HwpayOrderNotifyObj struct {
|
||||||
|
V string `json:"version"` //"0":OK;其它,错误
|
||||||
|
Type int64 `json:"notificationType"` //1 支付成功 2 退款成功
|
||||||
|
PT string `json:"purchaseToken"` //"ORDER" "SUBSCRIPTION"
|
||||||
|
PId string `json:"productId"` //hw productid
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hp *hwpay) init() {
|
||||||
|
hp.accessTokens = q5.ConcurrentMap[int64, TokenInfo]{}
|
||||||
|
|
||||||
|
mt.Table.Hwconfig.Traverse(func(w *mt.Hwconfig) bool {
|
||||||
|
hp.accessTokens.Store(w.GetGameid(), TokenInfo{})
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
hp.refreshflag = true
|
||||||
|
go hp.checkAccessToken()
|
||||||
|
|
||||||
|
hp.client = http.Client{
|
||||||
|
Timeout: time.Second * 5,
|
||||||
|
Transport: &http.Transport{
|
||||||
|
TLSClientConfig: &tls.Config{
|
||||||
|
CipherSuites: []uint16{
|
||||||
|
tls.TLS_AES_128_GCM_SHA256,
|
||||||
|
tls.TLS_AES_256_GCM_SHA384,
|
||||||
|
tls.TLS_CHACHA20_POLY1305_SHA256,
|
||||||
|
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
},
|
||||||
|
MinVersion: tls.VersionTLS12,
|
||||||
|
MaxVersion: tls.VersionTLS13,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hp *hwpay) unInit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hp *hwpay) freshAccessToken(gameid int64) (token string) {
|
||||||
|
cfg := mt.Table.Hwconfig.GetById(gameid)
|
||||||
|
params := map[string]string{
|
||||||
|
"grant_type": "client_credentials",
|
||||||
|
"client_id": cfg.GetClientid(),
|
||||||
|
"client_secret": cfg.GetClientsecret(),
|
||||||
|
}
|
||||||
|
url := mt.Table.Config.GetHwAtUrl()
|
||||||
|
f5.GetHttpCliMgr().SendGoStyleRequest(
|
||||||
|
url,
|
||||||
|
params,
|
||||||
|
func(hcr f5.HttpCliResponse) {
|
||||||
|
if hcr.GetErr() != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rspObj := struct {
|
||||||
|
Token string `json:"access_token"`
|
||||||
|
Expire int64 `json:"expires_in"`
|
||||||
|
ErrCode int64 `json:"error"`
|
||||||
|
ErrMsg string `json:"error_description"`
|
||||||
|
}{}
|
||||||
|
|
||||||
|
f5.GetSysLog().Debug("get hw access token rsp:%s", hcr.GetRawData())
|
||||||
|
if json.Unmarshal([]byte(hcr.GetRawData()), &rspObj) != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if rspObj.ErrCode == 0 {
|
||||||
|
tokenitem, _ := hp.accessTokens.Load(gameid)
|
||||||
|
tokenitem.GameId = gameid
|
||||||
|
tokenitem.Token = rspObj.Token
|
||||||
|
tokenitem.Expire = rspObj.Expire + f5.GetApp().GetRealSeconds()
|
||||||
|
hp.accessTokens.Store(gameid, *tokenitem)
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
return token
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hp *hwpay) getAccessToken(gameid int64) (token string) {
|
||||||
|
cfg, exist := hp.accessTokens.Load(gameid)
|
||||||
|
nowTime := f5.GetApp().GetRealSeconds()
|
||||||
|
if exist {
|
||||||
|
if cfg.Expire > nowTime {
|
||||||
|
if cfg.Expire < nowTime+3 && !hp.refreshflag {
|
||||||
|
hp.refreshflag = true
|
||||||
|
}
|
||||||
|
return cfg.Token
|
||||||
|
}
|
||||||
|
|
||||||
|
if !hp.refreshflag {
|
||||||
|
hp.refreshflag = true
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// return 0 unpaid, 1 paid, 2 consumed
|
||||||
|
func (hp *hwpay) QueryOrder(gameid int64, purchaseToken string, product_id string, orderid *string) (state int32, sporderid string, orderprice int64) {
|
||||||
|
bodyMap := map[string]string{"purchaseToken": purchaseToken, "productId": product_id}
|
||||||
|
|
||||||
|
hosts := mt.Table.Config.GetHwOrderHosts()
|
||||||
|
queryuri := "/applications/purchases/tokens/verify"
|
||||||
|
cfg := mt.Table.Hwconfig.GetById(gameid)
|
||||||
|
if cfg == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, hwhost := range hosts {
|
||||||
|
url := "https://" + hwhost + queryuri
|
||||||
|
bodybytes, err := hp.sendRequest(gameid, url, bodyMap)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
rsp := HwVerifyOrderRsp{}
|
||||||
|
f5.GetSysLog().Debug("get hw verify order rsp:%s", bodybytes)
|
||||||
|
if json.Unmarshal(bodybytes, &rsp) != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if rsp.RspCode != "0" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if hp.verifyRsaSign(rsp.PTokenData, rsp.Sig, cfg.GetPublickey()) != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
purdetails := InappPurchaseDetails{}
|
||||||
|
if json.Unmarshal([]byte(rsp.PTokenData), &purdetails) != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if q5.SafeToString(purdetails.AppId) != cfg.GetClientid() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if orderid == nil || (len(*orderid) > 0 && purdetails.PayLoad != *orderid) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if purdetails.ProdId != product_id {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if purdetails.State != 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if purdetails.ConsumeState != 0 {
|
||||||
|
state = 2
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
sporderid = purdetails.OrderId
|
||||||
|
orderprice = purdetails.Price
|
||||||
|
if len(*orderid) > 0 {
|
||||||
|
// confirm order
|
||||||
|
url = "https://" + hwhost + "/applications/v2/purchases/confirm"
|
||||||
|
confirmbytes, err := hp.sendRequest(gameid, url, bodyMap)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
f5.GetSysLog().Debug("get hw confirm order rsp:%s", confirmbytes)
|
||||||
|
confirmrsp := struct {
|
||||||
|
RspCode string `json:"responseCode"` //"0":OK;其它,错误
|
||||||
|
RspMsg string `json:"responseMessage"`
|
||||||
|
}{}
|
||||||
|
if json.Unmarshal(confirmbytes, &confirmrsp) != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if confirmrsp.RspCode == "0" {
|
||||||
|
state = 1
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*orderid = purdetails.PayLoad
|
||||||
|
state = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// call queryorder first and its return is 1
|
||||||
|
func (hp *hwpay) ConfirmOrder(gameid int64, purchaseToken string, product_id string) (ret bool) {
|
||||||
|
bodyMap := map[string]string{"purchaseToken": purchaseToken, "productId": product_id}
|
||||||
|
|
||||||
|
hosts := mt.Table.Config.GetHwOrderHosts()
|
||||||
|
queryuri := "/applications/v2/purchases/confirm"
|
||||||
|
cfg := mt.Table.Hwconfig.GetById(gameid)
|
||||||
|
if cfg == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, hwhost := range hosts {
|
||||||
|
url := "https://" + hwhost + queryuri
|
||||||
|
confirmbytes, err := hp.sendRequest(gameid, url, bodyMap)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
f5.GetSysLog().Debug("get hw confirm order rsp:%s", confirmbytes)
|
||||||
|
confirmrsp := struct {
|
||||||
|
RspCode string `json:"responseCode"` //"0":OK;其它,错误
|
||||||
|
RspMsg string `json:"responseMessage"`
|
||||||
|
}{}
|
||||||
|
if json.Unmarshal(confirmbytes, &confirmrsp) != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return confirmrsp.RspCode == "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hp *hwpay) GetAccessTokenList(data *[]TokenInfo) {
|
||||||
|
hp.accessTokens.Range(func(key int64, value TokenInfo) bool {
|
||||||
|
*data = append(*data, value)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hp *hwpay) checkAccessToken() {
|
||||||
|
for {
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
|
||||||
|
// if f5.IsOnlineEnv() {
|
||||||
|
gamesGoods.Range(func(gameid int64, value map[int64]GoodsInfo) bool {
|
||||||
|
cfg, ok := hp.accessTokens.Load(gameid)
|
||||||
|
if !ok {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if hp.refreshflag || (cfg != nil && cfg.Expire <= f5.GetApp().GetRealSeconds()) {
|
||||||
|
hp.freshAccessToken(gameid)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
// } else {
|
||||||
|
// if !hp.refreshflag {
|
||||||
|
// hp.accessTokens.Range(func(key int64, value TokenInfo) bool {
|
||||||
|
// if value.Expire <= f5.GetApp().GetRealSeconds() {
|
||||||
|
// hp.refreshflag = true
|
||||||
|
// return false
|
||||||
|
// }
|
||||||
|
// return true
|
||||||
|
// })
|
||||||
|
|
||||||
|
// if !hp.refreshflag {
|
||||||
|
// continue
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// url := "https://payservice.kingsome.cn/api/service/refresh"
|
||||||
|
|
||||||
|
// nowtimestr := q5.SafeToString(f5.GetApp().GetRealSeconds())
|
||||||
|
// params := map[string]string{
|
||||||
|
// "type": "1",
|
||||||
|
// "time": nowtimestr,
|
||||||
|
// "sign": Wxpay.GenSHA256Signature(nowtimestr+constant.GLOBAL_SALT, constant.GLOBAL_SALT),
|
||||||
|
// }
|
||||||
|
// f5.GetHttpCliMgr().SendGoStyleRequest(
|
||||||
|
// url,
|
||||||
|
// params,
|
||||||
|
// func(hcr f5.HttpCliResponse) {
|
||||||
|
// if hcr.GetErr() != nil {
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
|
||||||
|
// rspObj := struct {
|
||||||
|
// Data []TokenInfo `json:"data"`
|
||||||
|
// ErrCode int64 `json:"errcode"`
|
||||||
|
// ErrMsg string `json:"errmsg"`
|
||||||
|
// }{}
|
||||||
|
|
||||||
|
// f5.GetSysLog().Debug("hp get online payservice rsp:%s", hcr.GetRawData())
|
||||||
|
// if json.Unmarshal([]byte(hcr.GetRawData()), &rspObj) != nil {
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if rspObj.ErrCode == 0 {
|
||||||
|
// for _, dataitem := range rspObj.Data {
|
||||||
|
// hp.accessTokens.Store(dataitem.GameId, dataitem)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
|
||||||
|
hp.refreshflag = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hp *hwpay) buildAuthorization(gameid int64) (string, error) {
|
||||||
|
token := hp.getAccessToken(gameid)
|
||||||
|
if token == "" {
|
||||||
|
return "", errors.New("")
|
||||||
|
}
|
||||||
|
oriString := fmt.Sprintf("APPAT:%s", token)
|
||||||
|
var authString = base64.StdEncoding.EncodeToString([]byte(oriString))
|
||||||
|
var authHeaderString = fmt.Sprintf("Basic %s", authString)
|
||||||
|
return authHeaderString, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hp *hwpay) sendRequest(gameid int64, url string, bodyMap map[string]string) ([]byte, error) {
|
||||||
|
authHeader, err := hp.buildAuthorization(gameid)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
bodyString, err := json.Marshal(bodyMap)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := http.NewRequest("POST", url, bytes.NewReader(bodyString))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
req.Header.Set("Content-Type", "application/json; charset=UTF-8")
|
||||||
|
req.Header.Set("Authorization", authHeader)
|
||||||
|
response, err := hp.client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer response.Body.Close()
|
||||||
|
bodyBytes, err := io.ReadAll(response.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return bodyBytes, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hp *hwpay) verifyRsaSign(content string, sign string, publicKey string) error {
|
||||||
|
publicKeyByte, err := base64.StdEncoding.DecodeString(publicKey)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
pub, err := x509.ParsePKIXPublicKey(publicKeyByte)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
hashed := sha256.Sum256([]byte(content))
|
||||||
|
signature, err := base64.StdEncoding.DecodeString(sign)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return rsa.VerifyPKCS1v15(pub.(*rsa.PublicKey), crypto.SHA256, hashed[:], signature)
|
||||||
|
}
|
@ -1,14 +1,78 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"f5"
|
||||||
|
"main/mt"
|
||||||
|
"q5"
|
||||||
|
)
|
||||||
|
|
||||||
|
var gamesGoods q5.ConcurrentMap[int64, map[int64]GoodsInfo] //[gameid, [goodsid]goodsinfo]
|
||||||
type serviceMgr struct {
|
type serviceMgr struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *serviceMgr) Init() {
|
func (this *serviceMgr) Init() {
|
||||||
|
gamesGoods = q5.ConcurrentMap[int64, map[int64]GoodsInfo]{}
|
||||||
|
|
||||||
Wxpay.init()
|
Wxpay.init()
|
||||||
Redis.init()
|
Redis.init()
|
||||||
|
Hwpay.init()
|
||||||
|
|
||||||
|
mt.Table.Wxconfig.Traverse(func(w *mt.Wxconfig) bool {
|
||||||
|
filename := "../res/gamegoods/" + q5.SafeToString(w.GetGameid()) + ".json"
|
||||||
|
str, err := f5.ReadJsonFile(filename)
|
||||||
|
if err != nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
data := []map[string]interface{}{}
|
||||||
|
if json.Unmarshal([]byte(str), &data) != nil {
|
||||||
|
f5.GetSysLog().Error("parse [%s] error.", filename)
|
||||||
|
} else {
|
||||||
|
gamegoods := map[int64]GoodsInfo{}
|
||||||
|
for _, data := range data {
|
||||||
|
gamegoods[q5.SafeToInt64(data["id"])] = GoodsInfo{
|
||||||
|
Name: q5.SafeToString(data["name"]),
|
||||||
|
Count: q5.SafeToInt64(data["count"]),
|
||||||
|
Price: q5.SafeToInt64(data["price"]) * 100,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gamesGoods.Store(w.GetGameid(), gamegoods)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *serviceMgr) UnInit() {
|
func (this *serviceMgr) UnInit() {
|
||||||
Wxpay.unInit()
|
Wxpay.unInit()
|
||||||
Redis.unInit()
|
Redis.unInit()
|
||||||
|
Hwpay.unInit()
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetGoodsCount(gameid int64, goodsid int64) (count int64, err error) {
|
||||||
|
goods, ok := gamesGoods.Load(gameid)
|
||||||
|
if !ok {
|
||||||
|
return 0, errors.New("no game")
|
||||||
|
}
|
||||||
|
|
||||||
|
info, ok := (*goods)[goodsid]
|
||||||
|
if !ok {
|
||||||
|
return 0, errors.New("no goods")
|
||||||
|
}
|
||||||
|
|
||||||
|
return info.Count, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetGoodsName(gameid int64, goodsid int64) (name string, err error) {
|
||||||
|
goods, ok := gamesGoods.Load(gameid)
|
||||||
|
if !ok {
|
||||||
|
return "", errors.New("no game")
|
||||||
|
}
|
||||||
|
|
||||||
|
info, ok := (*goods)[goodsid]
|
||||||
|
if !ok {
|
||||||
|
return "", errors.New("no goods")
|
||||||
|
}
|
||||||
|
|
||||||
|
return info.Name, nil
|
||||||
}
|
}
|
@ -4,7 +4,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"f5"
|
"f5"
|
||||||
"main/constant"
|
"main/constant"
|
||||||
"main/mt"
|
"main/mt"
|
||||||
@ -30,7 +29,6 @@ type mediaidInfo struct {
|
|||||||
time int64
|
time int64
|
||||||
}
|
}
|
||||||
type wxpay struct {
|
type wxpay struct {
|
||||||
gamesGoods q5.ConcurrentMap[int64, map[int64]GoodsInfo] //[gameid, [goodsid]goodsinfo]
|
|
||||||
accessTokens q5.ConcurrentMap[int64, TokenInfo] //[gameid, TokenInfo]
|
accessTokens q5.ConcurrentMap[int64, TokenInfo] //[gameid, TokenInfo]
|
||||||
expireInfo q5.ConcurrentMap[string, *expireSession] //[accountid, expireSession]
|
expireInfo q5.ConcurrentMap[string, *expireSession] //[accountid, expireSession]
|
||||||
mediaInfo q5.ConcurrentMap[int64, mediaidInfo] //[gameid, mediainfo]
|
mediaInfo q5.ConcurrentMap[int64, mediaidInfo] //[gameid, mediainfo]
|
||||||
@ -120,7 +118,6 @@ type GoodsInfo struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (wp *wxpay) init() {
|
func (wp *wxpay) init() {
|
||||||
wp.gamesGoods = q5.ConcurrentMap[int64, map[int64]GoodsInfo]{}
|
|
||||||
wp.accessTokens = q5.ConcurrentMap[int64, TokenInfo]{}
|
wp.accessTokens = q5.ConcurrentMap[int64, TokenInfo]{}
|
||||||
wp.expireInfo = q5.ConcurrentMap[string, *expireSession]{}
|
wp.expireInfo = q5.ConcurrentMap[string, *expireSession]{}
|
||||||
|
|
||||||
@ -142,7 +139,6 @@ func (wp *wxpay) init() {
|
|||||||
Price: q5.SafeToInt64(data["price"]) * 100,
|
Price: q5.SafeToInt64(data["price"]) * 100,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wp.gamesGoods.Store(w.GetGameid(), gamegoods)
|
|
||||||
wp.accessTokens.Store(w.GetGameid(), TokenInfo{})
|
wp.accessTokens.Store(w.GetGameid(), TokenInfo{})
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@ -229,34 +225,6 @@ func (wp *wxpay) getAccessToken(gameid int64) (token string) {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wp *wxpay) GetGoodsCount(gameid int64, goodsid int64) (count int64, err error) {
|
|
||||||
goods, ok := wp.gamesGoods.Load(gameid)
|
|
||||||
if !ok {
|
|
||||||
return 0, errors.New("no game")
|
|
||||||
}
|
|
||||||
|
|
||||||
info, ok := (*goods)[goodsid]
|
|
||||||
if !ok {
|
|
||||||
return 0, errors.New("no goods")
|
|
||||||
}
|
|
||||||
|
|
||||||
return info.Count, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wp *wxpay) GetGoodsName(gameid int64, goodsid int64) (name string, err error) {
|
|
||||||
goods, ok := wp.gamesGoods.Load(gameid)
|
|
||||||
if !ok {
|
|
||||||
return "", errors.New("no game")
|
|
||||||
}
|
|
||||||
|
|
||||||
info, ok := (*goods)[goodsid]
|
|
||||||
if !ok {
|
|
||||||
return "", errors.New("no goods")
|
|
||||||
}
|
|
||||||
|
|
||||||
return info.Name, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wp *wxpay) QueryBalance(openid string, gameid int64, userip string, sessionkey string) (balance int64, wxerrcode int32, err error) {
|
func (wp *wxpay) QueryBalance(openid string, gameid int64, userip string, sessionkey string) (balance int64, wxerrcode int32, err error) {
|
||||||
cfg := mt.Table.Wxconfig.GetById(gameid)
|
cfg := mt.Table.Wxconfig.GetById(gameid)
|
||||||
postbody := struct {
|
postbody := struct {
|
||||||
@ -543,7 +511,7 @@ func (wp *wxpay) checkAccessToken() {
|
|||||||
time.Sleep(time.Second)
|
time.Sleep(time.Second)
|
||||||
|
|
||||||
if f5.IsOnlineEnv() {
|
if f5.IsOnlineEnv() {
|
||||||
wp.gamesGoods.Range(func(gameid int64, value map[int64]GoodsInfo) bool {
|
gamesGoods.Range(func(gameid int64, value map[int64]GoodsInfo) bool {
|
||||||
cfg, _ := wp.accessTokens.Load(gameid)
|
cfg, _ := wp.accessTokens.Load(gameid)
|
||||||
if wp.refreshflag || (cfg != nil && cfg.Expire <= f5.GetApp().GetRealSeconds()) {
|
if wp.refreshflag || (cfg != nil && cfg.Expire <= f5.GetApp().GetRealSeconds()) {
|
||||||
wp.freshAccessToken(gameid)
|
wp.freshAccessToken(gameid)
|
||||||
|
@ -187,7 +187,7 @@ func (wp *wxpay) GetPrepayInfoStr(openid string, gameid int64, userip string, or
|
|||||||
svc := jsapi.JsapiApiService{Client: wp.client}
|
svc := jsapi.JsapiApiService{Client: wp.client}
|
||||||
// 得到prepay_id,以及调起支付所需的参数和签名
|
// 得到prepay_id,以及调起支付所需的参数和签名
|
||||||
cfg := mt.Table.Wxconfig.GetById(gameid)
|
cfg := mt.Table.Wxconfig.GetById(gameid)
|
||||||
goods, ok := wp.gamesGoods.Load(gameid)
|
goods, ok := gamesGoods.Load(gameid)
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user