pay.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. package opay
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "io"
  6. "math"
  7. "net/http"
  8. "strings"
  9. "bet24.com/log"
  10. "bet24.com/public"
  11. "bet24.com/servers/payment/config"
  12. "bet24.com/servers/payment/db"
  13. "bet24.com/servers/payment/shop"
  14. "github.com/gin-gonic/gin"
  15. coreClient "bet24.com/servers/coreservice/client"
  16. )
  17. // 下单
  18. func PayOrder(c *gin.Context) {
  19. obj := db.NewOrder(db.SP_OPay_ORDER)
  20. if err := c.ShouldBind(&obj.In); err != nil {
  21. log.Debug("%s query params err %v", "oPay.PayOrder", err)
  22. c.String(http.StatusOK, "")
  23. return
  24. }
  25. obj.In.IpAddress = strings.Split(c.Request.RemoteAddr, ":")[0]
  26. //// 币种为空,根据ip获取
  27. //if obj.In.Currency == "" {
  28. // currency := shop.GetCurrencyRateByIp(obj.In.UserID, obj.In.IpAddress)
  29. // obj.In.Currency = currency
  30. //}
  31. // 获取产品信息
  32. item := shop.GetProduct(obj.In.ProductID)
  33. if item == nil {
  34. log.Error("%s query GetProduct productId=%s currency=%s is nil", "opay.PayOrder", obj.In.ProductID, obj.In.Currency)
  35. c.String(http.StatusOK, "")
  36. return
  37. }
  38. //// 获取当前汇率信息
  39. //info := shop.GetExchangeRate(obj.In.Currency)
  40. //if info == nil {
  41. // log.Error("%s query GetExchangeRate obj.In.Currency=%s is nil", "opay.PayOrder", obj.In.Currency)
  42. // c.String(http.StatusOK, "")
  43. // return
  44. //}
  45. //
  46. //// 计算价格
  47. //calPrice := info.Rate * item.Price
  48. //
  49. //// 检查价格是否篡改
  50. //if calPrice != obj.In.Price {
  51. // log.Error("%s obj.In.Price=%v info.Rate=%v calPrice=%v is invalid", "opay.PayOrder", obj.In.Price, info.Rate, calPrice)
  52. // c.String(http.StatusOK, "")
  53. // return
  54. //}
  55. // 检查价格是否篡改
  56. if item.Price != obj.In.Price {
  57. log.Error("%s obj.In.Price=%v calPrice=%v is invalid", "opay.PayOrder", obj.In.Price, item.Price)
  58. c.String(http.StatusOK, "")
  59. return
  60. }
  61. obj.DoAction(nil)
  62. if obj.Out.OrderID == "" {
  63. log.Debug("%s GenOrder fail obj.In=%+v", "oPay.PayOrder", obj.In)
  64. c.String(http.StatusOK, "")
  65. return
  66. }
  67. var productList []productInfo
  68. productList = append(productList, productInfo{
  69. ProductId: obj.In.ProductID,
  70. Name: obj.In.ProductID,
  71. Description: obj.In.ProductID,
  72. Price: int(math.Ceil(obj.In.Price)),
  73. Quantity: 1,
  74. })
  75. price := int(obj.In.Price)
  76. // 请求payOrder的代码
  77. req := pay_req{
  78. Reference: obj.Out.OrderID,
  79. Country: obj.In.Country,
  80. Amount: amountData{
  81. Total: price,
  82. Currency: obj.In.Currency,
  83. },
  84. CallbackUrl: config.Server.OPay.Url_pay_Notify,
  85. ReturnUrl: config.Server.OPay.Url_pay_Return,
  86. ProductList: productList,
  87. }
  88. // 生成签名
  89. checkContent, err := json.Marshal(req)
  90. if err != nil {
  91. log.Error("oPay.PayOrder json marshal fail %v", err)
  92. return
  93. }
  94. // sign := public.HmacSHA512(config.Server.OPay.PublicKey, string(checkContent))
  95. // log.Debug("oPay.payOrder checkContent=%s sign=%s", string(checkContent), sign)
  96. headers := make(map[string]string)
  97. headers["Authorization"] = fmt.Sprintf("Bearer " + config.Server.OPay.PublicKey)
  98. headers["MerchantId"] = config.Server.OPay.MerchantId
  99. // POST请求
  100. respBody := httpPostByJson(config.Server.OPay.Url_pay_order, string(checkContent), headers)
  101. log.Debug("oPay.payOrder req ==> %+v resp ==> %+v", req, respBody)
  102. var resp pay_resp
  103. if err := json.Unmarshal([]byte(respBody), &resp); err != nil {
  104. log.Error("oPay.payOrder json unmarshal req ==> %+v resp ==> %+v fail %v", req, respBody, err)
  105. return
  106. }
  107. log.Debug("oPay.payOrder resp ==> %+v", resp)
  108. // 返回码,’APPLY_SUCCESS’代表成功
  109. if resp.Data.Status == "FAIL" || resp.Data.Status == "CLOSE" {
  110. log.Error("oPay.payOrder post return resp fail ==> %+v", resp)
  111. return
  112. }
  113. // 跳转到支付页面,以便持卡人完成支付过程
  114. c.Redirect(http.StatusMovedPermanently, resp.Data.CashierUrl)
  115. // c.String(http.StatusOK, "Success")
  116. return
  117. }
  118. // 回调通知
  119. func PayNotify(c *gin.Context) {
  120. bodyData, _ := io.ReadAll(c.Request.Body)
  121. log.Debug("oPay.PayNotify ==> ctx.Request.body: %v", string(bodyData))
  122. var resp payNotify
  123. if err := json.Unmarshal(bodyData, &resp); err != nil {
  124. log.Debug("%s query params err %v", "oPay.PayNotify", err)
  125. c.String(http.StatusOK, "")
  126. return
  127. }
  128. // log.Debug("oPay.PayNotify resp ==> %+v", resp)
  129. // 生成签名
  130. sign := genNotifySign(resp, config.Server.OPay.SecretKey)
  131. // 验证签名
  132. if resp.Sha512 != sign {
  133. log.Error("oPay.PayNotify 签名失败 sign=%s ==> %+v", sign, resp)
  134. return
  135. }
  136. log.Debug("oPay.PayNotify 签名成功")
  137. // 返回码,’APPLY_SUCCESS’代表成功
  138. if resp.Payload.Status != "SUCCESS" {
  139. log.Error("oPay.PayNotify resp ==> %+v 失败", resp)
  140. c.JSON(http.StatusOK, ret{Code: "SUCCESS", Msg: "Success"})
  141. return
  142. }
  143. // 数据库操作
  144. obj := db.NewNotify(db.SP_OPay_NOTIFY)
  145. obj.In.OrderID = resp.Payload.Reference
  146. obj.In.TradeID = resp.Payload.TransactionId
  147. obj.In.Price = 0
  148. obj.DoAction(nil)
  149. // 操作成功,给道具
  150. if obj.Out.RetCode == 1 {
  151. // 充值
  152. resp := coreClient.Recharge(obj.Out.UserID, obj.Out.ProductID)
  153. log.Debug("%s 充值成功 %+v", "oPay.PayNotify", resp)
  154. }
  155. c.JSON(http.StatusOK, ret{Code: "SUCCESS", Msg: "Success"})
  156. return
  157. }
  158. // 生成签名
  159. func genNotifySign(resp payNotify, privateKey string) string {
  160. checkContent := "{Amount:\"%s\",Currency:\"%s\",Reference:\"%s\",Refunded:%s,Status:\"%s\",Timestamp:\"%s\",Token:\"%s\",TransactionID:\"%s\"}"
  161. refunded := "f"
  162. if resp.Payload.Refunded {
  163. refunded = "t"
  164. }
  165. signContent := fmt.Sprintf(checkContent,
  166. resp.Payload.Amount,
  167. resp.Payload.Currency,
  168. resp.Payload.Reference,
  169. refunded,
  170. resp.Payload.Status,
  171. resp.Payload.Timestamp,
  172. resp.Payload.Token,
  173. resp.Payload.TransactionId)
  174. // 生成签名
  175. sign := public.Hmac_SHA3_SHA512(privateKey, signContent)
  176. log.Debug("oPay.PayNotify 程序加密 resp=%+v signContent=%s sign=%s", resp, signContent, sign)
  177. return sign
  178. }
  179. // 支付完成跳转处理
  180. func PayCallback(c *gin.Context) {
  181. bodyData, _ := io.ReadAll(c.Request.Body)
  182. log.Debug("oPay.PayCallback ==> ctx.Request.body: %v", string(bodyData))
  183. c.String(http.StatusOK, "success")
  184. }