web_paymsg.go 50 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532
  1. package msg
  2. import (
  3. "bytes"
  4. "crypto"
  5. "crypto/hmac"
  6. "crypto/md5"
  7. "crypto/rsa"
  8. "crypto/sha1"
  9. "crypto/x509"
  10. "database/sql"
  11. "encoding/base64"
  12. "encoding/hex"
  13. "encoding/json"
  14. "encoding/pem"
  15. "encoding/xml"
  16. "fmt"
  17. "io"
  18. "math/big"
  19. "net/http"
  20. "net/url"
  21. "rocommon/service"
  22. "rocommon/socket/mysql"
  23. "rocommon/util"
  24. "roserver/baseserver/model"
  25. gmweb "roserver/gmweb/model"
  26. selfmodel "roserver/gmweb/model"
  27. "roserver/serverproto"
  28. "sort"
  29. "strconv"
  30. "strings"
  31. "time"
  32. "github.com/gin-gonic/gin"
  33. )
  34. // https://blog.csdn.net/chunyouhai5703/article/details/100978656?utm_medium=distribute.pc_relevant.none-task-blog-title-1&spm=1001.2101.3001.4242
  35. type QuickPayNotify struct {
  36. XMLName xml.Name `xml:"quicksdk_message"`
  37. Message QuickTBData `xml:"message"`
  38. }
  39. type QuickTBData struct {
  40. IsTest bool `xml:"is_test"`
  41. Channel string `xml:"channel"`
  42. ChannelUid string `xml:"channel_uid"`
  43. GameOrder string `xml:"game_order"`
  44. PayTime string `xml:"pay_time"`
  45. Amount float32 `xml:"amount"`
  46. Status int32 `xml:"status"`
  47. ExtrasParams string `xml:"extras_params"`
  48. }
  49. /*
  50. <?xml version="1.0" encoding="UTF-8" standalone="no">
  51. <quicksdk_message>
  52. <message>
  53. <is_test>0</is_test>
  54. <channel>8888</channel>
  55. <channel_uid>231845</channel_uid>
  56. <game_order>123456789</game_order>
  57. <order_no>12520160612114220441168433</order_no>
  58. <pay_time>2016-06-12 11:42:20</pay_time>
  59. <amount>1.00</amount>
  60. <status>0</status>
  61. <extras_params>{1}_{2}</extras_params>
  62. </message>
  63. </quicksdk_message>
  64. */
  65. func WebPayQuickNotify(c *gin.Context) {
  66. //ntData := c.PostForm("nt_data")
  67. //sign := c.PostForm("sign")
  68. //md5Sign := c.PostForm("md5Sign")
  69. //
  70. //data := ntData + sign + service.GetServiceConfig().SDKConfig.QuickMd5key
  71. //tmpSign := md5.Sum([]byte(data))
  72. //md5Str := fmt.Sprintf("%x", tmpSign)
  73. //util.DebugF("WebPayQuickNotify ntData=%v sign=%v md5sign=%v tmpsign=%v", ntData, sign, md5Sign, md5Str)
  74. //if md5Str == md5Sign {
  75. // util.InfoF("WebPayQuickNotify ok")
  76. //} else {
  77. // util.ErrorF("WebPayQuickNotify sign invalid!!!")
  78. // c.JSON(http.StatusOK, "FAILED")
  79. // return
  80. //}
  81. //
  82. ////decode nt_data
  83. //tmpNtDataList := strings.Split(ntData, "@")
  84. //tmpNtData := make([]byte, len(tmpNtDataList))
  85. //tmpKeyData := []byte(service.GetServiceConfig().SDKConfig.QuickCallbackKey)
  86. //for idx := 1; idx < len(tmpNtDataList); idx++ {
  87. // tmpVal, _ := strconv.Atoi(tmpNtDataList[idx])
  88. // tmpNtData[idx] = (byte)(tmpVal - (int)(0xff&tmpKeyData[(idx-1)%len(tmpKeyData)]))
  89. //}
  90. ////字符串最前面会有一个空格
  91. //if string(tmpNtData[0]) == "\u0000" {
  92. // tmpNtData = append(tmpNtData[:0], tmpNtData[1:]...)
  93. //}
  94. //util.InfoF("WebPayQuickNotify ntdata=%v", string(tmpNtData))
  95. //
  96. //tmpSt := &QuickPayNotify{}
  97. //err := xml.Unmarshal(tmpNtData, tmpSt)
  98. //if err != nil {
  99. // util.ErrorF("WebPayQuickNotify xml decode err=%v", err)
  100. // c.JSON(http.StatusOK, "FAILED")
  101. // return
  102. //}
  103. //
  104. //ntfData := &WebNotifyData{}
  105. //ntfData.CpOrderId = tmpSt.Message.GameOrder
  106. //ntfData.SdkOrderId = ""
  107. //ntfData.PayMethod = ""
  108. //ntfData.PayCurrency = ""
  109. //ntfData.PayTime = uint64(util.GetTimeSeconds())
  110. //ntfData.PayChannel = ""
  111. //webPayNotify(ntfData, tmpSt.Message.Amount, c)
  112. //c.JSON(http.StatusOK, "SUCCESS")
  113. game_order := c.PostForm("game_order") //游戏订单号
  114. order_no := c.PostForm("order_no") //SDK订单ID
  115. amount := c.PostForm("amount") //充值金额
  116. PayChannel := c.PostForm("channel") //充值渠道
  117. serverId := c.PostForm("server_id") //充值服ID
  118. util.DebugF("收到充值订单:GameOrder=%v, SdkOfderId=%v, PauAmount=%v, PayChannel=%v, serverId=%v", game_order, order_no, amount, PayChannel, serverId)
  119. checkPayAmount, _ := model.Str2Float32(amount)
  120. ntfData := &WebNotifyData{}
  121. ntfData.CpOrderId = game_order
  122. ntfData.SdkOrderId = order_no
  123. ntfData.PayMethod = ""
  124. ntfData.PayCurrency = ""
  125. ntfData.PayTime = uint64(util.GetTimeSeconds())
  126. ntfData.PayChannel = PayChannel
  127. retState := webPayNotify(ntfData, checkPayAmount, c)
  128. //c.JSON(http.StatusOK, `success`)
  129. c.Data(http.StatusOK, "text/plain; charset=utf-8", []byte(retState))
  130. }
  131. func getMd5Sign(callbackKey string, params map[string]string) string {
  132. // 删除参数中的 sign 字段
  133. delete(params, "sign")
  134. // 按参数名进行升序排序
  135. var keys []string
  136. for key := range params {
  137. keys = append(keys, key)
  138. }
  139. sort.Strings(keys)
  140. // 拼接参数和值
  141. var signKey strings.Builder
  142. for _, key := range keys {
  143. signKey.WriteString(key)
  144. signKey.WriteString("=")
  145. signKey.WriteString(params[key])
  146. signKey.WriteString("&")
  147. }
  148. // 添加回调密钥
  149. signKey.WriteString(callbackKey)
  150. // 计算 MD5
  151. hash := md5.Sum([]byte(signKey.String()))
  152. return hex.EncodeToString(hash[:])
  153. }
  154. func getMd5SignXiaoqi(params map[string]string) string {
  155. // 删除参数中的 sign 字段
  156. delete(params, "sign_data")
  157. // 按参数名进行升序排序
  158. var keys []string
  159. for key := range params {
  160. keys = append(keys, key)
  161. }
  162. sort.Strings(keys)
  163. // 拼接参数和值
  164. var signKey strings.Builder
  165. for _, key := range keys {
  166. signKey.WriteString(key)
  167. signKey.WriteString("=")
  168. signKey.WriteString(params[key])
  169. signKey.WriteString("&")
  170. }
  171. return signKey.String()
  172. }
  173. func getMd5RuSign(callbackKey string, params map[string]string) string {
  174. // 删除参数中的 sign 字段
  175. delete(params, "sign")
  176. // 按参数名进行升序排序
  177. var keys []string
  178. for key := range params {
  179. keys = append(keys, key)
  180. }
  181. sort.Strings(keys)
  182. // 拼接参数和值
  183. var signKey strings.Builder
  184. for i, key := range keys {
  185. signKey.WriteString(key)
  186. signKey.WriteString("=")
  187. signKey.WriteString(params[key])
  188. if i != len(keys)-1 {
  189. signKey.WriteString("&")
  190. }
  191. }
  192. // 添加回调密钥
  193. signKey.WriteString(callbackKey)
  194. // 计算 MD5
  195. hash := md5.Sum([]byte(signKey.String()))
  196. return hex.EncodeToString(hash[:])
  197. }
  198. func getMd5DnSign(callbackKey string, username, order_id, server, amount, extra, sandbox, timestamp string) string {
  199. // 拼接参数和值
  200. var signKey strings.Builder
  201. signKey.WriteString(username)
  202. signKey.WriteString(order_id)
  203. signKey.WriteString(server)
  204. signKey.WriteString(amount)
  205. signKey.WriteString(extra)
  206. signKey.WriteString(sandbox)
  207. signKey.WriteString(timestamp)
  208. // 添加回调密钥
  209. signKey.WriteString(callbackKey)
  210. // 计算 MD5
  211. hash := md5.Sum([]byte(signKey.String()))
  212. return hex.EncodeToString(hash[:])
  213. }
  214. type Extras struct {
  215. ServerId int `json:"serverId"`
  216. Platform string `json:"platform"`
  217. SubPlatform string `json:"subPlatform"`
  218. Bima string `json:"bima"`
  219. CpOrderId string `json:"cpOrderId"`
  220. }
  221. type ExtrasRu struct {
  222. AccountId string `json:"accountId"`
  223. Money string `json:"money"`
  224. Addtime string `json:"addtime"`
  225. OrderId string `json:"orderId"`
  226. CustomorderId string `json:"customorderId"`
  227. Paytype string `json:"paytype"`
  228. Success string `json:"success"`
  229. }
  230. type ExtrasDn struct {
  231. OrderNo string `json:"orderNo"`
  232. Uid string `json:"uid"`
  233. Platform string `json:"platform"`
  234. GoodsId int32 `json:"goodsId"`
  235. GoodsType int32 `json:"goodsType"`
  236. }
  237. type ExtrasDnIos struct {
  238. OrderNo string `json:"biwb"`
  239. Uid string `json:"uid"`
  240. Platform string `json:"bivz"`
  241. GoodsId int32 `json:"goodsId"`
  242. GoodsType int32 `json:"goodsType"`
  243. }
  244. // 海外版quick回调
  245. func WebPayHwQuickNotify(c *gin.Context) {
  246. //util.DebugF("支付回调信息:%v", c.Request.PostForm)
  247. params := make(map[string]string)
  248. if err := c.Request.ParseForm(); err != nil {
  249. util.InfoF("parseForm falied")
  250. c.String(http.StatusOK, "FAILED")
  251. return
  252. }
  253. util.DebugF("支付回调信息2:%v", c.Request.PostForm)
  254. for key, value := range c.Request.PostForm {
  255. params[key] = value[0] // 假设每个参数只有一个值
  256. }
  257. sign := params["sign"]
  258. info2 := params["extrasParams"]
  259. info := strings.ReplaceAll(info2, "\\", "")
  260. var extras Extras
  261. err := json.Unmarshal([]byte(info), &extras)
  262. if err != nil {
  263. util.ErrorF("支付回调参数解析错误:%v", err)
  264. }
  265. util.InfoF("支付签名认证:%v params:%v", extras, params)
  266. if extras.Platform == "SDKYOUYI_IOS" || extras.Bima == "SDKYOUYI_IOS" {
  267. util.ErrorF("ios 支付签名认证:%v", info)
  268. newSign := getMd5Sign("58696021497436514481898335416221", params)
  269. if newSign != sign {
  270. util.ErrorF("签名错误%v", sign)
  271. c.String(http.StatusOK, "FAILED")
  272. return
  273. }
  274. } else if extras.Platform == "SDKYOUYI_IOS_MyCard" || extras.Platform == "SDKHwQuick_MyCard" {
  275. util.ErrorF("mycard 支付签名认证:%v", info)
  276. newSign := getMd5Sign("03422134397322604272901806704074", params)
  277. if newSign != sign {
  278. util.ErrorF("签名错误%v", sign)
  279. c.String(http.StatusOK, "FAILED")
  280. return
  281. }
  282. } else {
  283. util.ErrorF("android 支付签名认证:%v", info)
  284. newSign := getMd5Sign("47409863970932353623015025039223", params)
  285. if newSign != sign {
  286. util.ErrorF("签名错误%v", sign)
  287. c.String(http.StatusOK, "FAILED")
  288. return
  289. }
  290. }
  291. uid := c.PostForm("uid")
  292. cpOrderId := c.PostForm("cpOrderNo")
  293. if cpOrderId == "" {
  294. if extras.CpOrderId != "" {
  295. cpOrderId = extras.CpOrderId
  296. } else {
  297. util.ErrorF("mycard pay cporderId is nil extras:%v", extras)
  298. }
  299. }
  300. orderNo := c.PostForm("orderNo")
  301. payAmount := c.PostForm("payAmount")
  302. payCurrency := c.PostForm("payCurrency")
  303. payType := c.PostForm("payType")
  304. usdAmount := c.PostForm("usdAmount")
  305. ntfData := &WebNotifyData{}
  306. ntfData.CpOrderId = cpOrderId
  307. ntfData.SdkOrderId = orderNo
  308. ntfData.PayMethod = payType
  309. ntfData.PayCurrency = payCurrency
  310. ntfData.PayTime = uint64(util.GetTimeSeconds())
  311. ntfData.PayChannel = "qk_hw"
  312. util.WarnF("paycallback uid=%v cpOrderNo=%v orderNo=%v payAmount=%v payCurrency=%v payType=%v usdAmount=%v",
  313. uid, cpOrderId, orderNo, payAmount, payCurrency, payType, usdAmount)
  314. f64, err := strconv.ParseFloat(usdAmount, 32)
  315. if err != nil {
  316. fmt.Println("Error:", err)
  317. return
  318. }
  319. webPayNotify(ntfData, float32(f64), c)
  320. c.String(http.StatusOK, "SUCCESS")
  321. }
  322. const xiaoqiIoskey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdP+3oq+95l5CvsqmZvzgTdueiIWur64OePQkKeNUaKTAR3ar4NU9laEvgI+pkN6q+7BoPpprTB/aBqoU5eLNFnPt/6T0Dq5245e+HGij4qUYiORsU12O+pex5jxWg/knnW1g5F8SrLtAr9lwJbOc4lNPFKi+U+1fdayC64qxmjQIDAQAB"
  323. const xiaoqiAndroidkey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCfYd3FqSaWqCpWLSktBSSgAelt0F6T+tO4C25YKR/6X/sPacDBbX662/0fW+H+YbXigHWFB/yangkhiZTpD/VmiOo5lISX6L0/m+13ti9b8jzTZcfVngfLsP+Ztbk81N1Jk0gWF4bndZxREJ3IxcEDHnIrwXgLGA2GJ89kdgudwIDAQAB"
  324. // 海外版xiaoqi回调
  325. func WebPayHwXiaoQiNotify(c *gin.Context) {
  326. //util.DebugF("支付回调信息:%v", c.Request.PostForm)
  327. params := make(map[string]string)
  328. if err := c.Request.ParseForm(); err != nil {
  329. util.InfoF("parseForm falied")
  330. c.String(http.StatusOK, "failed:order error")
  331. return
  332. }
  333. util.DebugF("支付回调信息2:%v", c.Request.PostForm)
  334. for key, value := range c.Request.PostForm {
  335. params[key] = value[0] // 假设每个参数只有一个值
  336. }
  337. info2 := params["extends_info_data"]
  338. info := strings.ReplaceAll(info2, "\\", "")
  339. var extras Extras
  340. err := json.Unmarshal([]byte(info), &extras)
  341. if err != nil {
  342. util.ErrorF("支付回调参数解析错误:%v", err)
  343. }
  344. var myData map[string]string
  345. var err3 error
  346. util.InfoF("xiaoqi 透传参数:%v params:%v", extras, params)
  347. if extras.Platform == "IOS_X7" || extras.Bima == "IOS_X7" {
  348. util.ErrorF("xiaoqi ios 支付签名认证:%v", info)
  349. b, err2 := VerifySignature(params, xiaoqiIoskey)
  350. if err2 != nil || !b {
  351. util.ErrorF("签名错误%v", err2)
  352. c.String(http.StatusOK, "sign_data_verify_failed")
  353. return
  354. }
  355. myData, err3 = DecryptDataToMap(params["encryp_data"], xiaoqiIoskey)
  356. if err3 != nil {
  357. util.ErrorF("解析encryp_data error:%v", err3)
  358. c.String(http.StatusOK, "encryp_data_decrypt_failed")
  359. return
  360. }
  361. } else {
  362. util.ErrorF("android 支付签名认证:%v", info)
  363. b, err2 := VerifySignature(params, xiaoqiAndroidkey)
  364. if err2 != nil || !b {
  365. util.ErrorF("签名错误%v", err2)
  366. c.String(http.StatusOK, "sign_data_verify_failed")
  367. return
  368. }
  369. myData, err3 = DecryptDataToMap(params["encryp_data"], xiaoqiAndroidkey)
  370. if err3 != nil {
  371. util.ErrorF("解析encryp_data error:%v", err3)
  372. c.String(http.StatusOK, "encryp_data_decrypt_failed")
  373. return
  374. }
  375. }
  376. util.ErrorF("xiaoqi mydata:%v", myData)
  377. uid := params["game_role_id"]
  378. cpOrderId := myData["game_orderid"]
  379. if cpOrderId == "" {
  380. if extras.CpOrderId != "" {
  381. cpOrderId = extras.CpOrderId
  382. } else {
  383. util.ErrorF("mycard pay cporderId is nil extras:%v", extras)
  384. }
  385. }
  386. orderNo := params["xiao7_goid"]
  387. payCurrency := myData["game_currency"]
  388. //if payCurrency != "USD" {
  389. // util.ErrorF("xiaoqi pay currency is not USD:%v", payCurrency)
  390. // c.String(http.StatusOK, "failed:game_currency error")
  391. // return
  392. //}
  393. server := params["game_area"]
  394. if server != strconv.Itoa(service.GetServiceConfig().Node.Zone/2) {
  395. util.ErrorF("xiaoqi pay server is not correct:%v", server)
  396. c.String(http.StatusOK, "failed:game_area error")
  397. return
  398. }
  399. payType := myData["game_currency"]
  400. usdAmount := myData["pay_price"]
  401. ntfData := &WebNotifyData{}
  402. ntfData.CpOrderId = cpOrderId
  403. ntfData.SdkOrderId = orderNo
  404. ntfData.PayMethod = payType
  405. ntfData.PayCurrency = payCurrency
  406. ntfData.PayTime = uint64(util.GetTimeSeconds())
  407. ntfData.PayChannel = "xiaoqi"
  408. ntfData.Guid = myData["guid"]
  409. ntfData.RoleName = params["game_role_name"]
  410. roleId, _ := strconv.ParseUint(params["game_role_id"], 10, 64)
  411. ntfData.GameRoleId = roleId
  412. util.WarnF("paycallback uid=%v cpOrderNo=%v orderNo=%v payAmount=%v payCurrency=%v payType=%v usdAmount=%v",
  413. uid, cpOrderId, orderNo, usdAmount, payCurrency, payType, usdAmount)
  414. f64, err := strconv.ParseFloat(usdAmount, 32)
  415. if err != nil {
  416. fmt.Println("Error:", err)
  417. c.String(http.StatusOK, "failed:order error")
  418. return
  419. }
  420. s := webPayNotify(ntfData, float32(f64), c)
  421. if s != "SUCCESS" {
  422. c.String(http.StatusOK, s)
  423. } else {
  424. c.String(http.StatusOK, "success")
  425. }
  426. }
  427. // 使用公钥解密(对应 PHP 的 openssl_public_decrypt)
  428. func DecryptDataToMap(encrypDataBase64 string, publicKeyStr string) (map[string]string, error) {
  429. // 1. Base64 解码得到 raw_encryp_data
  430. rawEncrypData, err := decodeBase64Compat(encrypDataBase64)
  431. if err != nil {
  432. return nil, fmt.Errorf("base64解码失败: %v", err)
  433. }
  434. // 2. 使用 RSA 公钥解密
  435. decryptedData, err := rsaPublicDecrypt(rawEncrypData, publicKeyStr)
  436. if err != nil {
  437. return nil, fmt.Errorf("RSA解密失败: %v", err)
  438. }
  439. // 3. 解析查询字符串为 map
  440. return parseQueryStringToMap(string(decryptedData)), nil
  441. }
  442. func rsaPublicDecrypt(ciphertext []byte, publicKeyStr string) ([]byte, error) {
  443. // 解析公钥
  444. publicKey, err := parsePublicKey(publicKeyStr)
  445. if err != nil {
  446. return nil, fmt.Errorf("解析公钥失败: %v", err)
  447. }
  448. keySize := (publicKey.N.BitLen() + 7) / 8
  449. if keySize == 0 {
  450. return nil, fmt.Errorf("无效RSA公钥")
  451. }
  452. if len(ciphertext)%keySize != 0 {
  453. return nil, fmt.Errorf("密文长度非法: len=%d keySize=%d", len(ciphertext), keySize)
  454. }
  455. // 兼容长消息分段密文(每段一个 RSA block)。
  456. plainData := make([]byte, 0, len(ciphertext))
  457. e := big.NewInt(int64(publicKey.E))
  458. for offset := 0; offset < len(ciphertext); offset += keySize {
  459. block := ciphertext[offset : offset+keySize]
  460. c := new(big.Int).SetBytes(block)
  461. if c.Cmp(publicKey.N) > 0 {
  462. return nil, fmt.Errorf("密文块超出模数范围")
  463. }
  464. m := new(big.Int).Exp(c, e, publicKey.N)
  465. em := leftPadToSize(m.Bytes(), keySize)
  466. plainBlock, err := unpadPKCS1v15ForPublicDecrypt(em)
  467. if err != nil {
  468. return nil, fmt.Errorf("块解密失败: %v", err)
  469. }
  470. plainData = append(plainData, plainBlock...)
  471. }
  472. return plainData, nil
  473. }
  474. func decodeBase64Compat(raw string) ([]byte, error) {
  475. // form-urlencoded 场景下,+ 可能被自动转为空格。
  476. s := strings.TrimSpace(strings.ReplaceAll(raw, " ", "+"))
  477. if s == "" {
  478. return nil, fmt.Errorf("空字符串")
  479. }
  480. encodings := []*base64.Encoding{
  481. base64.StdEncoding,
  482. base64.RawStdEncoding,
  483. base64.URLEncoding,
  484. base64.RawURLEncoding,
  485. }
  486. var lastErr error
  487. for _, enc := range encodings {
  488. data, err := enc.DecodeString(s)
  489. if err == nil {
  490. return data, nil
  491. }
  492. lastErr = err
  493. }
  494. return nil, lastErr
  495. }
  496. func leftPadToSize(src []byte, size int) []byte {
  497. if len(src) >= size {
  498. return src
  499. }
  500. dst := make([]byte, size)
  501. copy(dst[size-len(src):], src)
  502. return dst
  503. }
  504. // unpadPKCS1v15ForPublicDecrypt 兼容 openssl_public_decrypt 的 PKCS#1 v1.5 去填充。
  505. func unpadPKCS1v15ForPublicDecrypt(em []byte) ([]byte, error) {
  506. if len(em) < 11 {
  507. return nil, fmt.Errorf("EM 长度过短")
  508. }
  509. if em[0] != 0x00 {
  510. return nil, fmt.Errorf("EM 格式错误: 缺少前导0x00")
  511. }
  512. switch em[1] {
  513. case 0x01:
  514. i := 2
  515. for i < len(em) && em[i] == 0xFF {
  516. i++
  517. }
  518. if i < 10 {
  519. return nil, fmt.Errorf("PKCS#1 type1 填充长度不足")
  520. }
  521. if i >= len(em) || em[i] != 0x00 {
  522. return nil, fmt.Errorf("PKCS#1 type1 分隔符缺失")
  523. }
  524. return em[i+1:], nil
  525. case 0x02:
  526. // 某些渠道可能走普通公钥加密块,这里也做兼容。
  527. i := 2
  528. for i < len(em) && em[i] != 0x00 {
  529. i++
  530. }
  531. if i < 10 {
  532. return nil, fmt.Errorf("PKCS#1 type2 填充长度不足")
  533. }
  534. if i >= len(em) || em[i] != 0x00 {
  535. return nil, fmt.Errorf("PKCS#1 type2 分隔符缺失")
  536. }
  537. return em[i+1:], nil
  538. default:
  539. return nil, fmt.Errorf("不支持的填充类型: 0x%02x", em[1])
  540. }
  541. }
  542. // 解析查询字符串为 map
  543. func parseQueryStringToMap(queryStr string) map[string]string {
  544. result := make(map[string]string)
  545. // 按 & 分割
  546. pairs := strings.Split(queryStr, "&")
  547. for _, pair := range pairs {
  548. if pair == "" {
  549. continue
  550. }
  551. // 按 = 分割
  552. kv := strings.SplitN(pair, "=", 2)
  553. if len(kv) == 2 {
  554. // URL decode 值(如果需要)
  555. value, err := url.QueryUnescape(kv[1])
  556. if err != nil {
  557. value = kv[1]
  558. }
  559. result[kv[0]] = value
  560. } else if len(kv) == 1 {
  561. result[kv[0]] = ""
  562. }
  563. }
  564. return result
  565. }
  566. func VerifySignature(params map[string]string, publicKeyStr string) (bool, error) {
  567. // 1. 获取并解码 sign_data 参数
  568. signDataBase64, ok := params["sign_data"]
  569. if !ok {
  570. return false, fmt.Errorf("缺少 sign_data 参数")
  571. }
  572. // base64_decode 得到 raw_sign_data
  573. rawSignData, err := decodeBase64Compat(signDataBase64)
  574. if err != nil {
  575. return false, fmt.Errorf("base64解码失败: %v", err)
  576. }
  577. // 2. 构建 source_str(排除 sign_data,其他参数按字典序排序)
  578. sourceStr := buildSourceString(params)
  579. // 3. 验证签名
  580. err = verifyWithPublicKey(sourceStr, rawSignData, publicKeyStr)
  581. if err != nil {
  582. return false, err
  583. }
  584. return true, nil
  585. }
  586. // buildSourceString 构建查询字符串(排除 sign_data,按字典序排序)
  587. func buildSourceString(params map[string]string) string {
  588. // 收集除 sign_data 外的所有键
  589. keys := make([]string, 0)
  590. for key := range params {
  591. if key != "sign_data" {
  592. keys = append(keys, key)
  593. }
  594. }
  595. // 字典序排序
  596. sort.Strings(keys)
  597. // 拼接成 key=value&key=value 格式
  598. var pairs []string
  599. for _, key := range keys {
  600. value := params[key]
  601. pairs = append(pairs, fmt.Sprintf("%s=%s", key, value))
  602. }
  603. return strings.Join(pairs, "&")
  604. }
  605. // verifyWithPublicKey 使用公钥验证签名
  606. func verifyWithPublicKey(data string, signature []byte, publicKeyStr string) error {
  607. // 1. 解析公钥(支持多种格式)
  608. publicKey, err := parsePublicKey(publicKeyStr)
  609. if err != nil {
  610. return fmt.Errorf("解析公钥失败: %v", err)
  611. }
  612. // 2. 计算 SHA1 哈希
  613. hash := sha1.Sum([]byte(data))
  614. // 3. 验证签名
  615. err = rsa.VerifyPKCS1v15(publicKey, crypto.SHA1, hash[:], signature)
  616. if err != nil {
  617. return fmt.Errorf("签名验证失败: %v", err)
  618. }
  619. return nil
  620. }
  621. // parsePublicKey 解析 PEM 格式的公钥
  622. func parsePublicKey(publicKeyStr string) (*rsa.PublicKey, error) {
  623. // 去除空白字符
  624. publicKeyStr = strings.TrimSpace(publicKeyStr)
  625. // 如果公钥字符串不包含 PEM 头,尝试添加
  626. if !strings.Contains(publicKeyStr, "-----BEGIN") {
  627. publicKeyStr = "-----BEGIN PUBLIC KEY-----\n" +
  628. publicKeyStr +
  629. "\n-----END PUBLIC KEY-----"
  630. }
  631. // 解码 PEM
  632. block, _ := pem.Decode([]byte(publicKeyStr))
  633. if block == nil {
  634. return nil, fmt.Errorf("PEM解码失败")
  635. }
  636. // 解析公钥
  637. pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
  638. if err != nil {
  639. return nil, err
  640. }
  641. publicKey, ok := pubInterface.(*rsa.PublicKey)
  642. if !ok {
  643. return nil, fmt.Errorf("不是RSA公钥")
  644. }
  645. return publicKey, nil
  646. }
  647. // parsePublicKey 解析 PEM 格式的公钥
  648. //func parsePublicKey(publicKeyStr string) (*rsa.PublicKey, error) {
  649. // // 去除可能的空白字符
  650. // publicKeyStr = strings.TrimSpace(publicKeyStr)
  651. //
  652. // // 如果公钥字符串不包含 PEM 头,尝试添加
  653. // if !strings.Contains(publicKeyStr, "-----BEGIN") {
  654. // publicKeyStr = "-----BEGIN PUBLIC KEY-----\n" +
  655. // publicKeyStr +
  656. // "\n-----END PUBLIC KEY-----"
  657. // }
  658. //
  659. // // 解码 PEM
  660. // block, _ := pem.Decode([]byte(publicKeyStr))
  661. // if block == nil {
  662. // return nil, fmt.Errorf("PEM 解码失败")
  663. // }
  664. //
  665. // // 解析公钥
  666. // pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
  667. // if err != nil {
  668. // return nil, err
  669. // }
  670. //
  671. // publicKey, ok := pubInterface.(*rsa.PublicKey)
  672. // if !ok {
  673. // return nil, fmt.Errorf("不是 RSA 公钥")
  674. // }
  675. //
  676. // return publicKey, nil
  677. //}
  678. func WebPayHwRuNotify(c *gin.Context) {
  679. //util.DebugF("支付回调信息:%v", c.Request.PostForm)
  680. params := make(map[string]string)
  681. if err := c.Request.ParseForm(); err != nil {
  682. util.InfoF("parseForm falied")
  683. c.String(http.StatusOK, "FAILED")
  684. return
  685. }
  686. util.DebugF("支付回调信息2:%v", c.Request.PostForm)
  687. for key, value := range c.Request.PostForm {
  688. params[key] = value[0] // 假设每个参数只有一个值
  689. }
  690. sign := params["sign"]
  691. info2 := params["custominfo"]
  692. info := strings.ReplaceAll(info2, "\\", "")
  693. var extras Extras
  694. err := json.Unmarshal([]byte(info), &extras)
  695. if err != nil {
  696. util.ErrorF("支付回调参数解析错误:%v", err)
  697. }
  698. util.InfoF("支付签名认证:%v params:%v", extras, params)
  699. if extras.Platform == "ZT_IOS" || extras.Bima == "ZT_IOS" {
  700. util.ErrorF("ios 支付签名认证:%v", info)
  701. newSign := getMd5RuSign("80c648e7df8aaa72", params)
  702. if newSign != sign {
  703. util.ErrorF("签名错误%v", sign)
  704. c.String(http.StatusOK, "FAILED")
  705. return
  706. }
  707. } else if extras.Platform == "SDKYOUYI_IOS_MyCard" || extras.Platform == "SDKHwQuick_MyCard" {
  708. util.ErrorF("mycard 支付签名认证:%v", info)
  709. newSign := getMd5Sign("03422134397322604272901806704074", params)
  710. if newSign != sign {
  711. util.ErrorF("签名错误%v", sign)
  712. c.String(http.StatusOK, "FAILED")
  713. return
  714. }
  715. } else {
  716. util.ErrorF("android 支付签名认证:%v", info)
  717. newSign := getMd5RuSign("80c648e7df8aaa72", params)
  718. if newSign != sign {
  719. util.ErrorF("签名错误%v", sign)
  720. c.String(http.StatusOK, "FAILED")
  721. return
  722. }
  723. }
  724. uid := c.PostForm("account")
  725. cpOrderId := c.PostForm("customorderid")
  726. orderNo := c.PostForm("orderid")
  727. payAmount := c.PostForm("money")
  728. payCurrency := c.PostForm("currency")
  729. payType := c.PostForm("paytype")
  730. usdAmount := c.PostForm("doller")
  731. ntfData := &WebNotifyData{}
  732. ntfData.CpOrderId = cpOrderId
  733. ntfData.SdkOrderId = orderNo
  734. ntfData.PayMethod = payType
  735. ntfData.PayCurrency = payCurrency
  736. ntfData.PayTime = uint64(util.GetTimeSeconds())
  737. ntfData.PayChannel = "qk_hw"
  738. util.WarnF("paycallback uid=%v cpOrderNo=%v orderNo=%v payAmount=%v payCurrency=%v payType=%v usdAmount=%v",
  739. uid, cpOrderId, orderNo, payAmount, payCurrency, payType, usdAmount)
  740. f64, err := strconv.ParseFloat(payAmount, 32)
  741. if err != nil {
  742. fmt.Println("Error:", err)
  743. return
  744. }
  745. webPayNotify(ntfData, float32(f64), c)
  746. //// 简单粗暴,直接给其他服转发,不需要确认是哪个服
  747. //payPostRouter := service.GetServiceConfig().SDKConfig.PayPostRouter
  748. //util.WarnF("paycallback payPostRouter:%v\n", payPostRouter)
  749. //// 组装转发body
  750. //params["sign"] = sign
  751. //var routerStr strings.Builder
  752. //for key, value := range params {
  753. // routerStr.WriteString(key)
  754. // routerStr.WriteString("=")
  755. // routerStr.WriteString(value)
  756. // routerStr.WriteString("&")
  757. //}
  758. //routerString := routerStr.String()
  759. //util.WarnF("paycallback routerString:%v\n", routerString)
  760. //go sendPosts(payPostRouter, routerString)
  761. c.String(http.StatusOK, "success")
  762. }
  763. func WebPayHwDn2Notify(c *gin.Context) {
  764. //util.DebugF("支付回调信息:%v", c.Request.PostForm)
  765. orderId := c.DefaultQuery("order_id", "")
  766. payAmount := c.DefaultQuery("amount", "")
  767. sign := c.DefaultQuery("sign", "")
  768. extra := c.DefaultQuery("extra", "")
  769. username := c.DefaultQuery("username", "")
  770. server := c.DefaultQuery("server", "")
  771. sandbox := c.DefaultQuery("sandbox", "")
  772. timestamp := c.DefaultQuery("timestamp", "")
  773. var extras ExtrasDn
  774. err := json.Unmarshal([]byte(extra), &extras)
  775. if err != nil {
  776. util.ErrorF("支付回调参数解析错误:%v", err)
  777. }
  778. //cpOrderId := extras.OrderNo
  779. util.ErrorF("支付回调信息东南亚2:orderId:%v,payAmount:%v,sign:%v,extra:%v,username:%v,server:%v,sandbox:%v,timestamp:%v", orderId, payAmount, sign, extra, username, server, sandbox, timestamp)
  780. if extras.Platform == "XUAN_YOU_Google_Android" {
  781. if sign != getMd5DnSign("e81c2bd2ffb7feb7f0df477dc02b0bbd", username, orderId, server, payAmount, extra, sandbox, timestamp) {
  782. c.JSON(http.StatusOK, gin.H{"status": 1, "msg": "sign error"})
  783. return
  784. }
  785. } else if extras.Platform == "XUAN_YOU_IOS" {
  786. if sign != getMd5DnSign("3f8e9fec0794443f76d3a27cd41e2711", username, orderId, server, payAmount, extra, sandbox, timestamp) {
  787. c.JSON(http.StatusOK, gin.H{"status": 1, "msg": "sign error"})
  788. return
  789. }
  790. } else {
  791. if sign != getMd5DnSign("cee1b45a9aa02a75f9d720d6b9e7b7d4", username, orderId, server, payAmount, extra, sandbox, timestamp) {
  792. c.JSON(http.StatusOK, gin.H{"status": 1, "msg": "sign error"})
  793. return
  794. }
  795. }
  796. cpOrderId := extras.OrderNo
  797. if cpOrderId != "" {
  798. //f64, err := strconv.ParseFloat(payAmount, 64)
  799. //if err != nil {
  800. // fmt.Println("Error:", err)
  801. // return
  802. //}
  803. util.WarnF("paycallbackDn2 uid=%v cpOrderNo=%v orderNo=%v payAmount=%v",
  804. extras.Uid, cpOrderId, orderId, payAmount)
  805. res := webPayNotifyDn(cpOrderId, payAmount, orderId)
  806. if res == "SUCCESS" {
  807. c.JSON(http.StatusOK, gin.H{"status": 0})
  808. } else {
  809. c.JSON(http.StatusOK, gin.H{"status": 1, "msg": "order already complete"})
  810. }
  811. } else { //走的网页支付流程游戏这边没有orderid,只发代金券礼包
  812. for _, v := range ResDnyPayInfo.GiftList {
  813. if v.Id == strconv.Itoa(int(extras.GoodsId)) {
  814. //发送对应奖励
  815. var bfInfo *WebBriefInfo
  816. service.GetMysql().Operate(func(rawClient interface{}) interface{} {
  817. wrapper := mysql.NewWrapper(rawClient.(*sql.DB))
  818. wrapper.Query("select uid,nick_name,base_level,create_date,last_login_date,ban_date,map_level,fight_power,active_code,open_id,serverid from role where open_id=?", username).Each(func(wrapper2 *mysql.Wrapper) bool {
  819. bfInfo = parseUserInfo(wrapper2)
  820. return true
  821. })
  822. if wrapper.Err != nil {
  823. util.ErrorF("uid=%v WebGmProcessUserGet err=%v", username, wrapper.Err)
  824. }
  825. return nil
  826. })
  827. if bfInfo == nil {
  828. util.ErrorF("uid=%v not found err=%v", username)
  829. c.JSON(http.StatusOK, gin.H{"status": 1, "msg": "not found user"})
  830. return
  831. }
  832. uidStr := bfInfo.Uid
  833. titleStr := "system award"
  834. contentStr := v.Desc
  835. rewardStr := v.Reward
  836. // list表示获取邮件列表
  837. // attach添加替换邮件
  838. // del删除延迟发送邮件
  839. //mailType := c.DefaultQuery("type", "")
  840. //uid
  841. var uidList []uint64
  842. uidList = append(uidList, uidStr)
  843. //reward
  844. var rewardList []*serverproto.KeyValueType
  845. rewardStrList := strings.Split(rewardStr, ",")
  846. for idx := 0; idx < len(rewardStrList); idx++ {
  847. key, val := model.Str2Res(rewardStrList[idx])
  848. if key > 0 && val > 0 {
  849. rewardList = append(rewardList, &serverproto.KeyValueType{Key: key, Value: val})
  850. }
  851. }
  852. util.ErrorF("东南亚网页支付:orderId:%v,payAmount:%v,sign:%v,extra:%v,username:%v,server:%v,sandbox:%v,timestamp:%v,award:%v", orderId, payAmount, sign, extra, username, server, sandbox, timestamp, rewardStr)
  853. gmweb.GetMailUpdateMag().AttachMail2Update(1, uidList, titleStr, contentStr, util.GetTimeMilliseconds(), rewardList)
  854. c.JSON(http.StatusOK, gin.H{"status": 0})
  855. }
  856. }
  857. }
  858. }
  859. func WebPayHwDnOpenServerNotify(c *gin.Context) {
  860. //util.DebugF("支付回调信息:%v", c.Request.PostForm)
  861. sidStr := c.DefaultQuery("sid", "")
  862. nameStr := c.DefaultQuery("name", "")
  863. timeStr := c.DefaultQuery("time", "") //2019-01-01 12:00:00
  864. gameIdStr := c.DefaultQuery("gameid", "") //2019-01-01 12:00:00
  865. signKeyStr := c.DefaultQuery("signkey", "") //2019-01-01 12:00:00
  866. if nameStr == "" || sidStr == "" || timeStr == "" || gameIdStr == "" {
  867. c.JSON(http.StatusOK, "param error:"+nameStr+sidStr+timeStr)
  868. return
  869. }
  870. reqUrl := "https://i.dze-game.com/game/center/sync_server"
  871. now := strconv.FormatInt(time.Now().Unix(), 10)
  872. // 准备表单数据
  873. formData := url.Values{}
  874. formData.Add("GAME_ID", gameIdStr)
  875. formData.Add("SID", sidStr)
  876. formData.Add("_SID", sidStr)
  877. formData.Add("NAME", nameStr)
  878. formData.Add("START_TIME", timeStr)
  879. formData.Add("sign", Md5Dn(gameIdStr, nameStr, sidStr, timeStr, sidStr, now, signKeyStr))
  880. formData.Add("timestamp", now)
  881. resp, err := http.Post(
  882. reqUrl,
  883. "application/x-www-form-urlencoded",
  884. strings.NewReader(formData.Encode()),
  885. )
  886. if err != nil {
  887. util.ErrorF("req error:%v", err)
  888. c.JSON(http.StatusOK, "req error:"+nameStr+sidStr+timeStr)
  889. return
  890. }
  891. defer resp.Body.Close()
  892. body, err := io.ReadAll(resp.Body)
  893. if err != nil {
  894. util.ErrorF("red body error:%v", err)
  895. c.JSON(http.StatusOK, "res error:"+nameStr+sidStr+timeStr)
  896. return
  897. }
  898. util.ErrorF("东南亚开服信息,sid:%v,name:%v,time:%v,response:%v", sidStr, nameStr, timeStr, string(body))
  899. c.JSON(http.StatusOK, gin.H{"status": 0})
  900. }
  901. func Md5Dn(gameId, name, sid, time, _sid, timestamp, signKey string) string {
  902. key := gameId + name + sid + time + _sid + timestamp + signKey
  903. hash := md5.Sum([]byte(key))
  904. return hex.EncodeToString(hash[:])
  905. }
  906. func WebPayHwDnNotify(c *gin.Context) {
  907. //util.DebugF("支付回调信息:%v", c.Request.PostForm)
  908. params := make(map[string]string)
  909. if err := c.Request.ParseForm(); err != nil {
  910. util.InfoF("parseForm falied")
  911. c.String(http.StatusOK, "FAILED")
  912. return
  913. }
  914. util.ErrorF("支付回调信息东南亚:%v", c.Request.PostForm)
  915. for key, value := range c.Request.PostForm {
  916. params[key] = value[0] // 假设每个参数只有一个值
  917. }
  918. cpOrderId := params["order_code"]
  919. payAmount := params["amount"]
  920. //f64, err := strconv.ParseFloat(payAmount, 32)
  921. //if err != nil {
  922. // fmt.Println("Error:", err)
  923. // return
  924. //}
  925. res := webPayNotifyDn(cpOrderId, payAmount, "")
  926. //// 简单粗暴,直接给其他服转发,不需要确认是哪个服
  927. //payPostRouter := service.GetServiceConfig().SDKConfig.PayPostRouter
  928. //util.WarnF("paycallback payPostRouter:%v\n", payPostRouter)
  929. //// 组装转发body
  930. //params["sign"] = sign
  931. //var routerStr strings.Builder
  932. //for key, value := range params {
  933. // routerStr.WriteString(key)
  934. // routerStr.WriteString("=")
  935. // routerStr.WriteString(value)
  936. // routerStr.WriteString("&")
  937. //}
  938. //routerString := routerStr.String()
  939. //util.WarnF("paycallback routerString:%v\n", routerString)
  940. //go sendPosts(payPostRouter, routerString)
  941. if res == "SUCCESS" {
  942. c.JSON(http.StatusOK, gin.H{"processingStatus": "completed"})
  943. } else {
  944. c.JSON(404, gin.H{"code": "ORDER_CODE_NOT_FOUND", "message": "order_code does not exist"})
  945. }
  946. }
  947. func sendPosts(urls []string, routerString string) {
  948. for i := 0; i < len(urls); i++ {
  949. sendPostToOtherServer(urls[i], []byte(routerString))
  950. }
  951. }
  952. // http://110.40.223.119:8002/pay/hwQucikFromS1GmWeb
  953. func WebPayHwQuickNotifyFromS1GmWeb(c *gin.Context) {
  954. params := make(map[string]string)
  955. if err := c.Request.ParseForm(); err != nil {
  956. util.InfoF("parseForm falied")
  957. c.String(http.StatusOK, "FAILED")
  958. return
  959. }
  960. for key, value := range c.Request.PostForm {
  961. params[key] = value[0] // 假设每个参数只有一个值
  962. }
  963. sign := params["sign"]
  964. newSign := getMd5Sign("03422134397322604272901806704074", params)
  965. util.ErrorF("sign:%v", sign)
  966. util.ErrorF("newSign:%v", newSign)
  967. util.ErrorF("params:%v", params)
  968. if newSign != sign {
  969. util.ErrorF("签名错误%v", sign)
  970. c.String(http.StatusOK, "FAILED")
  971. return
  972. }
  973. uid := c.PostForm("uid")
  974. cpOrderId := c.PostForm("cpOrderNo")
  975. orderNo := c.PostForm("orderNo")
  976. payAmount := c.PostForm("payAmount")
  977. payCurrency := c.PostForm("payCurrency")
  978. payType := c.PostForm("payType")
  979. usdAmount := c.PostForm("usdAmount")
  980. ntfData := &WebNotifyData{}
  981. ntfData.CpOrderId = cpOrderId
  982. ntfData.SdkOrderId = orderNo
  983. ntfData.PayMethod = payType
  984. ntfData.PayCurrency = payCurrency
  985. ntfData.PayTime = uint64(util.GetTimeSeconds())
  986. ntfData.PayChannel = "qk_hw"
  987. util.DebugF("uid=%v cpOrderNo=%v orderNo=%v payAmount=%v payCurrency=%v payType=%v usdAmount=%v",
  988. uid, cpOrderId, orderNo, payAmount, payCurrency, payType, usdAmount)
  989. f64, err := strconv.ParseFloat(usdAmount, 32)
  990. if err != nil {
  991. fmt.Println("Error:", err)
  992. return
  993. }
  994. webPayNotify(ntfData, float32(f64), c)
  995. c.JSON(http.StatusOK, "SUCCESS")
  996. }
  997. // sendPostToOtherServer 发送给其他服务器
  998. func sendPostToOtherServer(url string, body []byte) {
  999. // 创建请求
  1000. req, err := http.NewRequest("POST", url, bytes.NewReader(body))
  1001. if err != nil {
  1002. util.ErrorF("r1 NewRequest:%v \n", err.Error())
  1003. }
  1004. // 设置Header
  1005. req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
  1006. req.Header.Set("Custom-Header", "custom-value")
  1007. // 发送请求
  1008. client := &http.Client{}
  1009. resp, err := client.Do(req)
  1010. if err != nil {
  1011. util.ErrorF("r1 client.Do(req):%v \n", err.Error())
  1012. return
  1013. }
  1014. defer resp.Body.Close()
  1015. }
  1016. type KVSt struct {
  1017. ParamKey string
  1018. ParamVal string
  1019. }
  1020. func WebPayNBSDKNotify(c *gin.Context) {
  1021. tmpReq := c.Request
  1022. err := tmpReq.ParseMultipartForm(32 << 20)
  1023. if err != nil {
  1024. return
  1025. }
  1026. formCache := tmpReq.PostForm
  1027. //util.DebugF("formCache2=%v", formCache)
  1028. var kvList []*KVSt
  1029. for k, v := range formCache {
  1030. if k == "sign" {
  1031. continue
  1032. }
  1033. kv := &KVSt{
  1034. ParamKey: k,
  1035. ParamVal: v[0],
  1036. }
  1037. kvList = append(kvList, kv)
  1038. }
  1039. sort.Slice(kvList, func(i, j int) bool {
  1040. return kvList[i].ParamKey < kvList[j].ParamKey
  1041. })
  1042. //util.DebugF("kvlist=%v", kvList)
  1043. verifyStr := ""
  1044. for idx := 0; idx < len(kvList); idx++ {
  1045. key := url.QueryEscape(kvList[idx].ParamKey)
  1046. val := url.QueryEscape(kvList[idx].ParamVal)
  1047. if idx == 0 {
  1048. verifyStr += key + "=" + val
  1049. } else {
  1050. verifyStr += "&" + key + "=" + val
  1051. }
  1052. }
  1053. sign := c.PostForm("sign")
  1054. sdkOrderId := c.PostForm("sdk_order_id") //SDK订单ID
  1055. cpOrderId := c.PostForm("cp_order_id") //游戏方订单ID,由游戏客户端生成(服务器生成给到客户端)
  1056. serverId := c.PostForm("server_id") //游戏区服ID
  1057. pfUid := c.PostForm("pf_uid") //渠道平台的UID
  1058. roleId := c.PostForm("role_id") //游戏方自己的角色ID
  1059. payAmount := c.PostForm("pay_amount") //支付金额(int,单位分,CP方需要验证是否与计费点金额一致,不做此判断,后果自负哦!!!)
  1060. gameKey := service.GetServiceConfig().SDKConfig.NbGameKey
  1061. tmpHmac := hmac.New(md5.New, []byte(gameKey))
  1062. tmpHmac.Write([]byte(verifyStr))
  1063. tmpSign := hex.EncodeToString(tmpHmac.Sum([]byte("")))
  1064. util.DebugF("uid=%v verifyStr=%v cpOrderId=%v pfUid=%v sdkOrderId=%v serverId=%v tmpSign=%v sign=%v gamekey=%v", roleId, verifyStr, cpOrderId, pfUid,
  1065. sdkOrderId, serverId, tmpSign, sign, gameKey)
  1066. if tmpSign != sign {
  1067. util.InfoF("uid=%v WebPayNBSDKNotify sign verify failed cpOrderId=%v", roleId, cpOrderId)
  1068. return
  1069. }
  1070. checkPayAmount, _ := model.Str2Num(payAmount)
  1071. ntfData := &WebNotifyData{}
  1072. ntfData.CpOrderId = cpOrderId
  1073. ntfData.SdkOrderId = sdkOrderId
  1074. ntfData.PayMethod = ""
  1075. ntfData.PayCurrency = ""
  1076. ntfData.PayTime = uint64(util.GetTimeSeconds())
  1077. ntfData.PayChannel = ""
  1078. ret := webPayNotify(ntfData, float32(checkPayAmount)/100, c)
  1079. //c.JSON(http.StatusOK, `success`)
  1080. c.Data(http.StatusOK, "text/plain; charset=utf-8", []byte(ret))
  1081. }
  1082. type UniSDKPayExtraST struct {
  1083. Aid int `json:"aid"` //用户唯一标识
  1084. PrivateParam string `json:"privateparam"`
  1085. PayChannel string `json:"paychannel"` //支付渠道
  1086. AppChannel string `json:"appchannel"` //appchannel
  1087. Platform string `json:"platfrom"`
  1088. UidId string `json:"uidid"` //设备id
  1089. GoodsCount int `json:"goodscount"` //商品数量
  1090. PayMoney string `json:"paymoney"` //玩家实际支付金额
  1091. FreeMoney string `json:"freemoney"` //免费总价,供游戏服写运营日志(如果渠道不提供,该字段为0)
  1092. PayCurrency string `json:"paycurrency"` //玩家实际支付币种
  1093. Deduct int `json:"deduct"`
  1094. DeductPercent string `json:"deductpercent"`
  1095. DeductReason string `json:"deductreason"` //扣除原因,是黑设备还是黑币种
  1096. JsonData string `json:"jsondata"`
  1097. InitTime int `json:"inittime"` //订单创建时间戳,精确到秒;若订单不通过create_order接口创建(例如web 支付),则此值为0
  1098. PayTime int `json:"paytime"` //订单支付时间戳,精确到秒
  1099. IsTest int `json:"istest"` //订单来源:0,正式环境订单;1,测试环境订单(v3.6.2新增)
  1100. FreeYuanBao int `json:"free_yuanbao"`
  1101. PayYuanBao int `json:"pay_yuanbao"`
  1102. PayMethod string `json:"paymethod"`
  1103. }
  1104. type UniSDKPayST struct {
  1105. GameId string `json:"gameid"`
  1106. HostId int `json:"hostid"`
  1107. RoleId string `json:"roleid"`
  1108. GoodsId string `json:"goodsid"`
  1109. UserName string `json:"username"` //玩家渠道帐号(玩家帐号被sdk渠道转换之后的字符串)
  1110. SN string `json:"sn"` //游戏订单号
  1111. ConsumeSN string `json:"consumesn"` //渠道流水订单号(苹果渠道对应为transaction-id)
  1112. ExtraData UniSDKPayExtraST
  1113. }
  1114. type UniSDKPayResponseST struct {
  1115. Code int `json:"code"`
  1116. Msg string `json:"msg"`
  1117. Data interface{} `json:"data"`
  1118. }
  1119. func WebPayUniSDKNotify(c *gin.Context) {
  1120. sign := c.GetHeader("Gas-Ship-Signature")
  1121. payInfo := &UniSDKPayST{}
  1122. bodyData, err := c.GetRawData()
  1123. if err != nil {
  1124. util.ErrorF("WebPayUniSDKNotify body get error=%v", err)
  1125. return
  1126. }
  1127. err = json.Unmarshal(bodyData, payInfo)
  1128. if err != nil {
  1129. util.ErrorF("WebPayUniSDKNotify body Unmarshal error=%v", err)
  1130. return
  1131. }
  1132. secretKey := service.GetServiceConfig().SDKConfig.UniSecretKey
  1133. tmpHmac := hmac.New(md5.New, []byte(secretKey))
  1134. tmpHmac.Write(bodyData)
  1135. tmpSign := hex.EncodeToString(tmpHmac.Sum([]byte("")))
  1136. if tmpSign != sign {
  1137. util.InfoF("uid=%v WebPayUniSDKNotify sign verify failed cpOrderId=%v", payInfo.RoleId, payInfo.SN)
  1138. c.Header("Gas-Ship-Signature", tmpSign)
  1139. responseSt := &UniSDKPayResponseST{
  1140. Code: 403,
  1141. Msg: "ok",
  1142. Data: nil,
  1143. }
  1144. c.JSON(http.StatusOK, responseSt)
  1145. return
  1146. }
  1147. checkPayAmount, _ := model.Str2Num(payInfo.ExtraData.PayMoney)
  1148. ntfData := &WebNotifyData{}
  1149. ntfData.CpOrderId = payInfo.SN
  1150. ntfData.SdkOrderId = payInfo.ConsumeSN
  1151. ntfData.PayMethod = payInfo.ExtraData.PayMethod
  1152. ntfData.PayCurrency = payInfo.ExtraData.PayCurrency
  1153. ntfData.PayTime = uint64(payInfo.ExtraData.PayTime)
  1154. ntfData.PayChannel = payInfo.ExtraData.PayChannel
  1155. ret := webPayNotify(ntfData, float32(checkPayAmount)/100, c)
  1156. if ret == "FAILED" {
  1157. c.JSON(http.StatusOK, "FAILED")
  1158. }
  1159. c.Header("Gas-Ship-Signature", tmpSign)
  1160. responseSt := &UniSDKPayResponseST{
  1161. Code: 200,
  1162. Msg: "ok",
  1163. Data: nil,
  1164. }
  1165. c.JSON(http.StatusOK, responseSt)
  1166. }
  1167. func WebPayNBH5Notify(c *gin.Context) {
  1168. sdkOrderId := c.PostForm("sdk_order_id") //SDK订单ID
  1169. cpOrderId := c.PostForm("cp_order_id") //游戏方订单ID,由游戏客户端生成(服务器生成给到客户端)
  1170. serverId := c.PostForm("server_id") //游戏区服ID
  1171. pfUid := c.PostForm("pf_uid") //渠道平台的UID
  1172. roleId := c.PostForm("role_id") //游戏方自己的角色ID(uid)
  1173. payAmount := c.PostForm("pay_amount") //支付金额(int,单位分,CP方需要验证是否与计费点金额一致,不做此判断,后果自负哦!!!)
  1174. goodsType := c.PostForm("goods_type")
  1175. goodsID := c.PostForm("goods_id")
  1176. util.InfoF("WebPayH5Notify roleId=%v pfUid=%v sdkOrderId=%v serverId=%v", roleId, pfUid, sdkOrderId, serverId)
  1177. if cpOrderId == "" {
  1178. cpOrderId = "WebPayH5Notify"
  1179. }
  1180. gameRoleId, _ := model.Str2NumU64(roleId)
  1181. checkPayAmount, _ := model.Str2Num(payAmount)
  1182. if gameRoleId <= 0 || checkPayAmount <= 0 {
  1183. c.Data(http.StatusOK, "text/plain; charset=utf-8", []byte("FAILED"))
  1184. return
  1185. }
  1186. ntfData := &WebNotifyData{}
  1187. ntfData.GameRoleId = gameRoleId
  1188. ntfData.CpOrderId = cpOrderId
  1189. ntfData.SdkOrderId = sdkOrderId
  1190. ntfData.PayMethod = ""
  1191. ntfData.PayCurrency = ""
  1192. ntfData.PayTime = uint64(util.GetTimeSeconds())
  1193. ntfData.PayChannel = "WebPayH5Notify"
  1194. ntfData.GoodsType, _ = model.Str2NumU64(goodsType)
  1195. ntfData.GoodsID, _ = model.Str2NumU64(goodsID)
  1196. ret := webPayNotifyH5(ntfData, float32(checkPayAmount)/100, c)
  1197. c.Data(http.StatusOK, "text/plain; charset=utf-8", []byte(ret))
  1198. }
  1199. type WebNotifyData struct {
  1200. CpOrderId string
  1201. SdkOrderId string
  1202. PayMethod string
  1203. PayCurrency string
  1204. PayTime uint64
  1205. PayChannel string
  1206. GameRoleId uint64
  1207. GoodsType uint64
  1208. GoodsID uint64
  1209. Guid string
  1210. RoleName string
  1211. }
  1212. func webPayNotify(webNtf *WebNotifyData, payAmount float32, c *gin.Context) string {
  1213. //流程处理gmweb保存订单状态到redis中设置为 成功充值状态
  1214. //发送给gameserver,成功收到后设置订单状态为成功获取充值状态,如果gameserver没有收到
  1215. //每次玩家上线时,重新获取一次订单状态如果是成功充值,但是没有获取成功就获取一次
  1216. // 充值成功获取对应的ntdata数据
  1217. // 1,回复成/失败消息给quick
  1218. // 2,订单状态写入redis(判重处理),并发送给social做获取奖励处理
  1219. msgStr, err := service.GetRedis().HGet(model.PayOrderPrefix, webNtf.CpOrderId).Result()
  1220. if err != nil {
  1221. //util.ErrorF("WebPayQuickNotify order not exist err=%v", err)
  1222. util.ErrorF("WebPayQuickNotify order not exist err=%v, cpOrderId=%v, sdkOrderId=%v", err, webNtf.CpOrderId, webNtf.SdkOrderId)
  1223. //c.JSON(http.StatusOK, "FAILED")
  1224. //return "FAILED"
  1225. return "failed:game_orderid error"
  1226. }
  1227. payInfo := &serverproto.PayOrderSaveInfo{}
  1228. err = model.GetDecodeMessage(payInfo, msgStr)
  1229. if err != nil {
  1230. util.ErrorF("WebPayQuickNotify GetDecodeMessage err=%, cpOrderId=%v, sdkOrderId=%v", err, webNtf.CpOrderId, webNtf.SdkOrderId)
  1231. //util.ErrorF("WebPayQuickNotify GetDecodeMessage err=%v", err)
  1232. //c.JSON(http.StatusOK, "FAILED")
  1233. //return "FAILED"
  1234. return fmt.Sprintf("FAILED,cpOrderId=%v err=%v", webNtf.CpOrderId, err)
  1235. }
  1236. if payInfo.OrderState == int32(serverproto.PayOrderState_EPayOrderState_Gen) {
  1237. if payInfo.PayChannel != webNtf.Guid && payInfo.PayChannel != "xiaoqi" {
  1238. util.ErrorF("WebPayQuickNotify order channel error order=%v, webNtf=%v", payInfo, webNtf)
  1239. return "failed:guid error"
  1240. }
  1241. if payInfo.Uid != webNtf.GameRoleId {
  1242. util.ErrorF("WebPayQuickNotify order uid error order=%v, webNtf=%v", payInfo, webNtf)
  1243. return "failed:game_role_id error"
  1244. }
  1245. if payInfo.PayCurrency != webNtf.RoleName {
  1246. util.ErrorF("WebPayQuickNotify order role name error order=%v, webNtf=%v", payInfo, webNtf)
  1247. return "failed:game_role_name error"
  1248. }
  1249. //实际支付 == 订单的钱,否则为支付失败
  1250. //payAmount := int32(payAmount * 100) //该渠道是以分为单位(游戏以卢布为单位)
  1251. //服务器订单实际金额:
  1252. //orderAmount := int32(payInfo.Amount * 1000)
  1253. if payAmount == payInfo.Amount {
  1254. payInfo.OrderState = int32(serverproto.PayOrderState_EPayOrderState_PayOk)
  1255. } else {
  1256. payInfo.OrderState = int32(serverproto.PayOrderState_EPayOrderState_PayFailed)
  1257. util.ErrorF("uid=%v WebPayQuickNotify failed payAmount:%v order=%v", payInfo.Uid, payAmount, payInfo)
  1258. return "failed:pay_price error"
  1259. }
  1260. payInfo.OrderProcessTime = util.GetTimeMilliseconds()
  1261. payInfo.SdkOrderId = webNtf.SdkOrderId //sdk订单id\
  1262. payInfo.PayMethod = webNtf.PayMethod
  1263. payInfo.PayCurrency = webNtf.RoleName
  1264. payInfo.PayTime = webNtf.PayTime
  1265. payInfo.PayChannel = webNtf.PayChannel
  1266. //订单状态修改,写入数据库(后续玩家发货成功后会再次修改订单状态为PayOrderState_EPayOrderState_PayOkReward)
  1267. err, newPayInfoStr := model.GetEncodeMessage(payInfo)
  1268. if err == nil {
  1269. service.GetRedis().HSet(model.PayOrderPrefix, webNtf.CpOrderId, newPayInfoStr)
  1270. }
  1271. //完成订单id列表(避免上次发货不成功,玩家下次登陆时可以重新获取一次奖励)
  1272. uidStr := strconv.FormatUint(payInfo.Uid, 10)
  1273. okListKeyStr := model.PayOrderOKIdListPrefix + uidStr
  1274. service.GetRedis().SAdd(okListKeyStr, payInfo.CpOrderId)
  1275. if payInfo.OrderState == int32(serverproto.PayOrderState_EPayOrderState_PayOk) {
  1276. ssNtfMsg := &serverproto.SSPayInfoOrderNtf{
  1277. PayOrderInfo: payInfo,
  1278. }
  1279. selfmodel.SendSocial(ssNtfMsg)
  1280. }
  1281. util.InfoF("uid=%v WebPayQuickNotify ok order=%v", payInfo.Uid, payInfo)
  1282. } else {
  1283. util.ErrorF("WebPayQuickNotify uid=%v state error state=%v", payInfo.Uid, payInfo.OrderState)
  1284. //return "FAILED"
  1285. if payInfo.SdkOrderId == webNtf.SdkOrderId {
  1286. return "SUCCESS"
  1287. } else {
  1288. util.ErrorF("WebPayQuickNotify uid=%v order is completed but sdkOrderId not same order=%v,sdkOrderId=%v", payInfo.Uid, payInfo, webNtf.SdkOrderId)
  1289. return "failed:xiao7_goid error"
  1290. }
  1291. }
  1292. return "SUCCESS"
  1293. }
  1294. func webPayNotifyDn(cpOrderId string, Amount, sdkOrderId string) string {
  1295. //流程处理gmweb保存订单状态到redis中设置为 成功充值状态
  1296. //发送给gameserver,成功收到后设置订单状态为成功获取充值状态,如果gameserver没有收到
  1297. //每次玩家上线时,重新获取一次订单状态如果是成功充值,但是没有获取成功就获取一次
  1298. // 充值成功获取对应的ntdata数据
  1299. // 1,回复成/失败消息给quick
  1300. // 2,订单状态写入redis(判重处理),并发送给social做获取奖励处理
  1301. msgStr, err := service.GetRedis().HGet(model.PayOrderPrefix, cpOrderId).Result()
  1302. if err != nil {
  1303. //util.ErrorF("WebPayQuickNotify order not exist err=%v", err)
  1304. util.ErrorF("WebPayQuickNotify order not exist err=%v, cpOrderId=%v, sdkOrderId=%v", err, cpOrderId, 0)
  1305. //c.JSON(http.StatusOK, "FAILED")
  1306. //return "FAILED"
  1307. return fmt.Sprintf("FAILED,cpOrderId=%v err=%v", cpOrderId, err)
  1308. }
  1309. payInfo := &serverproto.PayOrderSaveInfo{}
  1310. err = model.GetDecodeMessage(payInfo, msgStr)
  1311. if err != nil {
  1312. util.ErrorF("WebPayQuickNotify GetDecodeMessage err=%, cpOrderId=%v, sdkOrderId=%v", err, cpOrderId, 0)
  1313. //util.ErrorF("WebPayQuickNotify GetDecodeMessage err=%v", err)
  1314. //c.JSON(http.StatusOK, "FAILED")
  1315. //return "FAILED"
  1316. return fmt.Sprintf("FAILED,cpOrderId=%v err=%v", cpOrderId, err)
  1317. }
  1318. if payInfo.OrderState == int32(serverproto.PayOrderState_EPayOrderState_Gen) {
  1319. //实际支付 == 订单的钱,否则为支付失败
  1320. //payAmount := int32(Amount * 1000)
  1321. ////服务器订单实际金额:
  1322. orderAmount := fmt.Sprintf("%.2f", payInfo.Amount)
  1323. if Amount == orderAmount {
  1324. payInfo.OrderState = int32(serverproto.PayOrderState_EPayOrderState_PayOk)
  1325. } else {
  1326. payInfo.OrderState = int32(serverproto.PayOrderState_EPayOrderState_PayFailed)
  1327. util.ErrorF("uid=%v WebPayQuickNotify failed payAmount:%v order=%v ,price=%v", payInfo.Uid, Amount, payInfo, orderAmount)
  1328. return ""
  1329. }
  1330. //payInfo.OrderState = int32(serverproto.PayOrderState_EPayOrderState_PayOk)
  1331. payInfo.OrderProcessTime = util.GetTimeMilliseconds()
  1332. payInfo.SdkOrderId = sdkOrderId //sdk订单id\
  1333. //payInfo.PayMethod = webNtf.PayMethod
  1334. //payInfo.PayCurrency = webNtf.PayCurrency
  1335. payInfo.PayTime = util.GetTimeMilliseconds()
  1336. payInfo.PayChannel = "dn"
  1337. //订单状态修改,写入数据库(后续玩家发货成功后会再次修改订单状态为PayOrderState_EPayOrderState_PayOkReward)
  1338. err, newPayInfoStr := model.GetEncodeMessage(payInfo)
  1339. if err == nil {
  1340. service.GetRedis().HSet(model.PayOrderPrefix, cpOrderId, newPayInfoStr)
  1341. }
  1342. //完成订单id列表(避免上次发货不成功,玩家下次登陆时可以重新获取一次奖励)
  1343. uidStr := strconv.FormatUint(payInfo.Uid, 10)
  1344. okListKeyStr := model.PayOrderOKIdListPrefix + uidStr
  1345. service.GetRedis().SAdd(okListKeyStr, payInfo.CpOrderId)
  1346. if payInfo.OrderState == int32(serverproto.PayOrderState_EPayOrderState_PayOk) {
  1347. ssNtfMsg := &serverproto.SSPayInfoOrderNtf{
  1348. PayOrderInfo: payInfo,
  1349. }
  1350. selfmodel.SendSocial(ssNtfMsg)
  1351. }
  1352. util.InfoF("uid=%v WebPayQuickNotify ok order=%v", payInfo.Uid, payInfo)
  1353. } else {
  1354. util.ErrorF("WebPayQuickNotify uid=%v state error state=%v", payInfo.Uid, payInfo.OrderState)
  1355. //return "FAILED"
  1356. return fmt.Sprintf("FAILED,cpOrderId=%v state error=%v", cpOrderId, payInfo.OrderState)
  1357. }
  1358. return "SUCCESS"
  1359. }
  1360. // 外层发起主动充值(不走游戏流程)
  1361. func webPayNotifyH5(webNtf *WebNotifyData, payAmount float32, c *gin.Context) string {
  1362. payInfo := &serverproto.PayOrderSaveInfo{}
  1363. payInfo.Uid = webNtf.GameRoleId
  1364. payInfo.Amount = payAmount
  1365. payInfo.OrderProcessTime = util.GetTimeMilliseconds()
  1366. payInfo.SdkOrderId = webNtf.SdkOrderId //sdk订单id\
  1367. payInfo.PayMethod = webNtf.PayMethod
  1368. payInfo.PayCurrency = webNtf.PayCurrency
  1369. payInfo.PayTime = webNtf.PayTime
  1370. payInfo.PayChannel = webNtf.PayChannel
  1371. payInfo.GoodsType = int32(webNtf.GoodsType)
  1372. payInfo.GoodsId = int32(webNtf.GoodsID)
  1373. rewardStr := c.DefaultQuery("reward", "")
  1374. //reward
  1375. rewardStrList := strings.Split(rewardStr, ",")
  1376. for idx := 0; idx < len(rewardStrList); idx++ {
  1377. key, val := model.Str2Res(rewardStrList[idx])
  1378. if key > 0 && val > 0 {
  1379. payInfo.RewardList = append(payInfo.RewardList, &serverproto.KeyValueType{Key: key, Value: val})
  1380. }
  1381. }
  1382. payInfo.OrderState = int32(serverproto.PayOrderState_EPayOrderState_PayOk)
  1383. //订单状态修改,写入数据库(后续玩家发货成功后会再次修改订单状态为PayOrderState_EPayOrderState_PayOkReward)
  1384. err, newPayInfoStr := model.GetEncodeMessage(payInfo)
  1385. if err == nil {
  1386. service.GetRedis().HSet(model.PayOrderPrefix, webNtf.CpOrderId, newPayInfoStr)
  1387. }
  1388. //完成订单id列表(避免上次发货不成功,玩家下次登陆时可以重新获取一次奖励)
  1389. uidStr := strconv.FormatUint(payInfo.Uid, 10)
  1390. okListKeyStr := model.PayOrderOKIdListPrefix + uidStr
  1391. service.GetRedis().SAdd(okListKeyStr, payInfo.CpOrderId)
  1392. util.InfoF("webPayNotifyH5: %v", payInfo)
  1393. ssNtfMsg := &serverproto.SSPayInfoOrderNtf{
  1394. PayOrderInfo: payInfo,
  1395. }
  1396. selfmodel.SendSocial(ssNtfMsg)
  1397. return "SUCCESS"
  1398. }