package msg import ( "bytes" "crypto/hmac" "crypto/md5" "encoding/hex" "encoding/json" "encoding/xml" "fmt" "net/http" "net/url" "rocommon/service" "rocommon/util" "roserver/baseserver/model" selfmodel "roserver/gmweb/model" "roserver/serverproto" "sort" "strconv" "strings" "github.com/gin-gonic/gin" ) // https://blog.csdn.net/chunyouhai5703/article/details/100978656?utm_medium=distribute.pc_relevant.none-task-blog-title-1&spm=1001.2101.3001.4242 type QuickPayNotify struct { XMLName xml.Name `xml:"quicksdk_message"` Message QuickTBData `xml:"message"` } type QuickTBData struct { IsTest bool `xml:"is_test"` Channel string `xml:"channel"` ChannelUid string `xml:"channel_uid"` GameOrder string `xml:"game_order"` PayTime string `xml:"pay_time"` Amount float32 `xml:"amount"` Status int32 `xml:"status"` ExtrasParams string `xml:"extras_params"` } /* 0 8888 231845 123456789 12520160612114220441168433 2016-06-12 11:42:20 1.00 0 {1}_{2} */ func WebPayQuickNotify(c *gin.Context) { //ntData := c.PostForm("nt_data") //sign := c.PostForm("sign") //md5Sign := c.PostForm("md5Sign") // //data := ntData + sign + service.GetServiceConfig().SDKConfig.QuickMd5key //tmpSign := md5.Sum([]byte(data)) //md5Str := fmt.Sprintf("%x", tmpSign) //util.DebugF("WebPayQuickNotify ntData=%v sign=%v md5sign=%v tmpsign=%v", ntData, sign, md5Sign, md5Str) //if md5Str == md5Sign { // util.InfoF("WebPayQuickNotify ok") //} else { // util.ErrorF("WebPayQuickNotify sign invalid!!!") // c.JSON(http.StatusOK, "FAILED") // return //} // ////decode nt_data //tmpNtDataList := strings.Split(ntData, "@") //tmpNtData := make([]byte, len(tmpNtDataList)) //tmpKeyData := []byte(service.GetServiceConfig().SDKConfig.QuickCallbackKey) //for idx := 1; idx < len(tmpNtDataList); idx++ { // tmpVal, _ := strconv.Atoi(tmpNtDataList[idx]) // tmpNtData[idx] = (byte)(tmpVal - (int)(0xff&tmpKeyData[(idx-1)%len(tmpKeyData)])) //} ////字符串最前面会有一个空格 //if string(tmpNtData[0]) == "\u0000" { // tmpNtData = append(tmpNtData[:0], tmpNtData[1:]...) //} //util.InfoF("WebPayQuickNotify ntdata=%v", string(tmpNtData)) // //tmpSt := &QuickPayNotify{} //err := xml.Unmarshal(tmpNtData, tmpSt) //if err != nil { // util.ErrorF("WebPayQuickNotify xml decode err=%v", err) // c.JSON(http.StatusOK, "FAILED") // return //} // //ntfData := &WebNotifyData{} //ntfData.CpOrderId = tmpSt.Message.GameOrder //ntfData.SdkOrderId = "" //ntfData.PayMethod = "" //ntfData.PayCurrency = "" //ntfData.PayTime = uint64(util.GetTimeSeconds()) //ntfData.PayChannel = "" //webPayNotify(ntfData, tmpSt.Message.Amount, c) //c.JSON(http.StatusOK, "SUCCESS") game_order := c.PostForm("game_order") //游戏订单号 order_no := c.PostForm("order_no") //SDK订单ID amount := c.PostForm("amount") //充值金额 PayChannel := c.PostForm("channel") //充值渠道 serverId := c.PostForm("server_id") //充值服ID util.DebugF("收到充值订单:GameOrder=%v, SdkOfderId=%v, PauAmount=%v, PayChannel=%v, serverId=%v", game_order, order_no, amount, PayChannel, serverId) checkPayAmount, _ := model.Str2Float32(amount) ntfData := &WebNotifyData{} ntfData.CpOrderId = game_order ntfData.SdkOrderId = order_no ntfData.PayMethod = "" ntfData.PayCurrency = "" ntfData.PayTime = uint64(util.GetTimeSeconds()) ntfData.PayChannel = PayChannel retState := webPayNotify(ntfData, checkPayAmount, c) //c.JSON(http.StatusOK, `success`) c.Data(http.StatusOK, "text/plain; charset=utf-8", []byte(retState)) } func getMd5Sign(callbackKey string, params map[string]string) string { // 删除参数中的 sign 字段 delete(params, "sign") // 按参数名进行升序排序 var keys []string for key := range params { keys = append(keys, key) } sort.Strings(keys) // 拼接参数和值 var signKey strings.Builder for _, key := range keys { signKey.WriteString(key) signKey.WriteString("=") signKey.WriteString(params[key]) signKey.WriteString("&") } // 添加回调密钥 signKey.WriteString(callbackKey) // 计算 MD5 hash := md5.Sum([]byte(signKey.String())) return hex.EncodeToString(hash[:]) } func getMd5RuSign(callbackKey string, params map[string]string) string { // 删除参数中的 sign 字段 delete(params, "sign") // 按参数名进行升序排序 var keys []string for key := range params { keys = append(keys, key) } sort.Strings(keys) // 拼接参数和值 var signKey strings.Builder for i, key := range keys { signKey.WriteString(key) signKey.WriteString("=") signKey.WriteString(params[key]) if i != len(keys)-1 { signKey.WriteString("&") } } // 添加回调密钥 signKey.WriteString(callbackKey) // 计算 MD5 hash := md5.Sum([]byte(signKey.String())) return hex.EncodeToString(hash[:]) } type Extras struct { ServerId int `json:"serverId"` Platform string `json:"platform"` SubPlatform string `json:"subPlatform"` Bima string `json:"bima"` CpOrderId string `json:"cpOrderId"` } type ExtrasRu struct { AccountId string `json:"accountId"` Money string `json:"money"` Addtime string `json:"addtime"` OrderId string `json:"orderId"` CustomorderId string `json:"customorderId"` Paytype string `json:"paytype"` Success string `json:"success"` } // 海外版quick回调 func WebPayHwQuickNotify(c *gin.Context) { //util.DebugF("支付回调信息:%v", c.Request.PostForm) params := make(map[string]string) if err := c.Request.ParseForm(); err != nil { util.InfoF("parseForm falied") c.String(http.StatusOK, "FAILED") return } util.DebugF("支付回调信息2:%v", c.Request.PostForm) for key, value := range c.Request.PostForm { params[key] = value[0] // 假设每个参数只有一个值 } sign := params["sign"] info2 := params["extrasParams"] info := strings.ReplaceAll(info2, "\\", "") var extras Extras err := json.Unmarshal([]byte(info), &extras) if err != nil { util.ErrorF("支付回调参数解析错误:%v", err) } util.InfoF("支付签名认证:%v params:%v", extras, params) if extras.Platform == "SDKYOUYI_IOS" || extras.Bima == "SDKYOUYI_IOS" { util.ErrorF("ios 支付签名认证:%v", info) newSign := getMd5Sign("58696021497436514481898335416221", params) if newSign != sign { util.ErrorF("签名错误%v", sign) c.String(http.StatusOK, "FAILED") return } } else if extras.Platform == "SDKYOUYI_IOS_MyCard" || extras.Platform == "SDKHwQuick_MyCard" { util.ErrorF("mycard 支付签名认证:%v", info) newSign := getMd5Sign("03422134397322604272901806704074", params) if newSign != sign { util.ErrorF("签名错误%v", sign) c.String(http.StatusOK, "FAILED") return } } else { util.ErrorF("android 支付签名认证:%v", info) newSign := getMd5Sign("47409863970932353623015025039223", params) if newSign != sign { util.ErrorF("签名错误%v", sign) c.String(http.StatusOK, "FAILED") return } } uid := c.PostForm("uid") cpOrderId := c.PostForm("cpOrderNo") if cpOrderId == "" { if extras.CpOrderId != "" { cpOrderId = extras.CpOrderId } else { util.ErrorF("mycard pay cporderId is nil extras:%v", extras) } } orderNo := c.PostForm("orderNo") payAmount := c.PostForm("payAmount") payCurrency := c.PostForm("payCurrency") payType := c.PostForm("payType") usdAmount := c.PostForm("usdAmount") ntfData := &WebNotifyData{} ntfData.CpOrderId = cpOrderId ntfData.SdkOrderId = orderNo ntfData.PayMethod = payType ntfData.PayCurrency = payCurrency ntfData.PayTime = uint64(util.GetTimeSeconds()) ntfData.PayChannel = "qk_hw" util.WarnF("paycallback uid=%v cpOrderNo=%v orderNo=%v payAmount=%v payCurrency=%v payType=%v usdAmount=%v", uid, cpOrderId, orderNo, payAmount, payCurrency, payType, usdAmount) f64, err := strconv.ParseFloat(usdAmount, 32) if err != nil { fmt.Println("Error:", err) return } webPayNotify(ntfData, float32(f64), c) //// 简单粗暴,直接给其他服转发,不需要确认是哪个服 //payPostRouter := service.GetServiceConfig().SDKConfig.PayPostRouter //util.WarnF("paycallback payPostRouter:%v\n", payPostRouter) //// 组装转发body //params["sign"] = sign //var routerStr strings.Builder //for key, value := range params { // routerStr.WriteString(key) // routerStr.WriteString("=") // routerStr.WriteString(value) // routerStr.WriteString("&") //} //routerString := routerStr.String() //util.WarnF("paycallback routerString:%v\n", routerString) //go sendPosts(payPostRouter, routerString) c.String(http.StatusOK, "SUCCESS") } func WebPayHwRuNotify(c *gin.Context) { //util.DebugF("支付回调信息:%v", c.Request.PostForm) params := make(map[string]string) if err := c.Request.ParseForm(); err != nil { util.InfoF("parseForm falied") c.String(http.StatusOK, "FAILED") return } util.DebugF("支付回调信息2:%v", c.Request.PostForm) for key, value := range c.Request.PostForm { params[key] = value[0] // 假设每个参数只有一个值 } sign := params["sign"] info2 := params["custominfo"] info := strings.ReplaceAll(info2, "\\", "") var extras Extras err := json.Unmarshal([]byte(info), &extras) if err != nil { util.ErrorF("支付回调参数解析错误:%v", err) } util.InfoF("支付签名认证:%v params:%v", extras, params) if extras.Platform == "ZT_IOS" || extras.Bima == "ZT_IOS" { util.ErrorF("ios 支付签名认证:%v", info) newSign := getMd5RuSign("80c648e7df8aaa72", params) if newSign != sign { util.ErrorF("签名错误%v", sign) c.String(http.StatusOK, "FAILED") return } } else if extras.Platform == "SDKYOUYI_IOS_MyCard" || extras.Platform == "SDKHwQuick_MyCard" { util.ErrorF("mycard 支付签名认证:%v", info) newSign := getMd5Sign("03422134397322604272901806704074", params) if newSign != sign { util.ErrorF("签名错误%v", sign) c.String(http.StatusOK, "FAILED") return } } else { util.ErrorF("android 支付签名认证:%v", info) newSign := getMd5RuSign("80c648e7df8aaa72", params) if newSign != sign { util.ErrorF("签名错误%v", sign) c.String(http.StatusOK, "FAILED") return } } uid := c.PostForm("account") cpOrderId := c.PostForm("customorderid") orderNo := c.PostForm("orderid") payAmount := c.PostForm("money") payCurrency := c.PostForm("currency") payType := c.PostForm("paytype") usdAmount := c.PostForm("doller") ntfData := &WebNotifyData{} ntfData.CpOrderId = cpOrderId ntfData.SdkOrderId = orderNo ntfData.PayMethod = payType ntfData.PayCurrency = payCurrency ntfData.PayTime = uint64(util.GetTimeSeconds()) ntfData.PayChannel = "qk_hw" util.WarnF("paycallback uid=%v cpOrderNo=%v orderNo=%v payAmount=%v payCurrency=%v payType=%v usdAmount=%v", uid, cpOrderId, orderNo, payAmount, payCurrency, payType, usdAmount) f64, err := strconv.ParseFloat(payAmount, 32) if err != nil { fmt.Println("Error:", err) return } webPayNotify(ntfData, float32(f64), c) //// 简单粗暴,直接给其他服转发,不需要确认是哪个服 //payPostRouter := service.GetServiceConfig().SDKConfig.PayPostRouter //util.WarnF("paycallback payPostRouter:%v\n", payPostRouter) //// 组装转发body //params["sign"] = sign //var routerStr strings.Builder //for key, value := range params { // routerStr.WriteString(key) // routerStr.WriteString("=") // routerStr.WriteString(value) // routerStr.WriteString("&") //} //routerString := routerStr.String() //util.WarnF("paycallback routerString:%v\n", routerString) //go sendPosts(payPostRouter, routerString) c.String(http.StatusOK, "success") } func WebPayHwDnNotify(c *gin.Context) { //util.DebugF("支付回调信息:%v", c.Request.PostForm) params := make(map[string]string) if err := c.Request.ParseForm(); err != nil { util.InfoF("parseForm falied") c.String(http.StatusOK, "FAILED") return } util.ErrorF("支付回调信息东南亚:%v", c.Request.PostForm) for key, value := range c.Request.PostForm { params[key] = value[0] // 假设每个参数只有一个值 } cpOrderId := params["order_code"] payAmount := params["amount"] f64, err := strconv.ParseFloat(payAmount, 32) if err != nil { fmt.Println("Error:", err) return } res := webPayNotifyDn(cpOrderId, f64) //// 简单粗暴,直接给其他服转发,不需要确认是哪个服 //payPostRouter := service.GetServiceConfig().SDKConfig.PayPostRouter //util.WarnF("paycallback payPostRouter:%v\n", payPostRouter) //// 组装转发body //params["sign"] = sign //var routerStr strings.Builder //for key, value := range params { // routerStr.WriteString(key) // routerStr.WriteString("=") // routerStr.WriteString(value) // routerStr.WriteString("&") //} //routerString := routerStr.String() //util.WarnF("paycallback routerString:%v\n", routerString) //go sendPosts(payPostRouter, routerString) if res == "SUCCESS" { c.JSON(http.StatusOK, gin.H{"processingStatus": "completed"}) } else { c.JSON(404, gin.H{"code": "ORDER_CODE_NOT_FOUND", "message": "order_code does not exist"}) } } func sendPosts(urls []string, routerString string) { for i := 0; i < len(urls); i++ { sendPostToOtherServer(urls[i], []byte(routerString)) } } // http://110.40.223.119:8002/pay/hwQucikFromS1GmWeb func WebPayHwQuickNotifyFromS1GmWeb(c *gin.Context) { params := make(map[string]string) if err := c.Request.ParseForm(); err != nil { util.InfoF("parseForm falied") c.String(http.StatusOK, "FAILED") return } for key, value := range c.Request.PostForm { params[key] = value[0] // 假设每个参数只有一个值 } sign := params["sign"] newSign := getMd5Sign("03422134397322604272901806704074", params) util.ErrorF("sign:%v", sign) util.ErrorF("newSign:%v", newSign) util.ErrorF("params:%v", params) if newSign != sign { util.ErrorF("签名错误%v", sign) c.String(http.StatusOK, "FAILED") return } uid := c.PostForm("uid") cpOrderId := c.PostForm("cpOrderNo") orderNo := c.PostForm("orderNo") payAmount := c.PostForm("payAmount") payCurrency := c.PostForm("payCurrency") payType := c.PostForm("payType") usdAmount := c.PostForm("usdAmount") ntfData := &WebNotifyData{} ntfData.CpOrderId = cpOrderId ntfData.SdkOrderId = orderNo ntfData.PayMethod = payType ntfData.PayCurrency = payCurrency ntfData.PayTime = uint64(util.GetTimeSeconds()) ntfData.PayChannel = "qk_hw" util.DebugF("uid=%v cpOrderNo=%v orderNo=%v payAmount=%v payCurrency=%v payType=%v usdAmount=%v", uid, cpOrderId, orderNo, payAmount, payCurrency, payType, usdAmount) f64, err := strconv.ParseFloat(usdAmount, 32) if err != nil { fmt.Println("Error:", err) return } webPayNotify(ntfData, float32(f64), c) c.JSON(http.StatusOK, "SUCCESS") } // sendPostToOtherServer 发送给其他服务器 func sendPostToOtherServer(url string, body []byte) { // 创建请求 req, err := http.NewRequest("POST", url, bytes.NewReader(body)) if err != nil { util.ErrorF("r1 NewRequest:%v \n", err.Error()) } // 设置Header req.Header.Set("Content-Type", "application/x-www-form-urlencoded") req.Header.Set("Custom-Header", "custom-value") // 发送请求 client := &http.Client{} resp, err := client.Do(req) if err != nil { util.ErrorF("r1 client.Do(req):%v \n", err.Error()) return } defer resp.Body.Close() } type KVSt struct { ParamKey string ParamVal string } func WebPayNBSDKNotify(c *gin.Context) { tmpReq := c.Request err := tmpReq.ParseMultipartForm(32 << 20) if err != nil { return } formCache := tmpReq.PostForm //util.DebugF("formCache2=%v", formCache) var kvList []*KVSt for k, v := range formCache { if k == "sign" { continue } kv := &KVSt{ ParamKey: k, ParamVal: v[0], } kvList = append(kvList, kv) } sort.Slice(kvList, func(i, j int) bool { return kvList[i].ParamKey < kvList[j].ParamKey }) //util.DebugF("kvlist=%v", kvList) verifyStr := "" for idx := 0; idx < len(kvList); idx++ { key := url.QueryEscape(kvList[idx].ParamKey) val := url.QueryEscape(kvList[idx].ParamVal) if idx == 0 { verifyStr += key + "=" + val } else { verifyStr += "&" + key + "=" + val } } sign := c.PostForm("sign") sdkOrderId := c.PostForm("sdk_order_id") //SDK订单ID cpOrderId := c.PostForm("cp_order_id") //游戏方订单ID,由游戏客户端生成(服务器生成给到客户端) serverId := c.PostForm("server_id") //游戏区服ID pfUid := c.PostForm("pf_uid") //渠道平台的UID roleId := c.PostForm("role_id") //游戏方自己的角色ID payAmount := c.PostForm("pay_amount") //支付金额(int,单位分,CP方需要验证是否与计费点金额一致,不做此判断,后果自负哦!!!) gameKey := service.GetServiceConfig().SDKConfig.NbGameKey tmpHmac := hmac.New(md5.New, []byte(gameKey)) tmpHmac.Write([]byte(verifyStr)) tmpSign := hex.EncodeToString(tmpHmac.Sum([]byte(""))) util.DebugF("uid=%v verifyStr=%v cpOrderId=%v pfUid=%v sdkOrderId=%v serverId=%v tmpSign=%v sign=%v gamekey=%v", roleId, verifyStr, cpOrderId, pfUid, sdkOrderId, serverId, tmpSign, sign, gameKey) if tmpSign != sign { util.InfoF("uid=%v WebPayNBSDKNotify sign verify failed cpOrderId=%v", roleId, cpOrderId) return } checkPayAmount, _ := model.Str2Num(payAmount) ntfData := &WebNotifyData{} ntfData.CpOrderId = cpOrderId ntfData.SdkOrderId = sdkOrderId ntfData.PayMethod = "" ntfData.PayCurrency = "" ntfData.PayTime = uint64(util.GetTimeSeconds()) ntfData.PayChannel = "" ret := webPayNotify(ntfData, float32(checkPayAmount)/100, c) //c.JSON(http.StatusOK, `success`) c.Data(http.StatusOK, "text/plain; charset=utf-8", []byte(ret)) } type UniSDKPayExtraST struct { Aid int `json:"aid"` //用户唯一标识 PrivateParam string `json:"privateparam"` PayChannel string `json:"paychannel"` //支付渠道 AppChannel string `json:"appchannel"` //appchannel Platform string `json:"platfrom"` UidId string `json:"uidid"` //设备id GoodsCount int `json:"goodscount"` //商品数量 PayMoney string `json:"paymoney"` //玩家实际支付金额 FreeMoney string `json:"freemoney"` //免费总价,供游戏服写运营日志(如果渠道不提供,该字段为0) PayCurrency string `json:"paycurrency"` //玩家实际支付币种 Deduct int `json:"deduct"` DeductPercent string `json:"deductpercent"` DeductReason string `json:"deductreason"` //扣除原因,是黑设备还是黑币种 JsonData string `json:"jsondata"` InitTime int `json:"inittime"` //订单创建时间戳,精确到秒;若订单不通过create_order接口创建(例如web 支付),则此值为0 PayTime int `json:"paytime"` //订单支付时间戳,精确到秒 IsTest int `json:"istest"` //订单来源:0,正式环境订单;1,测试环境订单(v3.6.2新增) FreeYuanBao int `json:"free_yuanbao"` PayYuanBao int `json:"pay_yuanbao"` PayMethod string `json:"paymethod"` } type UniSDKPayST struct { GameId string `json:"gameid"` HostId int `json:"hostid"` RoleId string `json:"roleid"` GoodsId string `json:"goodsid"` UserName string `json:"username"` //玩家渠道帐号(玩家帐号被sdk渠道转换之后的字符串) SN string `json:"sn"` //游戏订单号 ConsumeSN string `json:"consumesn"` //渠道流水订单号(苹果渠道对应为transaction-id) ExtraData UniSDKPayExtraST } type UniSDKPayResponseST struct { Code int `json:"code"` Msg string `json:"msg"` Data interface{} `json:"data"` } func WebPayUniSDKNotify(c *gin.Context) { sign := c.GetHeader("Gas-Ship-Signature") payInfo := &UniSDKPayST{} bodyData, err := c.GetRawData() if err != nil { util.ErrorF("WebPayUniSDKNotify body get error=%v", err) return } err = json.Unmarshal(bodyData, payInfo) if err != nil { util.ErrorF("WebPayUniSDKNotify body Unmarshal error=%v", err) return } secretKey := service.GetServiceConfig().SDKConfig.UniSecretKey tmpHmac := hmac.New(md5.New, []byte(secretKey)) tmpHmac.Write(bodyData) tmpSign := hex.EncodeToString(tmpHmac.Sum([]byte(""))) if tmpSign != sign { util.InfoF("uid=%v WebPayUniSDKNotify sign verify failed cpOrderId=%v", payInfo.RoleId, payInfo.SN) c.Header("Gas-Ship-Signature", tmpSign) responseSt := &UniSDKPayResponseST{ Code: 403, Msg: "ok", Data: nil, } c.JSON(http.StatusOK, responseSt) return } checkPayAmount, _ := model.Str2Num(payInfo.ExtraData.PayMoney) ntfData := &WebNotifyData{} ntfData.CpOrderId = payInfo.SN ntfData.SdkOrderId = payInfo.ConsumeSN ntfData.PayMethod = payInfo.ExtraData.PayMethod ntfData.PayCurrency = payInfo.ExtraData.PayCurrency ntfData.PayTime = uint64(payInfo.ExtraData.PayTime) ntfData.PayChannel = payInfo.ExtraData.PayChannel ret := webPayNotify(ntfData, float32(checkPayAmount)/100, c) if ret == "FAILED" { c.JSON(http.StatusOK, "FAILED") } c.Header("Gas-Ship-Signature", tmpSign) responseSt := &UniSDKPayResponseST{ Code: 200, Msg: "ok", Data: nil, } c.JSON(http.StatusOK, responseSt) } func WebPayNBH5Notify(c *gin.Context) { sdkOrderId := c.PostForm("sdk_order_id") //SDK订单ID cpOrderId := c.PostForm("cp_order_id") //游戏方订单ID,由游戏客户端生成(服务器生成给到客户端) serverId := c.PostForm("server_id") //游戏区服ID pfUid := c.PostForm("pf_uid") //渠道平台的UID roleId := c.PostForm("role_id") //游戏方自己的角色ID(uid) payAmount := c.PostForm("pay_amount") //支付金额(int,单位分,CP方需要验证是否与计费点金额一致,不做此判断,后果自负哦!!!) goodsType := c.PostForm("goods_type") goodsID := c.PostForm("goods_id") util.InfoF("WebPayH5Notify roleId=%v pfUid=%v sdkOrderId=%v serverId=%v", roleId, pfUid, sdkOrderId, serverId) if cpOrderId == "" { cpOrderId = "WebPayH5Notify" } gameRoleId, _ := model.Str2NumU64(roleId) checkPayAmount, _ := model.Str2Num(payAmount) if gameRoleId <= 0 || checkPayAmount <= 0 { c.Data(http.StatusOK, "text/plain; charset=utf-8", []byte("FAILED")) return } ntfData := &WebNotifyData{} ntfData.GameRoleId = gameRoleId ntfData.CpOrderId = cpOrderId ntfData.SdkOrderId = sdkOrderId ntfData.PayMethod = "" ntfData.PayCurrency = "" ntfData.PayTime = uint64(util.GetTimeSeconds()) ntfData.PayChannel = "WebPayH5Notify" ntfData.GoodsType, _ = model.Str2NumU64(goodsType) ntfData.GoodsID, _ = model.Str2NumU64(goodsID) ret := webPayNotifyH5(ntfData, float32(checkPayAmount)/100, c) c.Data(http.StatusOK, "text/plain; charset=utf-8", []byte(ret)) } type WebNotifyData struct { CpOrderId string SdkOrderId string PayMethod string PayCurrency string PayTime uint64 PayChannel string GameRoleId uint64 GoodsType uint64 GoodsID uint64 } func webPayNotify(webNtf *WebNotifyData, payAmount float32, c *gin.Context) string { //流程处理gmweb保存订单状态到redis中设置为 成功充值状态 //发送给gameserver,成功收到后设置订单状态为成功获取充值状态,如果gameserver没有收到 //每次玩家上线时,重新获取一次订单状态如果是成功充值,但是没有获取成功就获取一次 // 充值成功获取对应的ntdata数据 // 1,回复成/失败消息给quick // 2,订单状态写入redis(判重处理),并发送给social做获取奖励处理 msgStr, err := service.GetRedis().HGet(model.PayOrderPrefix, webNtf.CpOrderId).Result() if err != nil { //util.ErrorF("WebPayQuickNotify order not exist err=%v", err) util.ErrorF("WebPayQuickNotify order not exist err=%v, cpOrderId=%v, sdkOrderId=%v", err, webNtf.CpOrderId, webNtf.SdkOrderId) //c.JSON(http.StatusOK, "FAILED") //return "FAILED" return fmt.Sprintf("FAILED,cpOrderId=%v err=%v", webNtf.CpOrderId, err) } payInfo := &serverproto.PayOrderSaveInfo{} err = model.GetDecodeMessage(payInfo, msgStr) if err != nil { util.ErrorF("WebPayQuickNotify GetDecodeMessage err=%, cpOrderId=%v, sdkOrderId=%v", err, webNtf.CpOrderId, webNtf.SdkOrderId) //util.ErrorF("WebPayQuickNotify GetDecodeMessage err=%v", err) //c.JSON(http.StatusOK, "FAILED") //return "FAILED" return fmt.Sprintf("FAILED,cpOrderId=%v err=%v", webNtf.CpOrderId, err) } if payInfo.OrderState == int32(serverproto.PayOrderState_EPayOrderState_Gen) { //实际支付 == 订单的钱,否则为支付失败 payAmount := int32(payAmount * 10) //该渠道是以分为单位(游戏以卢布为单位) //服务器订单实际金额: orderAmount := int32(payInfo.Amount * 1000) if payAmount == orderAmount { payInfo.OrderState = int32(serverproto.PayOrderState_EPayOrderState_PayOk) } else { payInfo.OrderState = int32(serverproto.PayOrderState_EPayOrderState_PayFailed) util.ErrorF("uid=%v WebPayQuickNotify failed payAmount:%v order=%v", payInfo.Uid, payAmount, payInfo) } payInfo.OrderProcessTime = util.GetTimeMilliseconds() payInfo.SdkOrderId = webNtf.SdkOrderId //sdk订单id\ payInfo.PayMethod = webNtf.PayMethod payInfo.PayCurrency = webNtf.PayCurrency payInfo.PayTime = webNtf.PayTime payInfo.PayChannel = webNtf.PayChannel //订单状态修改,写入数据库(后续玩家发货成功后会再次修改订单状态为PayOrderState_EPayOrderState_PayOkReward) err, newPayInfoStr := model.GetEncodeMessage(payInfo) if err == nil { service.GetRedis().HSet(model.PayOrderPrefix, webNtf.CpOrderId, newPayInfoStr) } //完成订单id列表(避免上次发货不成功,玩家下次登陆时可以重新获取一次奖励) uidStr := strconv.FormatUint(payInfo.Uid, 10) okListKeyStr := model.PayOrderOKIdListPrefix + uidStr service.GetRedis().SAdd(okListKeyStr, payInfo.CpOrderId) if payInfo.OrderState == int32(serverproto.PayOrderState_EPayOrderState_PayOk) { ssNtfMsg := &serverproto.SSPayInfoOrderNtf{ PayOrderInfo: payInfo, } selfmodel.SendSocial(ssNtfMsg) } util.InfoF("uid=%v WebPayQuickNotify ok order=%v", payInfo.Uid, payInfo) } else { util.ErrorF("WebPayQuickNotify uid=%v state error state=%v", payInfo.Uid, payInfo.OrderState) //return "FAILED" return fmt.Sprintf("FAILED,cpOrderId=%v state error=%v", webNtf.CpOrderId, payInfo.OrderState) } return "SUCCESS" } func webPayNotifyDn(cpOrderId string, Amount float64) string { //流程处理gmweb保存订单状态到redis中设置为 成功充值状态 //发送给gameserver,成功收到后设置订单状态为成功获取充值状态,如果gameserver没有收到 //每次玩家上线时,重新获取一次订单状态如果是成功充值,但是没有获取成功就获取一次 // 充值成功获取对应的ntdata数据 // 1,回复成/失败消息给quick // 2,订单状态写入redis(判重处理),并发送给social做获取奖励处理 msgStr, err := service.GetRedis().HGet(model.PayOrderPrefix, cpOrderId).Result() if err != nil { //util.ErrorF("WebPayQuickNotify order not exist err=%v", err) util.ErrorF("WebPayQuickNotify order not exist err=%v, cpOrderId=%v, sdkOrderId=%v", err, cpOrderId, 0) //c.JSON(http.StatusOK, "FAILED") //return "FAILED" return fmt.Sprintf("FAILED,cpOrderId=%v err=%v", cpOrderId, err) } payInfo := &serverproto.PayOrderSaveInfo{} err = model.GetDecodeMessage(payInfo, msgStr) if err != nil { util.ErrorF("WebPayQuickNotify GetDecodeMessage err=%, cpOrderId=%v, sdkOrderId=%v", err, cpOrderId, 0) //util.ErrorF("WebPayQuickNotify GetDecodeMessage err=%v", err) //c.JSON(http.StatusOK, "FAILED") //return "FAILED" return fmt.Sprintf("FAILED,cpOrderId=%v err=%v", cpOrderId, err) } if payInfo.OrderState == int32(serverproto.PayOrderState_EPayOrderState_Gen) { //实际支付 == 订单的钱,否则为支付失败 payAmount := int32(Amount * 10) //该渠道是以分为单位(游戏以卢布为单位) ////服务器订单实际金额: orderAmount := int32(payInfo.Amount * 1000) if payAmount == orderAmount { payInfo.OrderState = int32(serverproto.PayOrderState_EPayOrderState_PayOk) } else { payInfo.OrderState = int32(serverproto.PayOrderState_EPayOrderState_PayFailed) util.ErrorF("uid=%v WebPayQuickNotify failed payAmount:%v order=%v", payInfo.Uid, payAmount, payInfo) } payInfo.OrderState = int32(serverproto.PayOrderState_EPayOrderState_PayOk) payInfo.OrderProcessTime = util.GetTimeMilliseconds() //payInfo.SdkOrderId = webNtf.SdkOrderId //sdk订单id\ //payInfo.PayMethod = webNtf.PayMethod //payInfo.PayCurrency = webNtf.PayCurrency payInfo.PayTime = util.GetTimeMilliseconds() payInfo.PayChannel = "dn" //订单状态修改,写入数据库(后续玩家发货成功后会再次修改订单状态为PayOrderState_EPayOrderState_PayOkReward) err, newPayInfoStr := model.GetEncodeMessage(payInfo) if err == nil { service.GetRedis().HSet(model.PayOrderPrefix, cpOrderId, newPayInfoStr) } //完成订单id列表(避免上次发货不成功,玩家下次登陆时可以重新获取一次奖励) uidStr := strconv.FormatUint(payInfo.Uid, 10) okListKeyStr := model.PayOrderOKIdListPrefix + uidStr service.GetRedis().SAdd(okListKeyStr, payInfo.CpOrderId) if payInfo.OrderState == int32(serverproto.PayOrderState_EPayOrderState_PayOk) { ssNtfMsg := &serverproto.SSPayInfoOrderNtf{ PayOrderInfo: payInfo, } selfmodel.SendSocial(ssNtfMsg) } util.InfoF("uid=%v WebPayQuickNotify ok order=%v", payInfo.Uid, payInfo) } else { util.ErrorF("WebPayQuickNotify uid=%v state error state=%v", payInfo.Uid, payInfo.OrderState) //return "FAILED" return fmt.Sprintf("FAILED,cpOrderId=%v state error=%v", cpOrderId, payInfo.OrderState) } return "SUCCESS" } // 外层发起主动充值(不走游戏流程) func webPayNotifyH5(webNtf *WebNotifyData, payAmount float32, c *gin.Context) string { payInfo := &serverproto.PayOrderSaveInfo{} payInfo.Uid = webNtf.GameRoleId payInfo.Amount = payAmount payInfo.OrderProcessTime = util.GetTimeMilliseconds() payInfo.SdkOrderId = webNtf.SdkOrderId //sdk订单id\ payInfo.PayMethod = webNtf.PayMethod payInfo.PayCurrency = webNtf.PayCurrency payInfo.PayTime = webNtf.PayTime payInfo.PayChannel = webNtf.PayChannel payInfo.GoodsType = int32(webNtf.GoodsType) payInfo.GoodsId = int32(webNtf.GoodsID) rewardStr := c.DefaultQuery("reward", "") //reward rewardStrList := strings.Split(rewardStr, ",") for idx := 0; idx < len(rewardStrList); idx++ { key, val := model.Str2Res(rewardStrList[idx]) if key > 0 && val > 0 { payInfo.RewardList = append(payInfo.RewardList, &serverproto.KeyValueType{Key: key, Value: val}) } } payInfo.OrderState = int32(serverproto.PayOrderState_EPayOrderState_PayOk) //订单状态修改,写入数据库(后续玩家发货成功后会再次修改订单状态为PayOrderState_EPayOrderState_PayOkReward) err, newPayInfoStr := model.GetEncodeMessage(payInfo) if err == nil { service.GetRedis().HSet(model.PayOrderPrefix, webNtf.CpOrderId, newPayInfoStr) } //完成订单id列表(避免上次发货不成功,玩家下次登陆时可以重新获取一次奖励) uidStr := strconv.FormatUint(payInfo.Uid, 10) okListKeyStr := model.PayOrderOKIdListPrefix + uidStr service.GetRedis().SAdd(okListKeyStr, payInfo.CpOrderId) util.InfoF("webPayNotifyH5: %v", payInfo) ssNtfMsg := &serverproto.SSPayInfoOrderNtf{ PayOrderInfo: payInfo, } selfmodel.SendSocial(ssNtfMsg) return "SUCCESS" }