wechat_params.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. package gopay
  2. import (
  3. "bytes"
  4. "crypto/hmac"
  5. "crypto/md5"
  6. "crypto/sha256"
  7. "encoding/hex"
  8. "encoding/xml"
  9. "errors"
  10. "github.com/parnurzeal/gorequest"
  11. "sort"
  12. "strconv"
  13. "strings"
  14. )
  15. //获取请求支付的参数
  16. func (w *WeChatPayParams) getRequestBody(appId, mchId string, params *WeChatPayParams) (reqs requestBody) {
  17. reqs = make(requestBody)
  18. reqs.Set("appid", appId)
  19. reqs.Set("mch_id", mchId)
  20. reqs.Set("nonce_str", params.NonceStr)
  21. reqs.Set("body", params.Body)
  22. reqs.Set("out_trade_no", params.OutTradeNo)
  23. reqs.Set("total_fee", strconv.Itoa(params.TotalFee))
  24. reqs.Set("spbill_create_ip", params.SpbillCreateIp)
  25. reqs.Set("notify_url", params.NotifyUrl)
  26. reqs.Set("trade_type", params.TradeType)
  27. if params.DeviceInfo != "" {
  28. reqs.Set("device_info", params.DeviceInfo)
  29. }
  30. if params.SignType != "" {
  31. reqs.Set("sign_type", params.SignType)
  32. } else {
  33. reqs.Set("sign_type", "MD5")
  34. }
  35. if params.Detail != "" {
  36. reqs.Set("detail", params.Detail)
  37. }
  38. if params.Attach != "" {
  39. reqs.Set("attach", params.Attach)
  40. }
  41. if params.FeeType != "" {
  42. reqs.Set("fee_type", params.FeeType)
  43. }
  44. if params.TimeStart != "" {
  45. reqs.Set("time_start", params.TimeStart)
  46. }
  47. if params.TimeExpire != "" {
  48. reqs.Set("time_expire", params.TimeExpire)
  49. }
  50. if params.GoodsTag != "" {
  51. reqs.Set("goods_tag", params.GoodsTag)
  52. }
  53. if params.ProductId != "" {
  54. reqs.Set("product_id", params.ProductId)
  55. }
  56. if params.LimitPay != "" {
  57. reqs.Set("limit_pay", params.LimitPay)
  58. }
  59. if params.Openid != "" {
  60. reqs.Set("openid", params.Openid)
  61. }
  62. if params.Receipt != "" {
  63. reqs.Set("receipt", params.Receipt)
  64. }
  65. if params.SceneInfo != "" {
  66. //marshal, _ := json.Marshal(params.SceneInfo)
  67. //reqs.Set("scene_info", string(marshal))
  68. reqs.Set("scene_info", params.SceneInfo)
  69. }
  70. return reqs
  71. }
  72. //获取SanBox秘钥
  73. func (w *WeChatPayParams) getSanBoxSignKey(mchId, nonceStr, secretKey, signType string) (key string, err error) {
  74. body := make(requestBody)
  75. body.Set("mch_id", mchId)
  76. body.Set("nonce_str", nonceStr)
  77. //计算沙箱参数Sign
  78. sanboxSign := getSign(secretKey, signType, body)
  79. //沙箱环境:获取key后,重新计算Sign
  80. key, err = getSanBoxSignKey(mchId, nonceStr, sanboxSign)
  81. if err != nil {
  82. return "", err
  83. }
  84. return
  85. }
  86. //获取Sign签名和请求支付的参数
  87. func getSign(secretKey string, signType string, body requestBody) (sign string) {
  88. signStr := getSignString(secretKey, body)
  89. //fmt.Println("signStr:", signStr)
  90. var hashSign []byte
  91. if signType == WX_SignType_MD5 {
  92. hash := md5.New()
  93. hash.Write([]byte(signStr))
  94. hashSign = hash.Sum(nil)
  95. } else {
  96. hash := hmac.New(sha256.New, []byte(secretKey))
  97. hash.Write([]byte(signStr))
  98. hashSign = hash.Sum(nil)
  99. }
  100. sign = strings.ToUpper(hex.EncodeToString(hashSign))
  101. return
  102. }
  103. //获取根据Key排序后的请求参数字符串
  104. func getSignString(secretKey string, body requestBody) string {
  105. keyList := make([]string, 0)
  106. for k := range body {
  107. keyList = append(keyList, k)
  108. }
  109. sort.Strings(keyList)
  110. buffer := new(bytes.Buffer)
  111. for _, k := range keyList {
  112. buffer.WriteString(k)
  113. buffer.WriteString("=")
  114. buffer.WriteString(body[k])
  115. buffer.WriteString("&")
  116. }
  117. buffer.WriteString("key=")
  118. buffer.WriteString(secretKey)
  119. return buffer.String()
  120. }
  121. //获取SanboxKey
  122. func getSanBoxSignKey(mchId, nonceStr, sign string) (key string, err error) {
  123. reqs := make(requestBody)
  124. reqs.Set("mch_id", mchId)
  125. reqs.Set("nonce_str", nonceStr)
  126. reqs.Set("sign", sign)
  127. reqXml := generateXml(reqs)
  128. //fmt.Println("req:::", reqXml)
  129. _, byteList, errorList := gorequest.New().
  130. Post(wxURL_sanbox_getsignkey).
  131. Type("xml").
  132. SendString(reqXml).EndBytes()
  133. if len(errorList) > 0 {
  134. return "", errorList[0]
  135. }
  136. keyResponse := new(getSignKeyResponse)
  137. err = xml.Unmarshal(byteList, keyResponse)
  138. if err != nil {
  139. return "", err
  140. }
  141. if keyResponse.ReturnCode == "FAIL" {
  142. return "", errors.New(keyResponse.Retmsg)
  143. }
  144. return keyResponse.SandboxSignkey, nil
  145. }