jspay
This commit is contained in:
parent
4effa9ed0d
commit
7cf416e643
@ -4,8 +4,11 @@
|
||||
"wx_notify_token": "dV93f4FwSGMwkYcvsRHD8egdW5egPMhF",
|
||||
"wx_notify_encoding_aes_key": "t7zDjlqSow7OY4s61q8wp4EabjWnUtTSi5w0KM48O1K",
|
||||
"wx_merchant_id": "1509252791",
|
||||
"wx_certificate_sn": "1234",
|
||||
"wx_merchant_api_key": "123",
|
||||
"wx_certificate_sn": "3490963E4E2767E6D8EC99CFE406A2CBEB3CD195",
|
||||
"wx_merchant_api_key": "fgRnUvC5Zu04ir9HQPHWesrsh49ZnfpC",
|
||||
"wx_msg_notify_token": "kingsome",
|
||||
"wx_msg_notify_encoding_aes_key": "2L02BseGYDjPRK6xSf00pv3PzWtOq2c3d8NhZHAVYbL"
|
||||
"wx_msg_notify_encoding_aes_key": "2LO2BseGYDjPRK6xSf0Opv3PzWtOq2c3d8NhZHAVYbL",
|
||||
"wx_nofity_host": "https://payservice-test.kingsome.cn",
|
||||
"wx_link_title": "点我充值",
|
||||
"wx_link_description": "充值后返回游戏查看"
|
||||
}
|
||||
|
39
bin/payserver/config/payhtml.template
Normal file
39
bin/payserver/config/payhtml.template
Normal file
@ -0,0 +1,39 @@
|
||||
<html>
|
||||
<script>
|
||||
function onBridgeReady() {
|
||||
WeixinJSBridge.invoke('getBrandWCPayRequest', {
|
||||
"appId": "%s",
|
||||
"timeStamp": "%s",
|
||||
"nonceStr": "%s",
|
||||
"package": "%s",
|
||||
"signType": "RSA",
|
||||
"paySign":"%s"
|
||||
},
|
||||
function(res) {
|
||||
console.log(res.err_msg)
|
||||
if (res.err_msg == "get_brand_wcpay_request:ok") { // 支付成功
|
||||
document.write("payment success");
|
||||
WeixinJSBridge.call('closeWindow');
|
||||
}
|
||||
if (res.err_msg == "get_brand_wcpay_request:fail") { // 支付失败
|
||||
document.write("payment fail");
|
||||
WeixinJSBridge.call('closeWindow');
|
||||
}
|
||||
if (res.err_msg == "get_brand_wcpay_request:cancel") { // 支付取消
|
||||
document.write("payment cancel");
|
||||
WeixinJSBridge.call('closeWindow');
|
||||
}
|
||||
});
|
||||
}
|
||||
if (typeof WeixinJSBridge == "undefined") {
|
||||
if (document.addEventListener) {
|
||||
document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
|
||||
} else if (document.attachEvent) {
|
||||
document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
|
||||
document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
|
||||
}
|
||||
} else {
|
||||
onBridgeReady();
|
||||
}
|
||||
</script>
|
||||
</html>
|
BIN
bin/payserver/res/gamepics/1004.jpg
Normal file
BIN
bin/payserver/res/gamepics/1004.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 142 KiB |
BIN
bin/payserver/res/gamepics/2004.jpg
Normal file
BIN
bin/payserver/res/gamepics/2004.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 172 KiB |
28
bin/payserver/res/kingsome_key.pem
Normal file
28
bin/payserver/res/kingsome_key.pem
Normal file
@ -0,0 +1,28 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDe5kueQMqnwK2N
|
||||
FSeRn+s6smlNG9xvDy64Y6s5kRdRF0h4Qe8VhAF5ooh54IQDubk/zHT+zeF6mpUT
|
||||
2LhkoPc6yeq0CU6NHpIUcrjul2UMq1wuDTsyGN2FbYGKBozsHw059drgMyIw+GPv
|
||||
tMpr8cT5/z/BtRQzHdXdoHqPUcWChknRWVkeOU1sQsWeY0Y/c//s1tT7DzzNm8HC
|
||||
Yh3tuwkcAav0VnXrHblbeCfqng3ukSxnxCxJo+b/y1w95KR/1qSrak6MJW+QVW6N
|
||||
lDhmzTE0QQ+4ZHPWsmtmbFjkCsoMDqd/WLDWPBH4o1YpPXlkjBIeaLxYAh31uuuv
|
||||
YG1OnWE3AgMBAAECggEAEg5737UF9bLxHDWzf+OBjb64MwvnvoNvWHaSf1ZWmjYV
|
||||
o9BLiuWnrO/SuHTMnPSlohpw+9c3xdPR8cqjnVtAy91hivYaC+qHEOr+Oi2/fNhA
|
||||
3mYp/nPvNgjZ7pF7RwF489ILyg+6XFcy2U8++qGaQFpCEvIVUdK/6XU/mG6aXmlV
|
||||
wDob+aPsbzupFmoZ4R22aalQlg/QnOSKuI2jF2k6esCNjgRs4qTriDpMaqjGhn69
|
||||
w9llRd7RaLzc/QtBoCZLy36GutTepckZtOmRQKlexoIPqXW+krZzU/ZoZbp30GQi
|
||||
MFoZKcoZPvoxP8cqalNxA9HFA9X5BMX5eW92o4sEiQKBgQD6qTh73jmr7mS3ySgM
|
||||
Q/ILZtqdIg0/TWdivtlZZBHrfe3luA/5554XfsmpuAdu2jQygxI/jsDFaxcRqRcv
|
||||
Rpx1T3xwvrupRu1pU0/1EYJDpneWowb7wuchN0+DghbG9sIAe95vpZKvMLOPBnUQ
|
||||
foARTQ8ZIVNFu/v7psAWh2lpiwKBgQDjpbMzxM0kEFrtqqTcw0ErkpVzCy96NjpF
|
||||
ykejvu2kP6kxf1muQWwklE/B/zmMQrzr4Y2PmrhYt79AHzr7QW2vx3G8wSLqkJdZ
|
||||
RkKdlwjkyJ+PxRuAo3C7DBHGFx9Jlm9kG+lHzTgp4LNY6Afn+5uur8BOUTRfcltB
|
||||
Q78+kkYkhQKBgQDFwOuHDfOB6TocpN6rjo9O335pqYu5/V8rUFY5Z/GbUGZ3bZdt
|
||||
GYZoEucWttFma0/y6eVjr0P2fF5e2IAqFBMrmeIbMN7s1cBH8CqMtZuHs7V1anj/
|
||||
9uxSEEjy/5bosZSsvQzoGEB5ZnrCw91nfeWbwKfAs8H2qjBKgWvaWkqXsQKBgG0k
|
||||
m5ddarE4ui+qmeJSJuO6IrcGjNu+NhAR3GkQeCVAdGEL2rZmHXAoP1kWgcPSl3tM
|
||||
J6/LEUlPx3z5vDCMfQdCyzAhNRla+4VM31FpAVWXLpEign4ZXkn/jmH34gNJAdzw
|
||||
WNcY+C1z0uj0Th4WDt0g3EVwP3jnfgL7dSyNut11AoGAfOArrHKF/7WSQLH42ARs
|
||||
2ZwQ5qZsaqkXkZeqyh3SXsyqXqOUwKs+aD8ASs4Mt4oEk1+q5byQySRTRfPlgYjG
|
||||
AgHJcXGiR5uMu3Ca0fKpaNasYbPR5j/UO6vAzs1RvCKQkcQuvgSqkoB8R7jmjIYa
|
||||
5QeJpvz8Qwj/FQlkmh16wQ8=
|
||||
-----END PRIVATE KEY-----
|
@ -25,11 +25,18 @@ func (this *InGameApi) PreOrder(c *gin.Context) {
|
||||
f5.RspErr(c, 401, "params error")
|
||||
return
|
||||
}
|
||||
|
||||
data, ret := this.checkSessionData(c, reqJson.AccountId)
|
||||
if !ret {
|
||||
return
|
||||
}
|
||||
|
||||
nowTime := int32(f5.GetApp().GetRealSeconds())
|
||||
order := new(model.InAppOrder)
|
||||
order.AccountId = reqJson.AccountId
|
||||
order.OrderId = q5.ToString(f5.GetApp().NewLockNodeUuid())
|
||||
order.ItemId = reqJson.GoodsId
|
||||
order.GameId = q5.SafeToInt32(data["gameid"])
|
||||
order.IP = this.getIP(c)
|
||||
|
||||
order.CreateTime = nowTime
|
||||
@ -110,37 +117,12 @@ func (this *InGameApi) PayDone(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
strs := strings.Split(accountId, "_")
|
||||
if len(strs) < 3 {
|
||||
f5.RspErr(c, 401, "params error1")
|
||||
data, ret := this.checkSessionData(c, accountId)
|
||||
if !ret {
|
||||
return
|
||||
}
|
||||
|
||||
rediskey := "ls:accountid:" + accountId
|
||||
str, err := service.Redis.Get(constant.LOGIN_REDIS, rediskey)
|
||||
if err != nil {
|
||||
f5.RspErr(c, 402, "invalid session")
|
||||
return
|
||||
}
|
||||
|
||||
data := map[string]interface{}{}
|
||||
if json.Unmarshal([]byte(str), &data) != nil {
|
||||
f5.RspErr(c, 402, "invalid session 1")
|
||||
return
|
||||
}
|
||||
|
||||
sessionkey := q5.SafeToString(data["session_key"])
|
||||
if len(sessionkey) == 0 {
|
||||
f5.GetSysLog().Debug("empty sessionkey:%s", accountId)
|
||||
f5.RspErr(c, 402, "invalid session 2")
|
||||
return
|
||||
}
|
||||
|
||||
sessionkeytime := q5.SafeToInt64(data["update_time"])
|
||||
if service.Wxpay.CheckExpireCache(accountId, sessionkeytime) {
|
||||
f5.RspErr(c, 402, "session expired")
|
||||
return
|
||||
}
|
||||
sessionkey := q5.SafeToString(data["session_key"])
|
||||
|
||||
status := orderModel.Status
|
||||
rspObj := struct {
|
||||
@ -151,8 +133,8 @@ func (this *InGameApi) PayDone(c *gin.Context) {
|
||||
}{
|
||||
OrderId: orderid,
|
||||
}
|
||||
for status < 2 {
|
||||
gameid := q5.SafeToInt64(strs[1])
|
||||
if status < 2 {
|
||||
gameid := q5.SafeToInt64(data["gameid"])
|
||||
openid := q5.SafeToString(data["openid"])
|
||||
userip := this.getIP(c)
|
||||
balance, errcode, err := int64(0), int32(0), error(nil)
|
||||
@ -181,8 +163,6 @@ func (this *InGameApi) PayDone(c *gin.Context) {
|
||||
rspObj.ErrorCode = 402
|
||||
rspObj.ErrMsg = "session overtime"
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
c.JSON(200, rspObj)
|
||||
@ -202,12 +182,6 @@ func (this *InGameApi) ServerPrePurchase(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
strs := strings.Split(req.AccountId, "_")
|
||||
if len(strs) < 3 {
|
||||
f5.RspErr(c, 401, "params error1")
|
||||
return
|
||||
}
|
||||
|
||||
if !strings.EqualFold(q5.Md5Str(req.AccountId+constant.GLOBAL_SALT+req.SessionId), req.Sign) {
|
||||
f5.RspErr(c, 401, "sign err")
|
||||
return
|
||||
@ -225,38 +199,20 @@ func (this *InGameApi) ServerPrePurchase(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
rediskey := "ls:accountid:" + req.AccountId
|
||||
str, err := service.Redis.Get(constant.LOGIN_REDIS, rediskey)
|
||||
if err != nil {
|
||||
f5.RspErr(c, 402, "invalid session")
|
||||
data, ret := this.checkSessionData(c, req.AccountId)
|
||||
if !ret {
|
||||
return
|
||||
}
|
||||
|
||||
data := map[string]interface{}{}
|
||||
if json.Unmarshal([]byte(str), &data) != nil {
|
||||
f5.RspErr(c, 402, "invalid session 1")
|
||||
return
|
||||
}
|
||||
sessionkey := q5.SafeToString(data["session_key"])
|
||||
|
||||
sessionkey := q5.SafeToString(data["session_key"])
|
||||
if len(sessionkey) == 0 {
|
||||
f5.GetSysLog().Debug("empty sessionkey:%s", req.AccountId)
|
||||
f5.RspErr(c, 402, "invalid session 2")
|
||||
return
|
||||
}
|
||||
|
||||
sessionkeytime := q5.SafeToInt64(data["update_time"])
|
||||
if service.Wxpay.CheckExpireCache(req.AccountId, sessionkeytime) {
|
||||
f5.RspErr(c, 402, "session expired")
|
||||
return
|
||||
}
|
||||
|
||||
gameid := q5.SafeToInt64(strs[1])
|
||||
gameid := q5.SafeToInt64(data["gameid"])
|
||||
|
||||
nowTime := int32(f5.GetApp().GetRealSeconds())
|
||||
order := new(model.InAppOrder)
|
||||
order.AccountId = req.AccountId
|
||||
order.OrderId = q5.ToString(f5.GetApp().NewLockNodeUuid())
|
||||
order.OrderId = "p" + q5.ToString(f5.GetApp().NewLockNodeUuid())
|
||||
order.GameId = int32(gameid)
|
||||
order.ItemId = goodsid
|
||||
order.IP = req.UserIp
|
||||
|
||||
@ -308,35 +264,8 @@ func (this *InGameApi) OrderInfo(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
strs := strings.Split(reqJson.AccountId, "_")
|
||||
if len(strs) < 3 {
|
||||
f5.RspErr(c, 401, "params error1")
|
||||
return
|
||||
}
|
||||
|
||||
rediskey := "ls:accountid:" + reqJson.AccountId
|
||||
str, err := service.Redis.Get(constant.LOGIN_REDIS, rediskey)
|
||||
if err != nil {
|
||||
f5.RspErr(c, 402, "invalid session")
|
||||
return
|
||||
}
|
||||
|
||||
data := map[string]interface{}{}
|
||||
if json.Unmarshal([]byte(str), &data) != nil {
|
||||
f5.RspErr(c, 402, "invalid session 1")
|
||||
return
|
||||
}
|
||||
|
||||
sessionkey := q5.SafeToString(data["session_key"])
|
||||
if len(sessionkey) == 0 {
|
||||
f5.GetSysLog().Debug("empty sessionkey:%s", reqJson.AccountId)
|
||||
f5.RspErr(c, 402, "invalid session 2")
|
||||
return
|
||||
}
|
||||
|
||||
sessionkeytime := q5.SafeToInt64(data["update_time"])
|
||||
if service.Wxpay.CheckExpireCache(reqJson.AccountId, sessionkeytime) {
|
||||
f5.RspErr(c, 402, "session expired")
|
||||
data, ret := this.checkSessionData(c, reqJson.AccountId)
|
||||
if !ret {
|
||||
return
|
||||
}
|
||||
|
||||
@ -368,9 +297,10 @@ func (this *InGameApi) OrderInfo(c *gin.Context) {
|
||||
c.JSON(200, rspObj)
|
||||
|
||||
if orderModel.Status == 0 {
|
||||
gameid := q5.SafeToInt64(strs[1])
|
||||
gameid := q5.SafeToInt64(data["gameid"])
|
||||
openid := q5.SafeToString(data["openid"])
|
||||
userip := this.getIP(c)
|
||||
sessionkey := q5.SafeToString(data["session_key"])
|
||||
balance, errcode, err := service.Wxpay.QueryBalance(openid, gameid, userip, sessionkey)
|
||||
if err != nil {
|
||||
return
|
||||
@ -394,6 +324,7 @@ func (this *InGameApi) OrderInfo(c *gin.Context) {
|
||||
}
|
||||
|
||||
if errcode == constant.WX_ERRCODE_SESSIONERR || errcode == constant.WX_ERRCODE_SIGERR {
|
||||
sessionkeytime := q5.SafeToInt64(data["update_time"])
|
||||
service.Wxpay.AddExpireInfo(reqJson.AccountId, sessionkeytime)
|
||||
}
|
||||
} else if orderModel.Status == 1 {
|
||||
@ -412,45 +343,20 @@ func (this *InGameApi) OtherOrder(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
strs := strings.Split(reqJson.AccountId, "_")
|
||||
if len(strs) < 3 {
|
||||
f5.RspErr(c, 401, "params error1")
|
||||
return
|
||||
}
|
||||
|
||||
rediskey := "ls:accountid:" + reqJson.AccountId
|
||||
str, err := service.Redis.Get(constant.LOGIN_REDIS, rediskey)
|
||||
if err != nil {
|
||||
f5.RspErr(c, 402, "invalid session")
|
||||
return
|
||||
}
|
||||
|
||||
data := map[string]interface{}{}
|
||||
if json.Unmarshal([]byte(str), &data) != nil {
|
||||
f5.RspErr(c, 402, "invalid session 1")
|
||||
return
|
||||
}
|
||||
|
||||
sessionkey := q5.SafeToString(data["session_key"])
|
||||
if len(sessionkey) == 0 {
|
||||
f5.GetSysLog().Debug("empty sessionkey:%s", reqJson.AccountId)
|
||||
f5.RspErr(c, 402, "invalid session 2")
|
||||
data, ret := this.checkSessionData(c, reqJson.AccountId)
|
||||
if !ret {
|
||||
return
|
||||
}
|
||||
|
||||
sessionkey := q5.SafeToString(data["session_key"])
|
||||
sessionkeytime := q5.SafeToInt64(data["update_time"])
|
||||
if service.Wxpay.CheckExpireCache(reqJson.AccountId, sessionkeytime) {
|
||||
f5.RspErr(c, 402, "session expired")
|
||||
return
|
||||
}
|
||||
|
||||
rspObj := struct {
|
||||
ErrorCode int32 `json:"errcode"`
|
||||
ErrMsg string `json:"errmsg"`
|
||||
Count int64 `json:"count"`
|
||||
}{}
|
||||
|
||||
gameid := q5.SafeToInt64(strs[1])
|
||||
gameid := q5.SafeToInt64(data["gameid"])
|
||||
openid := q5.SafeToString(data["openid"])
|
||||
userip := this.getIP(c)
|
||||
balance, errcode, err := service.Wxpay.QueryBalance(openid, gameid, userip, sessionkey)
|
||||
@ -467,8 +373,8 @@ func (this *InGameApi) OtherOrder(c *gin.Context) {
|
||||
|
||||
errcode = service.Wxpay.QueryPay(openid, gameid, userip, sessionkey, int32(balance), order.OrderId)
|
||||
if errcode == constant.WX_ERRCODE_OK {
|
||||
order.GameId = int32(gameid)
|
||||
order.Channel = q5.SafeToInt32(strs[0])
|
||||
order.GameId = int32(gameid)
|
||||
order.Channel = q5.SafeToInt32(data["channel"])
|
||||
order.IP = this.getIP(c)
|
||||
order.Status = 2
|
||||
order.SpOthers = int32(balance)
|
||||
@ -489,6 +395,124 @@ func (this *InGameApi) OtherOrder(c *gin.Context) {
|
||||
c.JSON(200, rspObj)
|
||||
}
|
||||
|
||||
func (this *InGameApi) QueryPay(c *gin.Context) {
|
||||
reqJson := struct {
|
||||
AccountId string `json:"account_id" binding:"required"`
|
||||
SessionId string `json:"session_id" binding:"required"`
|
||||
OrderId string `json:"order_id" binding:"required"`
|
||||
}{}
|
||||
if err := c.ShouldBindJSON(&reqJson); err != nil {
|
||||
f5.RspErr(c, 401, "params error")
|
||||
return
|
||||
}
|
||||
|
||||
_, ret := this.checkSessionData(c, reqJson.AccountId)
|
||||
if !ret {
|
||||
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"`
|
||||
Count int32 `json:"count"`
|
||||
Others int32 `json:"others"`
|
||||
Status int32 `json:"status"`
|
||||
}{
|
||||
OrderId: orderModel.OrderId,
|
||||
GoodsId: orderModel.ItemId,
|
||||
Count: orderModel.SpAmount,
|
||||
Others: orderModel.SpOthers,
|
||||
Status: orderModel.Status,
|
||||
}
|
||||
|
||||
c.JSON(200, rspObj)
|
||||
|
||||
if orderModel.Status == 0 {
|
||||
// gameid := q5.SafeToInt64(data["gameid"])
|
||||
// openid := q5.SafeToString(data["openid"])
|
||||
// userip := this.getIP(c)
|
||||
// sessionkey := q5.SafeToString(data["session_key"])
|
||||
// balance, errcode, err := service.Wxpay.QueryBalance(openid, gameid, userip, sessionkey)
|
||||
// if err != nil {
|
||||
// return
|
||||
// }
|
||||
|
||||
// if errcode == constant.WX_ERRCODE_OK {
|
||||
// count, err := service.Wxpay.GetGoodsCount(gameid, int64(orderModel.ItemId))
|
||||
// if err != nil {
|
||||
// return
|
||||
// }
|
||||
|
||||
// if balance >= count {
|
||||
// errcode = service.Wxpay.QueryPay(openid, gameid, userip, sessionkey, int32(balance), orderModel.OrderId)
|
||||
// if errcode == constant.WX_ERRCODE_OK {
|
||||
// orderModel.Status = 1
|
||||
// orderModel.SpAmount = int32(count)
|
||||
// orderModel.SpOthers = int32(balance - count)
|
||||
// orderModel.UpdateFields([]string{"status", "sp_amount", "sp_others"})
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// if errcode == constant.WX_ERRCODE_SESSIONERR || errcode == constant.WX_ERRCODE_SIGERR {
|
||||
// sessionkeytime := q5.SafeToInt64(data["update_time"])
|
||||
// service.Wxpay.AddExpireInfo(reqJson.AccountId, sessionkeytime)
|
||||
// }
|
||||
} else if orderModel.Status == 1 {
|
||||
orderModel.Status = 2
|
||||
orderModel.UpdateFields([]string{"status"})
|
||||
}
|
||||
}
|
||||
|
||||
func (iga *InGameApi) checkSessionData(c *gin.Context, accountId string) (data map[string]interface{}, ret bool){
|
||||
strs := strings.Split(accountId, "_")
|
||||
if len(strs) < 3 {
|
||||
f5.RspErr(c, 401, "params error1")
|
||||
return
|
||||
}
|
||||
|
||||
rediskey := "ls:accountid:" + accountId
|
||||
str, err := service.Redis.Get(constant.LOGIN_REDIS, rediskey)
|
||||
if err != nil {
|
||||
f5.RspErr(c, 402, "invalid session")
|
||||
return
|
||||
}
|
||||
|
||||
data = map[string]interface{}{}
|
||||
if json.Unmarshal([]byte(str), &data) != nil {
|
||||
f5.RspErr(c, 402, "invalid session 1")
|
||||
return
|
||||
}
|
||||
|
||||
sessionkey := q5.SafeToString(data["session_key"])
|
||||
if len(sessionkey) == 0 {
|
||||
f5.GetSysLog().Debug("empty sessionkey:%s", accountId)
|
||||
f5.RspErr(c, 402, "invalid session 2")
|
||||
return
|
||||
}
|
||||
|
||||
sessionkeytime := q5.SafeToInt64(data["update_time"])
|
||||
if service.Wxpay.CheckExpireCache(accountId, sessionkeytime) {
|
||||
f5.RspErr(c, 402, "session expired")
|
||||
return
|
||||
}
|
||||
|
||||
data["channel"] = strs[0]
|
||||
data["gameid"] = strs[1]
|
||||
return data, true
|
||||
}
|
||||
|
||||
func (iga *InGameApi) getIP(c *gin.Context) (ip string) {
|
||||
ip = c.Request.Header.Get("X-Real-Ip")
|
||||
if ip == "" {
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"f5"
|
||||
"fmt"
|
||||
"io"
|
||||
"main/constant"
|
||||
"main/model"
|
||||
@ -307,20 +308,10 @@ func (this *MainServiceApi) WxMsgNotify(c *gin.Context) {
|
||||
postObj := struct {
|
||||
ToUserName string `json:"ToUserName"` //小程序的原始 ID
|
||||
Encrypt string `json:"Encrypt"`
|
||||
// FromUserName string `json:"FromUserName"` //发送者的 openid
|
||||
// CreateTime int64 `json:"CreateTime"`
|
||||
// MsgType string `json:"MsgType"`
|
||||
// Content string `json:"Content"`
|
||||
// MediaId string `json:"MediaId"`
|
||||
// PicUrl string `json:"PicUrl"`
|
||||
// MsgId int64 `json:"MsgId"`
|
||||
// Event string `json:"Event"`
|
||||
// SessionFrom string `json:"SessionFrom"`
|
||||
}{}
|
||||
|
||||
if err := c.ShouldBindJSON(&postObj); err != nil {
|
||||
rspObj.ErrorCode = 401
|
||||
rspObj.ErrMsg = "msg post data error"
|
||||
f5.GetSysLog().Debug("post data error ")
|
||||
c.JSON(200, rspObj)
|
||||
return
|
||||
}
|
||||
@ -332,158 +323,223 @@ func (this *MainServiceApi) WxMsgNotify(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
f5.GetSysLog().Debug("wx msg decrypt msg:%s", smsg)
|
||||
rspObj.ErrorCode = 0
|
||||
rspObj.ErrMsg = "success"
|
||||
defer c.JSON(200, rspObj)
|
||||
|
||||
// wxnotifyobj := service.WxPurchaseNotify{}
|
||||
// if json.Unmarshal(smsg, &wxnotifyobj) != nil {
|
||||
// f5.GetSysLog().Debug("unmarshal data error")
|
||||
// c.JSON(200, rspObj)
|
||||
// return
|
||||
// }
|
||||
wxmsg := struct {
|
||||
ToUserName string `json:"ToUserName"` //小程序的原始 ID
|
||||
FromUserName string `json:"FromUserName"` //发送者的 openid
|
||||
CreateTime int64 `json:"CreateTime"`
|
||||
MsgType string `json:"MsgType"`
|
||||
Content string `json:"Content"`
|
||||
MediaId string `json:"MediaId"`
|
||||
PicUrl string `json:"PicUrl"`
|
||||
MsgId int64 `json:"MsgId"`
|
||||
Event string `json:"Event"`
|
||||
SessionFrom string `json:"SessionFrom"`
|
||||
}{}
|
||||
|
||||
// gameid := int64(0)
|
||||
// appkey := ""
|
||||
// notifyurl := ""
|
||||
// mt.Table.Wxconfig.Traverse(func(w *mt.Wxconfig) bool {
|
||||
// if w.GetAppid() == string(appid) {
|
||||
// gameid = w.GetGameid()
|
||||
// appkey = w.GetAppkey()
|
||||
// notifyurl = w.GetNotifyurl()
|
||||
// return false
|
||||
// }
|
||||
// return true
|
||||
// })
|
||||
f5.GetSysLog().Debug("wx msg notify decrypted data:%s", smsg)
|
||||
if err := json.Unmarshal(smsg, &wxmsg); err != nil {
|
||||
f5.GetSysLog().Debug("decrypt msg data error")
|
||||
return
|
||||
}
|
||||
|
||||
// if appkey == "" {
|
||||
// f5.GetSysLog().Error("wx app config error:%s", appid)
|
||||
// c.JSON(200, rspObj)
|
||||
// return
|
||||
// }
|
||||
if wxmsg.MsgType != "event" || wxmsg.Event != "user_enter_tempsession" {
|
||||
return
|
||||
}
|
||||
|
||||
// oristr := wxnotifyobj.Event + "&" + wxnotifyobj.MiniGame.Payload
|
||||
// sig := service.Wxpay.GenSHA256Signature(oristr, appkey)
|
||||
// if sig != wxnotifyobj.MiniGame.PayEventSig {
|
||||
// f5.GetSysLog().Error("pay event sig error:%s, %s, %s", appid, sig, wxnotifyobj.MiniGame.PayEventSig)
|
||||
// c.JSON(200, rspObj)
|
||||
// return
|
||||
// }
|
||||
strs := q5.StrSplit(wxmsg.SessionFrom, ":")
|
||||
if len(strs) < 2 || strs[0] != "prepare_pay_from_game" {
|
||||
return
|
||||
}
|
||||
|
||||
// if wxnotifyobj.MiniGame.IsMock {
|
||||
// rspObj.ErrorCode = 0
|
||||
// rspObj.ErrMsg = "Success"
|
||||
// c.JSON(200, rspObj)
|
||||
// return
|
||||
// }
|
||||
orderid := strs[1]
|
||||
orderModel := new(model.InAppOrder)
|
||||
if err, found := orderModel.FindByOrderId(orderid); err != nil || !found {
|
||||
return
|
||||
}
|
||||
|
||||
// payloadobj := new(service.WxPayload)
|
||||
// if json.Unmarshal([]byte(wxnotifyobj.MiniGame.Payload), &payloadobj) != nil {
|
||||
// c.JSON(200, rspObj)
|
||||
// return
|
||||
// }
|
||||
thumburl := service.Wxpay.GenThumburl(int64(orderModel.GameId))
|
||||
|
||||
// envpass := true
|
||||
// if f5.IsOnlineEnv() {
|
||||
// if payloadobj.Env != 0 {
|
||||
// f5.GetSysLog().Error("notify test info to prod url")
|
||||
// envpass = false
|
||||
// }
|
||||
// } else {
|
||||
// if payloadobj.Env != 1 {
|
||||
// f5.GetSysLog().Error("notify prod info to test url")
|
||||
// envpass = false
|
||||
// }
|
||||
// }
|
||||
// 发给客服系统的clicklink
|
||||
clickurl := fmt.Sprintf("%s/wx/clicknotify?orderid=%s", mt.Table.Config.GetWxNofityHost(), orderid)
|
||||
req := struct {
|
||||
ToUser string `json:"touser"`
|
||||
MsgType string `json:"msgtype"`
|
||||
Link interface{} `json:"link"`
|
||||
}{
|
||||
ToUser: wxmsg.FromUserName,
|
||||
MsgType: "link",
|
||||
Link: struct {
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
Url string `json:"url"`
|
||||
Thumb_url string `json:"thumb_url"`
|
||||
}{
|
||||
Title: mt.Table.Config.GetWxLinkTitle(),
|
||||
Description: mt.Table.Config.GetWxLinkDescription(),
|
||||
Url: clickurl,
|
||||
Thumb_url: thumburl,
|
||||
},
|
||||
}
|
||||
|
||||
// if !envpass {
|
||||
// c.JSON(200, rspObj)
|
||||
// return
|
||||
// }
|
||||
postbytes, err := json.Marshal(req)
|
||||
|
||||
// orderModel := new(model.InAppOrder)
|
||||
// if err, found := orderModel.FindByOrderId(payloadobj.OutTradeNo); err != nil {
|
||||
// c.JSON(200, rspObj)
|
||||
// return
|
||||
// } else if !found {
|
||||
// c.JSON(200, rspObj)
|
||||
// return
|
||||
// }
|
||||
dstUrl := service.Wxpay.GenSendWxMsgUrl(int64(orderModel.GameId))
|
||||
f5.GetHttpCliMgr().SendGoStylePost(
|
||||
dstUrl,
|
||||
map[string]string{},
|
||||
"Content-Type: application/json",
|
||||
string(postbytes),
|
||||
func(hcr f5.HttpCliResponse) {
|
||||
if hcr.GetErr() != nil {
|
||||
f5.GetSysLog().Error("Post wx custom msg err:%v dstUrl:%v", hcr.GetErr().Error(), dstUrl)
|
||||
return
|
||||
}
|
||||
|
||||
// if orderModel.ItemId != q5.SafeToInt32(payloadobj.GoodsInfo.ProductId) {
|
||||
// c.JSON(200, rspObj)
|
||||
// return
|
||||
// }
|
||||
rspJson := struct {
|
||||
Errcode int `json:"errcode"` // 0为成功
|
||||
Errmsg string `json:"errmsg"` //
|
||||
}{}
|
||||
|
||||
// if orderModel.Status > 1 {
|
||||
// rspObj.ErrorCode = 0
|
||||
// rspObj.ErrMsg = "Success"
|
||||
// c.JSON(200, rspObj)
|
||||
// return
|
||||
// }
|
||||
f5.GetSysLog().Debug("send wx custom msg rsp:%s", hcr.GetRawData())
|
||||
err = q5.DecodeJson(hcr.GetRawData(), &rspJson)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// rediskey := "ls:accountid:" + orderModel.AccountId
|
||||
// str, err := service.Redis.Get(constant.LOGIN_REDIS, rediskey)
|
||||
// if err != nil {
|
||||
// c.JSON(200, rspObj)
|
||||
// return
|
||||
// }
|
||||
if rspJson.Errcode != 0 {
|
||||
f5.GetSysLog().Error("send wx custom msg error:%v", rspJson.Errmsg)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
c.JSON(200, rspObj)
|
||||
}
|
||||
}
|
||||
|
||||
// data := map[string]interface{}{}
|
||||
// if json.Unmarshal([]byte(str), &data) != nil {
|
||||
// c.JSON(200, rspObj)
|
||||
// return
|
||||
// }
|
||||
|
||||
// openid := q5.SafeToString(data["openid"])
|
||||
// if openid != payloadobj.OpenId {
|
||||
// c.JSON(200, rspObj)
|
||||
// return
|
||||
// }
|
||||
|
||||
// orderModel.GameId = int32(gameid)
|
||||
// f5.GetSysLog().Debug("notify url:%s, %s", appid, notifyurl)
|
||||
|
||||
// nowtimestr := q5.SafeToString(f5.GetApp().GetRealSeconds())
|
||||
// originstr := "account_id=" + orderModel.AccountId
|
||||
// originstr += "&goodsid=" + payloadobj.GoodsInfo.ProductId
|
||||
// originstr += "&orderid=" + orderModel.OrderId
|
||||
// originstr += "&amount=" + q5.SafeToString(payloadobj.GoodsInfo.ActualPrice)
|
||||
// originstr += ":" + nowtimestr + constant.NOFITY_GAMESERVER_SALT
|
||||
// params := map[string]string{
|
||||
// "c": "Recharge",
|
||||
// "a": "purchaseNotify",
|
||||
// "account_id": orderModel.AccountId,
|
||||
// "orderid": orderModel.OrderId,
|
||||
// "timestamp": nowtimestr,
|
||||
// "goodsid": payloadobj.GoodsInfo.ProductId,
|
||||
// "amount": q5.SafeToString(payloadobj.GoodsInfo.ActualPrice),
|
||||
// "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
|
||||
// orderModel.UpdateFields([]string{"status"})
|
||||
// rspObj.ErrorCode = 0
|
||||
// rspObj.ErrMsg = "Success"
|
||||
// }
|
||||
// })
|
||||
func (this *MainServiceApi) WxClickNotify(c *gin.Context) {
|
||||
// balabala 校验代码
|
||||
orderid := c.DefaultQuery("orderid", "")
|
||||
if len(orderid) == 0 {
|
||||
c.String(200, "")
|
||||
return
|
||||
}
|
||||
|
||||
// c.JSON(200, rspObj)
|
||||
orderModel := new(model.InAppOrder)
|
||||
if err, found := orderModel.FindByOrderId(orderid); err != nil || !found {
|
||||
c.String(200, "")
|
||||
return
|
||||
}
|
||||
|
||||
strs := strings.Split(orderModel.AccountId, "_")
|
||||
if len(strs) < 3 {
|
||||
c.String(200, "")
|
||||
return
|
||||
}
|
||||
|
||||
rediskey := "ls:accountid:" + orderModel.AccountId
|
||||
str, err := service.Redis.Get(constant.LOGIN_REDIS, rediskey)
|
||||
if err != nil {
|
||||
c.String(200, "")
|
||||
return
|
||||
}
|
||||
|
||||
data := map[string]interface{}{}
|
||||
if json.Unmarshal([]byte(str), &data) != nil {
|
||||
c.String(200, "")
|
||||
return
|
||||
}
|
||||
|
||||
rspstr := service.Wxpay.GetPrepayInfoStr(q5.SafeToString(data["openid"]), int64(orderModel.GameId), orderModel.IP, orderid, int64(orderModel.ItemId))
|
||||
|
||||
c.Header("Content-Type", "text/html")
|
||||
c.String(200, rspstr)
|
||||
}
|
||||
|
||||
func (this *MainServiceApi) WxPayNotify(c *gin.Context) {
|
||||
f5.GetSysLog().Debug("wx pay notify:%s", c.Request.URL.RawQuery)
|
||||
|
||||
payserial := c.GetHeader("Wechatpay-Serial") //验签的微信支付平台证书序列号/微信支付公钥ID
|
||||
if mt.Table.Config.GetWxCertificateSn() != payserial {
|
||||
f5.GetSysLog().Alert("!!!!!!!!!!cerificate Serial error")
|
||||
return
|
||||
}
|
||||
|
||||
paysign := c.GetHeader("Wechatpay-Signature") //验签的签名值
|
||||
paytimestamp := c.GetHeader("Wechatpay-Timestamp") //验签的时间戳
|
||||
paynonce := c.GetHeader("Wechatpay-Nonce") //验签的随机字符串
|
||||
nowtime := f5.GetApp().GetRealSeconds()
|
||||
paytime := q5.SafeToInt64(paytimestamp)
|
||||
if paytime < nowtime - 60 || paytime > nowtime + 60 {
|
||||
return
|
||||
}
|
||||
|
||||
rawdata, err := c.GetRawData()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
rawstr := fmt.Sprintf("%s\n%s\n%s", paytimestamp, paynonce, rawdata)
|
||||
if !service.Wxpay.VerifyPaySign(rawstr, paysign) {
|
||||
return
|
||||
}
|
||||
|
||||
rspObj := struct {
|
||||
ErrorCode int32 `json:"ErrCode"`
|
||||
ErrMsg string `json:"ErrMsg"`
|
||||
}{
|
||||
ErrorCode: 99999,
|
||||
ErrMsg: "internal error",
|
||||
}
|
||||
|
||||
msg_signature := c.Query("msg_signature")
|
||||
if msg_signature != "" {
|
||||
// postObj := struct {
|
||||
// ToUserName string `json:"ToUserName"` //小程序的原始 ID
|
||||
// Encrypt string `json:"Encrypt"`
|
||||
// }{}
|
||||
|
||||
// if err := c.ShouldBindJSON(&postObj); err != nil {
|
||||
// f5.GetSysLog().Debug("post data error ")
|
||||
// c.JSON(200, rspObj)
|
||||
// return
|
||||
// }
|
||||
|
||||
// smsg, appid := service.Wxpay.DecryptMsg(msg_signature, timestamp, nonce, postObj.Encrypt, mt.Table.Config.GetWxMsgNotifyToken(), mt.Table.Config.GetWxMsgNotifyEncodingAesKey())
|
||||
// if len(smsg) == 0 || len(appid) == 0 {
|
||||
// f5.GetSysLog().Debug("decrypt msg data error")
|
||||
// c.JSON(200, rspObj)
|
||||
// return
|
||||
// }
|
||||
|
||||
// wxmsg := struct {
|
||||
// ToUserName string `json:"ToUserName"` //小程序的原始 ID
|
||||
// FromUserName string `json:"FromUserName"` //发送者的 openid
|
||||
// CreateTime int64 `json:"CreateTime"`
|
||||
// MsgType string `json:"MsgType"`
|
||||
// Content string `json:"Content"`
|
||||
// MediaId string `json:"MediaId"`
|
||||
// PicUrl string `json:"PicUrl"`
|
||||
// MsgId int64 `json:"MsgId"`
|
||||
// Event string `json:"Event"`
|
||||
// SessionFrom string `json:"SessionFrom"`
|
||||
// }{}
|
||||
|
||||
// f5.GetSysLog().Debug("wx msg notify decrypted data:%s", smsg)
|
||||
// if err := json.Unmarshal(smsg, &wxmsg); err != nil {
|
||||
// f5.GetSysLog().Debug("decrypt msg data error")
|
||||
// c.JSON(200, rspObj)
|
||||
// return
|
||||
// }
|
||||
|
||||
// if wxmsg.MsgType != "event" || wxmsg.Event != "user_enter_tempsession" || wxmsg.SessionFrom != "prepare_pay_from_game" {
|
||||
// c.JSON(200, rspObj)
|
||||
// return
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
c.JSON(200, rspObj)
|
||||
}
|
||||
|
@ -51,6 +51,18 @@ func (ct *ConfigTable) GetWxMsgNotifyEncodingAesKey() string {
|
||||
return ct.selfConf.GetWxMsgNotifyEncodingAesKey()
|
||||
}
|
||||
|
||||
func (ct *ConfigTable) GetWxNofityHost() string {
|
||||
return ct.selfConf.GetWxNofityHost()
|
||||
}
|
||||
|
||||
func (ct *ConfigTable) GetWxLinkTitle() string {
|
||||
return ct.selfConf.GetWxLinkTitle()
|
||||
}
|
||||
|
||||
func (ct *ConfigTable) GetWxLinkDescription() string {
|
||||
return ct.selfConf.GetWxLinkDescription()
|
||||
}
|
||||
|
||||
func (ct *ConfigTable) PostInit1() {
|
||||
ct.selfConf = ct.GetById(int64(0))
|
||||
if ct.selfConf == nil {
|
||||
|
@ -75,6 +75,9 @@ type Config struct {
|
||||
wx_merchant_api_key string
|
||||
wx_msg_notify_token string
|
||||
wx_msg_notify_encoding_aes_key string
|
||||
wx_nofity_host string
|
||||
wx_link_title string
|
||||
wx_link_description string
|
||||
|
||||
_flags1_ uint64
|
||||
_flags2_ uint64
|
||||
@ -464,6 +467,30 @@ func (this *Config) HasWxMsgNotifyEncodingAesKey() bool {
|
||||
return (this._flags1_ & (uint64(1) << 9)) > 0
|
||||
}
|
||||
|
||||
func (this *Config) GetWxNofityHost() string {
|
||||
return this.wx_nofity_host
|
||||
}
|
||||
|
||||
func (this *Config) HasWxNofityHost() bool {
|
||||
return (this._flags1_ & (uint64(1) << 10)) > 0
|
||||
}
|
||||
|
||||
func (this *Config) GetWxLinkTitle() string {
|
||||
return this.wx_link_title
|
||||
}
|
||||
|
||||
func (this *Config) HasWxLinkTitle() bool {
|
||||
return (this._flags1_ & (uint64(1) << 11)) > 0
|
||||
}
|
||||
|
||||
func (this *Config) GetWxLinkDescription() string {
|
||||
return this.wx_link_description
|
||||
}
|
||||
|
||||
func (this *Config) HasWxLinkDescription() bool {
|
||||
return (this._flags1_ & (uint64(1) << 12)) > 0
|
||||
}
|
||||
|
||||
func (this *RechargeCurrency) GetCurrencyName() string {
|
||||
return this.currency_name
|
||||
}
|
||||
@ -745,6 +772,9 @@ func (this *Config) LoadFromKv(kv map[string]interface{}) {
|
||||
f5.ReadMetaTableField(&this.wx_merchant_api_key, "wx_merchant_api_key", &this._flags1_, 7, kv)
|
||||
f5.ReadMetaTableField(&this.wx_msg_notify_token, "wx_msg_notify_token", &this._flags1_, 8, kv)
|
||||
f5.ReadMetaTableField(&this.wx_msg_notify_encoding_aes_key, "wx_msg_notify_encoding_aes_key", &this._flags1_, 9, kv)
|
||||
f5.ReadMetaTableField(&this.wx_nofity_host, "wx_nofity_host", &this._flags1_, 10, kv)
|
||||
f5.ReadMetaTableField(&this.wx_link_title, "wx_link_title", &this._flags1_, 11, kv)
|
||||
f5.ReadMetaTableField(&this.wx_link_description, "wx_link_description", &this._flags1_, 12, kv)
|
||||
}
|
||||
|
||||
func (this *RechargeCurrency) LoadFromKv(kv map[string]interface{}) {
|
||||
|
@ -64,6 +64,9 @@ message Config
|
||||
optional string wx_merchant_api_key = 7;
|
||||
optional string wx_msg_notify_token = 8;
|
||||
optional string wx_msg_notify_encoding_aes_key = 9;
|
||||
optional string wx_nofity_host = 10;
|
||||
optional string wx_link_title = 11;
|
||||
optional string wx_link_description = 12;
|
||||
}
|
||||
|
||||
message RechargeCurrency
|
||||
|
@ -21,4 +21,8 @@ func (this *IngameRouter) InitRouter() {
|
||||
api.InGameApi.PayDone)
|
||||
f5.GetApp().GetGinEngine().POST("/api/ingame/sprepurchase",
|
||||
api.InGameApi.ServerPrePurchase)
|
||||
f5.GetApp().GetGinEngine().POST("/api/ingame/prepay",
|
||||
api.InGameApi.PreOrder)
|
||||
f5.GetApp().GetGinEngine().POST("/api/ingame/querypay",
|
||||
api.InGameApi.QueryPay)
|
||||
}
|
||||
|
@ -19,4 +19,8 @@ func (this *MainServiceRouter) InitRouter() {
|
||||
api.WxMsgTNotify)
|
||||
f5.GetApp().GetGinEngine().POST("/wx/msgnotify",
|
||||
api.WxMsgNotify)
|
||||
f5.GetApp().GetGinEngine().GET("/wx/clicknotify",
|
||||
api.WxClickNotify)
|
||||
f5.GetApp().GetGinEngine().POST("/wx/paynotify",
|
||||
api.WxPayNotify)
|
||||
}
|
||||
|
@ -24,12 +24,14 @@ type expireSession struct {
|
||||
Time int64
|
||||
}
|
||||
type wxpay struct {
|
||||
gamesGoods q5.ConcurrentMap[int64, map[int64]int64] //[gameid, [goodsid]count]
|
||||
accessTokens q5.ConcurrentMap[int64, TokenInfo] //[gameid, TokenInfo]
|
||||
expireInfo q5.ConcurrentMap[string, *expireSession] //[accountid, expireSession]
|
||||
gamesGoods q5.ConcurrentMap[int64, map[int64]GoodsInfo] //[gameid, [goodsid]goodsinfo]
|
||||
accessTokens q5.ConcurrentMap[int64, TokenInfo] //[gameid, TokenInfo]
|
||||
expireInfo q5.ConcurrentMap[string, *expireSession] //[accountid, expireSession]
|
||||
mediaInfo q5.ConcurrentMap[int64, string] //[gameid, mediaid]
|
||||
refreshflag bool
|
||||
ctx context.Context
|
||||
client *core.Client
|
||||
payhtmlstr string
|
||||
}
|
||||
|
||||
type WxQuery struct {
|
||||
@ -104,8 +106,14 @@ type WxPayload struct {
|
||||
|
||||
}
|
||||
|
||||
type GoodsInfo struct {
|
||||
Name string
|
||||
Count int64
|
||||
Price int64 //
|
||||
}
|
||||
|
||||
func (wp *wxpay) init() {
|
||||
wp.gamesGoods = q5.ConcurrentMap[int64, map[int64]int64]{}
|
||||
wp.gamesGoods = q5.ConcurrentMap[int64, map[int64]GoodsInfo]{}
|
||||
wp.accessTokens = q5.ConcurrentMap[int64, TokenInfo]{}
|
||||
wp.expireInfo = q5.ConcurrentMap[string, *expireSession]{}
|
||||
|
||||
@ -119,9 +127,13 @@ func (wp *wxpay) init() {
|
||||
if json.Unmarshal([]byte(str), &data) != nil {
|
||||
f5.GetSysLog().Error("parse [%s] error.", filename)
|
||||
} else {
|
||||
gamegoods := map[int64]int64{}
|
||||
gamegoods := map[int64]GoodsInfo{}
|
||||
for _, data := range data {
|
||||
gamegoods[q5.SafeToInt64(data["id"])] = q5.SafeToInt64(data["count"])
|
||||
gamegoods[q5.SafeToInt64(data["id"])] = GoodsInfo{
|
||||
Name: q5.SafeToString(data["name"]),
|
||||
Count: q5.SafeToInt64(data["count"]),
|
||||
Price: q5.SafeToInt64(data["price"]) * 100,
|
||||
}
|
||||
}
|
||||
wp.gamesGoods.Store(w.GetGameid(), gamegoods)
|
||||
wp.accessTokens.Store(w.GetGameid(), TokenInfo{})
|
||||
@ -133,6 +145,8 @@ func (wp *wxpay) init() {
|
||||
|
||||
wp.refreshflag = true
|
||||
go wp.checkAccessToken()
|
||||
|
||||
wp.initMch()
|
||||
}
|
||||
|
||||
func (wp *wxpay) unInit() {
|
||||
@ -214,12 +228,12 @@ func (wp *wxpay) GetGoodsCount(gameid int64, goodsid int64) (count int64, err er
|
||||
return 0, errors.New("no game")
|
||||
}
|
||||
|
||||
count, ok = (*goods)[goodsid]
|
||||
info, ok := (*goods)[goodsid]
|
||||
if !ok {
|
||||
return 0, errors.New("no goods")
|
||||
}
|
||||
|
||||
return count, nil
|
||||
return info.Count, nil
|
||||
}
|
||||
|
||||
func (wp *wxpay) QueryBalance(openid string, gameid int64, userip string, sessionkey string) (balance int64, wxerrcode int32, err error) {
|
||||
@ -508,7 +522,7 @@ func (wp *wxpay) checkAccessToken() {
|
||||
time.Sleep(time.Second)
|
||||
|
||||
if f5.IsOnlineEnv() {
|
||||
wp.gamesGoods.Range(func(gameid int64, value map[int64]int64) bool {
|
||||
wp.gamesGoods.Range(func(gameid int64, value map[int64]GoodsInfo) bool {
|
||||
cfg, _ := wp.accessTokens.Load(gameid)
|
||||
if wp.refreshflag || (cfg != nil && cfg.Expire <= f5.GetApp().GetRealSeconds()) {
|
||||
wp.freshAccessToken(gameid)
|
||||
|
@ -5,10 +5,15 @@ import (
|
||||
"f5"
|
||||
"fmt"
|
||||
"main/mt"
|
||||
"os"
|
||||
"q5"
|
||||
"time"
|
||||
|
||||
"github.com/wechatpay-apiv3/wechatpay-go/core"
|
||||
"github.com/wechatpay-apiv3/wechatpay-go/core/consts"
|
||||
"github.com/wechatpay-apiv3/wechatpay-go/core/option"
|
||||
"github.com/wechatpay-apiv3/wechatpay-go/services/certificates"
|
||||
"github.com/wechatpay-apiv3/wechatpay-go/services/fileuploader"
|
||||
"github.com/wechatpay-apiv3/wechatpay-go/services/payments/jsapi"
|
||||
"github.com/wechatpay-apiv3/wechatpay-go/utils"
|
||||
)
|
||||
@ -21,7 +26,7 @@ func (wp *wxpay) initMch() {
|
||||
)
|
||||
|
||||
// 使用 utils 提供的函数从本地文件中加载商户私钥,商户私钥会用来生成请求的签名
|
||||
mchPrivateKey, err := utils.LoadPrivateKeyWithPath("../res/apiclient_key.pem")
|
||||
mchPrivateKey, err := utils.LoadPrivateKeyWithPath("../res/kingsome_key.pem")
|
||||
if err != nil {
|
||||
f5.GetSysLog().Alert("load merchant private key error")
|
||||
}
|
||||
@ -40,23 +45,100 @@ func (wp *wxpay) initMch() {
|
||||
// https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay5_1.shtml
|
||||
svc := certificates.CertificatesApiService{Client: wp.client}
|
||||
resp, result, err := svc.DownloadCertificates(wp.ctx)
|
||||
f5.GetSysLog().Debug("status=%d resp=%s", result.Response.StatusCode, resp)
|
||||
f5.GetSysLog().Debug("status=%d resp=%s err=%s", result.Response.StatusCode, resp, err.Error())
|
||||
|
||||
go wp.checkGameMediaId()
|
||||
|
||||
wp.payhtmlstr, err = f5.ReadJsonFile("../config/payhtml.template")
|
||||
|
||||
if err != nil {
|
||||
f5.GetSysLog().Error("%s", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func (wp *wxpay) GetPrepareid(openid string, gameid int64, userip string, orderid string) (balance int64, wxerrcode int32, err error) {
|
||||
func (wp *wxpay) checkGameMediaId() {
|
||||
wp.mediaInfo = q5.ConcurrentMap[int64, string]{}
|
||||
uploadtime := int64(0)
|
||||
for {
|
||||
nowtime := f5.GetApp().GetRealSeconds()
|
||||
if wp.mediaInfo.GetSize() == 0 || q5.GetDaySeconds(uploadtime, 8) != q5.GetDaySeconds(nowtime, 8) {
|
||||
uploader := fileuploader.ImageUploader{Client: wp.client}
|
||||
mt.Table.Wxconfig.Traverse(func(w *mt.Wxconfig) bool {
|
||||
filename := q5.SafeToString(w.GetGameid()) + ".jpg"
|
||||
file, err := os.Open("../res/gamepics/" + filename)
|
||||
if err != nil {
|
||||
f5.GetSysLog().Error("file error:%s", filename)
|
||||
return false
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
resp, result, err := uploader.Upload(wp.ctx, file, filename, consts.ImageJPG)
|
||||
if err == nil {
|
||||
wp.mediaInfo.Store(w.GetGameid(), *resp.MediaId)
|
||||
f5.GetSysLog().Debug("refresh media ok:%s, %s", filename, *resp.MediaId)
|
||||
} else {
|
||||
f5.GetSysLog().Error("refresh media err:%s, %s", filename, result.Response.Status)
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
uploadtime = nowtime
|
||||
}
|
||||
time.Sleep(time.Minute)
|
||||
}
|
||||
}
|
||||
|
||||
func (wp *wxpay) GenThumburl(gameid int64) (thumburl string) {
|
||||
token := wp.getAccessToken(gameid)
|
||||
mediaid := ""
|
||||
pmediaid, ok := wp.mediaInfo.Load(gameid)
|
||||
if ok {
|
||||
mediaid = *pmediaid
|
||||
}
|
||||
|
||||
urls := mt.Table.Config.GetWxUrl()
|
||||
if len(urls) > 0 {
|
||||
thumburl = fmt.Sprintf("https://%s/cgi-bin/media/get?access_token=%s&type=image&media_id=%s", urls[0], token, mediaid)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (wp *wxpay) GenSendWxMsgUrl(gameid int64) (msgurl string) {
|
||||
token := wp.getAccessToken(gameid)
|
||||
urls := mt.Table.Config.GetWxUrl()
|
||||
if len(urls) > 0 {
|
||||
msgurl = fmt.Sprintf("https://%s/cgi-bin/message/custom/send?access_token=%s", urls[0], token)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (wp *wxpay) GetPrepayInfoStr(openid string, gameid int64, userip string, orderid string, goodsid int64) (rspstr string) {
|
||||
svc := jsapi.JsapiApiService{Client: wp.client}
|
||||
// 得到prepay_id,以及调起支付所需的参数和签名
|
||||
cfg := mt.Table.Wxconfig.GetById(gameid)
|
||||
goods, ok := wp.gamesGoods.Load(gameid)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
info, ok := (*goods)[goodsid]
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
resp, result, err := svc.PrepayWithRequestPayment(wp.ctx,
|
||||
jsapi.PrepayRequest{
|
||||
Appid: core.String(cfg.GetAppid()),
|
||||
Mchid: core.String(mt.Table.Config.GetWxMerchantId()),
|
||||
Description: core.String(""),
|
||||
Description: core.String(info.Name),
|
||||
OutTradeNo: core.String(orderid),
|
||||
Attach: core.String(userip),
|
||||
NotifyUrl: core.String("https://www.weixin.qq.com/wxpay/pay.php"),
|
||||
NotifyUrl: core.String(mt.Table.Config.GetWxNofityHost() + "/wx/paynotify"),
|
||||
Amount: &jsapi.Amount{
|
||||
Total: core.Int64(100),
|
||||
Total: core.Int64(info.Count),
|
||||
},
|
||||
Payer: &jsapi.Payer{
|
||||
Openid: core.String(openid),
|
||||
@ -64,165 +146,21 @@ func (wp *wxpay) GetPrepareid(openid string, gameid int64, userip string, orderi
|
||||
},
|
||||
)
|
||||
|
||||
if err == nil {
|
||||
f5.GetSysLog().Debug("%s, %s", fmt.Sprintln(resp), result.Response.Status)
|
||||
f5.GetSysLog().Debug("prepay rsp:%s, %s", fmt.Sprintln(resp.String()), result.Response.Status)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
rspstr = fmt.Sprintf(wp.payhtmlstr, resp.Appid, resp.TimeStamp, resp.NonceStr, resp.Package, resp.PaySign)
|
||||
return
|
||||
}
|
||||
|
||||
// func (wp *wxpay) QueryPay(openid string, gameid int64, userip string, sessionkey string, amount int32, billno string) (wxerrcode int32) {
|
||||
// cfg := mt.Table.Wxconfig.GetById(gameid)
|
||||
// postbody := struct {
|
||||
// OpenId string `json:"openid"`
|
||||
// OfferId string `json:"offer_id"`
|
||||
// Ts int64 `json:"ts"`
|
||||
// ZoneId string `json:"zone_id"`
|
||||
// Env int32 `json:"env"`
|
||||
// UserIp string `json:"user_ip"`
|
||||
// Amount int32 `json:"amount"`
|
||||
// BillNo string `json:"bill_no"`
|
||||
// }{
|
||||
// OpenId: openid,
|
||||
// OfferId: cfg.GetOfferid(),
|
||||
// Ts: f5.GetApp().GetRealSeconds(),
|
||||
// ZoneId: cfg.GetZoneid(),
|
||||
// UserIp: userip,
|
||||
// Amount: amount,
|
||||
// BillNo: billno,
|
||||
// }
|
||||
func (wp *wxpay) VerifyPaySign(rawdata string, signature string) bool {
|
||||
sign, err := wp.client.Sign(wp.ctx, rawdata)
|
||||
f5.GetSysLog().Debug("verify pay sign:%s, signature:%s", sign.Signature, signature)
|
||||
if err != nil || sign.Signature != signature {
|
||||
return false
|
||||
}
|
||||
|
||||
// if !f5.IsOnlineEnv() {
|
||||
// postbody.Env = 1
|
||||
// }
|
||||
|
||||
// poststr := q5.EncodeJson(postbody)
|
||||
|
||||
// queryuri := "/wxa/game/pay"
|
||||
// query := WxQuery{
|
||||
// AccessToken: wp.getAccessToken(gameid),
|
||||
// Signature: wp.GenSHA256Signature(poststr, sessionkey),
|
||||
// SigMethod: "hmac_sha256",
|
||||
// PaySig: wp.GenSHA256Signature(queryuri+"&"+poststr, cfg.GetAppkey()),
|
||||
// }
|
||||
|
||||
// params := map[string]string{}
|
||||
// data, _ := json.Marshal(query)
|
||||
// json.Unmarshal(data, ¶ms)
|
||||
|
||||
// sendRequest := false
|
||||
// urls := mt.Table.Config.GetWxUrl()
|
||||
// for _, wxhost := range urls {
|
||||
// url := "https://" + wxhost + queryuri
|
||||
// f5.GetHttpCliMgr().SendGoStylePost(
|
||||
// url,
|
||||
// params,
|
||||
// "Content-Type: application/json",
|
||||
// poststr,
|
||||
// func(rsp f5.HttpCliResponse) {
|
||||
// if rsp.GetErr() != nil {
|
||||
// return
|
||||
// }
|
||||
|
||||
// sendRequest = true
|
||||
// rspJson := WxPayRsp{}
|
||||
// f5.GetSysLog().Debug("wx pay rsp:%s", rsp.GetRawData())
|
||||
// err := q5.DecodeJson(rsp.GetRawData(), &rspJson)
|
||||
// if err != nil {
|
||||
// return
|
||||
// }
|
||||
|
||||
// wxerrcode = rspJson.ErrCode
|
||||
// switch rspJson.ErrCode {
|
||||
// case constant.WX_ERRCODE_OK:
|
||||
// case constant.WX_ERRCODE_BUSY:
|
||||
// sendRequest = false
|
||||
// default:
|
||||
// f5.GetSysLog().Info("err msg:%s", rspJson.ErrMsg)
|
||||
// wp.checkErrorCode(rspJson.ErrCode)
|
||||
// }
|
||||
|
||||
// })
|
||||
// if sendRequest {
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
|
||||
// return wxerrcode
|
||||
// }
|
||||
|
||||
// func (wp *wxpay) QueryPurchase(openid string, gameid int64, userip string, sessionkey string, amount int32, tradeno string) (wxerrcode int32) {
|
||||
// cfg := mt.Table.Wxconfig.GetById(gameid)
|
||||
// postbody := struct {
|
||||
// OpenId string `json:"openid"`
|
||||
// Ts int64 `json:"ts"`
|
||||
// Env int32 `json:"env"`
|
||||
// TradeNo string `json:"out_trade_no"`
|
||||
// BizId int32 `json:"biz_id"`
|
||||
// OfferId string `json:"offer_id"`
|
||||
// }{
|
||||
// OpenId: openid,
|
||||
// Ts: f5.GetApp().GetRealSeconds(),
|
||||
// BizId: 2, //1代币 2道具直购
|
||||
// TradeNo: tradeno,
|
||||
// OfferId: cfg.GetOfferid(),
|
||||
// }
|
||||
|
||||
// if !f5.IsOnlineEnv() {
|
||||
// postbody.Env = 1
|
||||
// }
|
||||
|
||||
// poststr := q5.EncodeJson(postbody)
|
||||
|
||||
// queryuri := "/wxa/game/queryorderinfo"
|
||||
// query := WxQuery{
|
||||
// AccessToken: wp.getAccessToken(gameid),
|
||||
// Signature: wp.GenSHA256Signature(poststr, sessionkey),
|
||||
// SigMethod: "hmac_sha256",
|
||||
// PaySig: wp.GenSHA256Signature(queryuri+"&"+poststr, cfg.GetAppkey()),
|
||||
// }
|
||||
|
||||
// params := map[string]string{}
|
||||
// data, _ := json.Marshal(query)
|
||||
// json.Unmarshal(data, ¶ms)
|
||||
|
||||
// sendRequest := false
|
||||
// urls := mt.Table.Config.GetWxUrl()
|
||||
// for _, wxhost := range urls {
|
||||
// url := "https://" + wxhost + queryuri
|
||||
// f5.GetHttpCliMgr().SendGoStylePost(
|
||||
// url,
|
||||
// params,
|
||||
// "Content-Type: application/json",
|
||||
// poststr,
|
||||
// func(rsp f5.HttpCliResponse) {
|
||||
// if rsp.GetErr() != nil {
|
||||
// return
|
||||
// }
|
||||
|
||||
// sendRequest = true
|
||||
// rspJson := WxQueryOrderRsp{}
|
||||
// f5.GetSysLog().Debug("wx query order rsp:%s", rsp.GetRawData())
|
||||
// err := q5.DecodeJson(rsp.GetRawData(), &rspJson)
|
||||
// if err != nil {
|
||||
// return
|
||||
// }
|
||||
|
||||
// wxerrcode = rspJson.ErrCode
|
||||
// switch rspJson.ErrCode {
|
||||
// case constant.WX_ERRCODE_OK:
|
||||
// case constant.WX_ERRCODE_BUSY:
|
||||
// sendRequest = false
|
||||
// default:
|
||||
// f5.GetSysLog().Info("err msg:%s", rspJson.ErrMsg)
|
||||
// wp.checkErrorCode(rspJson.ErrCode)
|
||||
// }
|
||||
|
||||
// })
|
||||
// if sendRequest {
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
|
||||
// return wxerrcode
|
||||
// }
|
||||
return true
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ func (wp *wxpay) DecryptMsg(sMsgSignature string, sTimeStamp string, sNonce stri
|
||||
buf := bytes.NewReader(netlenbyte)
|
||||
iMsgLen := int32(0) //ntohl(iNetLen);
|
||||
binary.Read(buf, binary.BigEndian, &iMsgLen)
|
||||
if len(sNoEncryptData) <= constant.WX_RANDENCRYPT_STRLEN+constant.WX_KMSG_LEN+int(iMsgLen) {
|
||||
if int(iMsgLen) < 1 || len(sNoEncryptData) <= constant.WX_RANDENCRYPT_STRLEN+constant.WX_KMSG_LEN+int(iMsgLen) {
|
||||
return
|
||||
}
|
||||
sMsg = sNoEncryptData[constant.WX_RANDENCRYPT_STRLEN+constant.WX_KMSG_LEN : constant.WX_RANDENCRYPT_STRLEN+constant.WX_KMSG_LEN+iMsgLen]
|
||||
|
Loading…
x
Reference in New Issue
Block a user