diff --git a/bin/payserver/config/config.json b/bin/payserver/config/config.json index 71750f4..33bfe5a 100644 --- a/bin/payserver/config/config.json +++ b/bin/payserver/config/config.json @@ -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": "充值后返回游戏查看" } diff --git a/bin/payserver/config/payhtml.template b/bin/payserver/config/payhtml.template new file mode 100644 index 0000000..259c508 --- /dev/null +++ b/bin/payserver/config/payhtml.template @@ -0,0 +1,39 @@ + + + \ No newline at end of file diff --git a/bin/payserver/res/gamepics/1004.jpg b/bin/payserver/res/gamepics/1004.jpg new file mode 100644 index 0000000..642888b Binary files /dev/null and b/bin/payserver/res/gamepics/1004.jpg differ diff --git a/bin/payserver/res/gamepics/2004.jpg b/bin/payserver/res/gamepics/2004.jpg new file mode 100644 index 0000000..1f192f2 Binary files /dev/null and b/bin/payserver/res/gamepics/2004.jpg differ diff --git a/bin/payserver/res/kingsome_key.pem b/bin/payserver/res/kingsome_key.pem new file mode 100644 index 0000000..d14f160 --- /dev/null +++ b/bin/payserver/res/kingsome_key.pem @@ -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----- diff --git a/server/payserver/api/v1/ingame/ingame.go b/server/payserver/api/v1/ingame/ingame.go index f2d3ed9..9ae20e4 100644 --- a/server/payserver/api/v1/ingame/ingame.go +++ b/server/payserver/api/v1/ingame/ingame.go @@ -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 == "" { diff --git a/server/payserver/api/v1/mainservice/mainservice.go b/server/payserver/api/v1/mainservice/mainservice.go index 9fdfccc..8f36ddc 100644 --- a/server/payserver/api/v1/mainservice/mainservice.go +++ b/server/payserver/api/v1/mainservice/mainservice.go @@ -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) } diff --git a/server/payserver/mt/Config.go b/server/payserver/mt/Config.go index c8f4cb6..3435a2a 100644 --- a/server/payserver/mt/Config.go +++ b/server/payserver/mt/Config.go @@ -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 { diff --git a/server/payserver/mtb/mtb.auto_gen.go b/server/payserver/mtb/mtb.auto_gen.go index 937583c..48f8496 100644 --- a/server/payserver/mtb/mtb.auto_gen.go +++ b/server/payserver/mtb/mtb.auto_gen.go @@ -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{}) { diff --git a/server/payserver/proto/mt.proto b/server/payserver/proto/mt.proto index d965f87..434408f 100644 --- a/server/payserver/proto/mt.proto +++ b/server/payserver/proto/mt.proto @@ -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 diff --git a/server/payserver/router/ingame/ingame.go b/server/payserver/router/ingame/ingame.go index 52865e4..9855d9e 100644 --- a/server/payserver/router/ingame/ingame.go +++ b/server/payserver/router/ingame/ingame.go @@ -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) } diff --git a/server/payserver/router/mainservice/mainservice.go b/server/payserver/router/mainservice/mainservice.go index 66e2054..1ed7567 100644 --- a/server/payserver/router/mainservice/mainservice.go +++ b/server/payserver/router/mainservice/mainservice.go @@ -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) } diff --git a/server/payserver/service/wxpay.go b/server/payserver/service/wxpay.go index 7a99ec7..94d964e 100644 --- a/server/payserver/service/wxpay.go +++ b/server/payserver/service/wxpay.go @@ -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) diff --git a/server/payserver/service/wxpay_prepare.go b/server/payserver/service/wxpay_prepare.go index 954b8a4..61324d6 100644 --- a/server/payserver/service/wxpay_prepare.go +++ b/server/payserver/service/wxpay_prepare.go @@ -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 +} diff --git a/server/payserver/service/wxpaybase.go b/server/payserver/service/wxpaybase.go index 5803941..d703e84 100644 --- a/server/payserver/service/wxpaybase.go +++ b/server/payserver/service/wxpaybase.go @@ -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]