pay.go 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. package flash
  2. import (
  3. "encoding/base64"
  4. "encoding/json"
  5. "fmt"
  6. "io"
  7. "net/http"
  8. "net/url"
  9. "strconv"
  10. "strings"
  11. "bet24.com/servers/payment/shop"
  12. "bet24.com/log"
  13. "bet24.com/public"
  14. "bet24.com/servers/payment/config"
  15. "bet24.com/servers/payment/db"
  16. "github.com/gin-gonic/gin"
  17. )
  18. // 下单
  19. func PayOrder(c *gin.Context) {
  20. obj := db.NewOrder(db.SP_Flash_ORDER)
  21. if err := c.ShouldBind(&obj.In); err != nil {
  22. log.Debug("%s query params err %v", "flash.PayOrder", err)
  23. c.String(http.StatusOK, "")
  24. return
  25. }
  26. obj.In.IpAddress = strings.Split(c.Request.RemoteAddr, ":")[0]
  27. //// 币种为空,根据ip获取
  28. //if obj.In.Currency == "" {
  29. // currency := shop.GetCurrencyRateByIp(obj.In.UserID, obj.In.IpAddress)
  30. // obj.In.Currency = currency
  31. //}
  32. // 获取产品信息
  33. item := shop.GetProduct(obj.In.ProductID)
  34. if item == nil {
  35. log.Error("%s query GetProduct productId=%s currency=%s is nil", "flash.PayOrder", obj.In.ProductID, obj.In.Currency)
  36. c.String(http.StatusOK, "")
  37. return
  38. }
  39. //// 获取当前汇率信息
  40. //info := shop.GetExchangeRate(obj.In.Currency)
  41. //if info == nil {
  42. // log.Error("%s query GetExchangeRate obj.In.Currency=%s is nil", "flash.PayOrder", obj.In.Currency)
  43. // c.String(http.StatusOK, "")
  44. // return
  45. //}
  46. //
  47. //// 计算价格
  48. //calPrice := info.Rate * item.Price
  49. //
  50. //// 检查价格是否篡改
  51. //if calPrice != obj.In.Price {
  52. // log.Error("%s obj.In.Price=%v info.Rate=%v calPrice=%v is invalid", "flash.PayOrder", obj.In.Price, info.Rate, calPrice)
  53. // c.String(http.StatusOK, "")
  54. // return
  55. //}
  56. // 检查价格是否篡改
  57. if item.Price != obj.In.Price {
  58. log.Error("%s obj.In.Price=%v calPrice=%v is invalid", "flash.PayOrder", obj.In.Price, item.Price)
  59. c.String(http.StatusOK, "")
  60. return
  61. }
  62. obj.DoAction(nil)
  63. if obj.Out.OrderID == "" {
  64. log.Debug("%s GenOrder fail obj.In=%+v", "flash.PayOrder", obj.In)
  65. c.String(http.StatusOK, "")
  66. return
  67. }
  68. // 请求payOrder的代码
  69. req := pay_req{
  70. MerchantNo: config.Server.FlashPay.MerchantCode,
  71. MerchantOrderNo: obj.Out.OrderID,
  72. PayAmount: obj.In.Price,
  73. Mobile: obj.In.Tel,
  74. Name: obj.In.Name,
  75. Method: "CHECKOUT",
  76. // ExpiryPeriod: "",
  77. Email: obj.In.Email,
  78. NotifyUrl: config.Server.FlashPay.Url_pay_notify,
  79. // ClientNo: "",
  80. Description: obj.In.ProductID,
  81. }
  82. payAmount := strconv.FormatFloat(req.PayAmount, 'f', -1, 64)
  83. params := url.Values{}
  84. params.Set("merchantNo", req.MerchantNo)
  85. params.Set("merchantOrderNo", req.MerchantOrderNo)
  86. params.Set("payAmount", payAmount)
  87. params.Set("mobile", req.Mobile)
  88. params.Set("name", req.Name)
  89. params.Set("method", req.Method)
  90. params.Set("notifyUrl", req.NotifyUrl)
  91. params.Set("description", req.Description)
  92. // 生成签名
  93. checkContent := createEncryptStr(params)
  94. log.Debug("order.checkContent ==> %s", checkContent)
  95. // 商户请求我们接口时使用商户私钥对请求参数 进行加密
  96. mchPriKey := fmt.Sprintf(`-----BEGIN PRIVATE KEY-----
  97. %s
  98. -----END PRIVATE KEY-----
  99. `, config.Server.FlashPay.MCH_PRIVATE_KEY)
  100. if err := public.RSA.SetPrivateKey(mchPriKey); err != nil {
  101. log.Error("flash.payOrder set private key :%v ==> %+v", err, params)
  102. return
  103. }
  104. // 私钥加密
  105. prienctypt, err := public.RSA.PriKeyENCTYPT([]byte(checkContent))
  106. if err != nil {
  107. log.Error("flash.payOrder RSA.PriKeyENCTYPT err %v", err)
  108. return
  109. }
  110. req.Sign = base64.StdEncoding.EncodeToString(prienctypt)
  111. log.Debug("flash.payOrder req ==> %+v ", params)
  112. // POST请求
  113. buf, _ := json.Marshal(req)
  114. respBody := public.HttpPostByJson(config.Server.FlashPay.Url_pay_order, string(buf))
  115. log.Debug("flash.payOrder req ==> %+v resp ==> %+v", params, respBody)
  116. var resp pay_resp
  117. if err := json.Unmarshal([]byte(respBody), &resp); err != nil {
  118. log.Error("flash.payOrder json unmarshal req ==> %+v resp ==> %+v fail %v", params, respBody, err)
  119. return
  120. }
  121. log.Debug("flash.payOrder resp ==> %+v", resp)
  122. // 请求响应码
  123. if resp.Status != "200" {
  124. log.Error("flash.payOrder post return resp fail ==> %+v", resp)
  125. return
  126. }
  127. // ARRIVED,SUCCESS,CLEARED都可以认为是收款成功
  128. if resp.Data.OrderStatus != PAY_STATUS_ARRIVED &&
  129. resp.Data.OrderStatus != PAY_STATUS_SUCCESS &&
  130. resp.Data.OrderStatus != PAY_STATUS_CLEARED {
  131. log.Error("flash.payOrder post return resp fail ==> %+v", resp)
  132. return
  133. }
  134. // 跳转到支付页面,以便持卡人完成支付过程
  135. c.Redirect(http.StatusMovedPermanently, resp.Data.PaymentUrl)
  136. // c.String(http.StatusOK, "Success")
  137. return
  138. }
  139. // 回调通知
  140. func PayNotify(c *gin.Context) {
  141. bodyData, _ := io.ReadAll(c.Request.Body)
  142. log.Debug("flash.PayNotify ==> ctx.Request.body: %v", string(bodyData))
  143. var resp payNotify
  144. err := json.Unmarshal(bodyData, &resp)
  145. if err != nil {
  146. log.Debug("%s query params err %v", "flash.PayNotify", err)
  147. c.String(http.StatusOK, "")
  148. return
  149. }
  150. log.Debug("flash.PayNotify resp ==> %+v", resp)
  151. params := url.Values{}
  152. params.Set("amount", resp.Amount)
  153. params.Set("factAmount", resp.FactAmount)
  154. params.Set("merchantOrderNo", resp.MerchantOrderNo)
  155. params.Set("platOrderNo", resp.PlatOrderNo)
  156. params.Set("orderStatus", resp.OrderStatus)
  157. params.Set("orderMessage", resp.OrderMessage)
  158. // 生成签名
  159. checkContent := createEncryptStr(params)
  160. // log.Debug("flash.PayNotify checkContent ==> %s", checkContent)
  161. // 商户使用 商户后台显示的平台公钥 进行解密
  162. platPubKey := fmt.Sprintf(`-----BEGIN PUBLIC KEY-----
  163. %s
  164. -----END PUBLIC KEY-----
  165. `, config.Server.FlashPay.PLAT_PUBLIC_KEY)
  166. if err := public.RSA.SetPublicKey(platPubKey); err != nil {
  167. log.Error("flash.PayNotify set public key :%v ==> %+v", err, params)
  168. return
  169. }
  170. data, err := base64.RawURLEncoding.DecodeString(resp.Sign)
  171. if err != nil {
  172. log.Error("flash.PayNotify base64.StdEncoding.DecodeString err %v", err)
  173. return
  174. }
  175. // 公钥解密
  176. pubdecrypt, err := public.RSA.PubKeyDECRYPT(data)
  177. if err != nil {
  178. log.Error("flash.PayNotify RSA.PubKeyDECRYPT err %v", err)
  179. return
  180. }
  181. if checkContent != string(pubdecrypt) {
  182. log.Error("flash.PayNotify 签名失败 ==> %+v", resp)
  183. return
  184. }
  185. log.Debug("flash.PayNotify 签名成功")
  186. // ARRIVED,SUCCESS,CLEARED都可以认为是收款成功
  187. if resp.OrderStatus != PAY_STATUS_ARRIVED &&
  188. resp.OrderStatus != PAY_STATUS_SUCCESS &&
  189. resp.OrderStatus != PAY_STATUS_CLEARED {
  190. log.Error("flash.PayNotify resp ==> %+v 失败", resp)
  191. return
  192. }
  193. //faceAmount, _ := strconv.Atoi(resp.FactAmount)
  194. // 数据库操作
  195. obj := db.NewNotify(db.SP_Flash_NOTIFY)
  196. obj.In.OrderID = resp.MerchantOrderNo
  197. obj.In.TradeID = resp.PlatOrderNo
  198. //obj.In.Price = faceAmount
  199. obj.DoAction(nil)
  200. // 操作成功,给道具
  201. // if obj.Out.RetCode == 1 {
  202. // // 充值
  203. // resp := coreClient.Recharge(obj.Out.UserID, obj.Out.ProductID)
  204. // log.Debug("%s 充值成功 %+v", "flash.PayNotify", resp)
  205. // }
  206. c.String(http.StatusOK, "success")
  207. return
  208. }