pay.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. package pay
  2. import (
  3. "bytes"
  4. "crypto/md5"
  5. "encoding/hex"
  6. "encoding/json"
  7. "fmt"
  8. "net/url"
  9. "strconv"
  10. "time"
  11. "github.com/pkg/errors"
  12. "go-common/library/log"
  13. )
  14. // Pay is.
  15. type Pay struct {
  16. ID string
  17. Token string
  18. RechargeShellNotifyURL string
  19. }
  20. // TraceID .
  21. func (p *Pay) TraceID() string {
  22. return strconv.FormatInt(time.Now().UnixNano(), 10)
  23. }
  24. // RechargeShellReq .
  25. type RechargeShellReq struct {
  26. CustomerID string `json:"customerId"`
  27. ProductName string `json:"productName"`
  28. Rate string `json:"rate"`
  29. NotifyURL string `json:"notifyUrl"`
  30. Timestamp int64 `json:"timestamp"`
  31. SignType string `json:"signType"`
  32. Sign string `json:"sign"`
  33. Data []RechargeShellData `json:"data"`
  34. }
  35. // RechargeShellData .
  36. type RechargeShellData struct {
  37. ThirdOrderNo string `json:"thirdOrderNo"`
  38. MID int64 `json:"mid"`
  39. ThirdCoin string `json:"thirdCoin"`
  40. Brokerage string `json:"brokerage"`
  41. ThirdCtime int64 `json:"thirdCtime"`
  42. }
  43. // RechargeShell 转入贝壳
  44. func (p *Pay) RechargeShell(orderID string, mid int64, assetBP int64, shell int64) (params url.Values, jsonData string, err error) {
  45. var (
  46. productName = "UGC付费"
  47. rate = "1.00"
  48. timestamp = time.Now().Unix() * 1000
  49. thirdCoin = float64(assetBP) / 100
  50. brokerage = float64(shell) / 100
  51. )
  52. params = make(url.Values)
  53. params.Set("customerId", p.ID)
  54. params.Set("productName", productName)
  55. params.Set("rate", rate)
  56. params.Set("notifyUrl", p.RechargeShellNotifyURL)
  57. params.Set("timestamp", strconv.FormatInt(timestamp, 10))
  58. params.Set("data", fmt.Sprintf("[{brokerage=%.2f&mid=%d&thirdCoin=%.2f&thirdCtime=%d&thirdOrderNo=%s}]", brokerage, mid, thirdCoin, timestamp, orderID))
  59. p.Sign(params)
  60. data := RechargeShellData{
  61. ThirdOrderNo: orderID,
  62. MID: mid,
  63. ThirdCoin: fmt.Sprintf("%.2f", thirdCoin),
  64. Brokerage: fmt.Sprintf("%.2f", brokerage),
  65. ThirdCtime: timestamp,
  66. }
  67. req := RechargeShellReq{
  68. CustomerID: p.ID,
  69. ProductName: productName,
  70. Rate: rate,
  71. NotifyURL: p.RechargeShellNotifyURL,
  72. Timestamp: timestamp,
  73. SignType: params.Get("signType"),
  74. Sign: params.Get("sign"),
  75. Data: []RechargeShellData{data},
  76. }
  77. payBytes, err := json.Marshal(req)
  78. if err != nil {
  79. err = errors.Wrapf(err, "pay.RechargeShell.ToJSON : %s", params.Encode())
  80. return
  81. }
  82. jsonData = string(payBytes)
  83. return
  84. }
  85. // CheckOrder 对账param
  86. func (p Pay) CheckOrder(txID string) (params url.Values) {
  87. params = make(url.Values)
  88. params.Set("customerId", p.ID)
  89. params.Set("txIds", txID)
  90. return
  91. }
  92. // CheckRefundOrder 退款对账param
  93. func (p Pay) CheckRefundOrder(txID string) (params url.Values) {
  94. params = make(url.Values)
  95. params.Set("customerId", p.ID)
  96. params.Set("txIds", txID)
  97. return
  98. }
  99. // Query 返回订单查询param
  100. func (p *Pay) Query(orderID string) (params url.Values) {
  101. params = make(url.Values)
  102. params.Set("customerId", p.ID)
  103. params.Set("orderIds", orderID)
  104. params.Set("timestamp", strconv.FormatInt(time.Now().Unix()*1000, 10))
  105. params.Set("traceId", p.TraceID())
  106. params.Set("version", "1.0")
  107. return
  108. }
  109. // ToJSON param to json
  110. func (p *Pay) ToJSON(params url.Values) (j string, err error) {
  111. var (
  112. payBytes []byte
  113. pmap = make(map[string]string)
  114. )
  115. for k, v := range params {
  116. if len(v) > 0 {
  117. pmap[k] = v[0]
  118. }
  119. }
  120. if payBytes, err = json.Marshal(pmap); err != nil {
  121. err = errors.Wrapf(err, "pay.ToJSON : %s", params.Encode())
  122. return
  123. }
  124. j = string(payBytes)
  125. return
  126. }
  127. // DeviceType 支付平台DeviceType
  128. func (p *Pay) DeviceType(platform string) (t int64) {
  129. // 支付设备渠道类型, 1 pc 2 webapp 3 app 4jsapi 5 server 6小程序支付 7聚合二维码支付
  130. switch platform {
  131. case "ios", "android":
  132. return 3
  133. default:
  134. return 1
  135. }
  136. }
  137. // Sign 支付平台接口签名
  138. func (p *Pay) Sign(params url.Values) (err error) {
  139. params.Set("signType", "MD5")
  140. sortedStr := params.Encode()
  141. if sortedStr, err = url.QueryUnescape(sortedStr); err != nil {
  142. return
  143. }
  144. b := bytes.Buffer{}
  145. b.WriteString(sortedStr)
  146. b.WriteString("&token=" + p.Token)
  147. signMD5 := md5.Sum(b.Bytes())
  148. sign := hex.EncodeToString(signMD5[:])
  149. params.Set("sign", sign)
  150. return
  151. }
  152. // Verify 支付平台返回param校验
  153. func (p *Pay) Verify(params url.Values) (ok bool) {
  154. var (
  155. rs = params.Get("sign")
  156. s string
  157. )
  158. ok = false
  159. defer func() {
  160. if !ok {
  161. params.Set("sign", rs)
  162. log.Error("Verify pay sign error, expect : %s, actual : %s, params : %s", s, rs, params.Encode())
  163. }
  164. }()
  165. if rs == "" {
  166. return
  167. }
  168. params.Del("sign")
  169. if err := p.Sign(params); err != nil {
  170. log.Error("Verify pay sign error : %+v", err)
  171. return
  172. }
  173. s = params.Get("sign")
  174. if rs == s {
  175. ok = true
  176. return
  177. }
  178. return
  179. }