wechat_params.go 3.7 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. "strings"
  13. )
  14. //JSAPI支付,支付参数后,再次计算出小程序用的paySign
  15. func GetMiniPaySign(appId, nonceStr, prepayId, signType, timeStamp, secretKey string) (paySign string) {
  16. buffer := new(bytes.Buffer)
  17. buffer.WriteString("appId=")
  18. buffer.WriteString(appId)
  19. buffer.WriteString("&nonceStr=")
  20. buffer.WriteString(nonceStr)
  21. buffer.WriteString("&package=")
  22. buffer.WriteString(prepayId)
  23. buffer.WriteString("&signType=")
  24. buffer.WriteString(signType)
  25. buffer.WriteString("&timeStamp=")
  26. buffer.WriteString(timeStamp)
  27. buffer.WriteString("&key=")
  28. buffer.WriteString(secretKey)
  29. signStr := buffer.String()
  30. var hashSign []byte
  31. if signType == SignType_MD5 {
  32. hash := md5.New()
  33. hash.Write([]byte(signStr))
  34. hashSign = hash.Sum(nil)
  35. } else {
  36. hash := hmac.New(sha256.New, []byte(secretKey))
  37. hash.Write([]byte(signStr))
  38. hashSign = hash.Sum(nil)
  39. }
  40. paySign = strings.ToUpper(hex.EncodeToString(hashSign))
  41. return
  42. }
  43. //本地通过支付参数计算Sign值
  44. func getLocalSign(secretKey string, signType string, body BodyMap) (sign string) {
  45. signStr := sortSignParams(secretKey, body)
  46. //fmt.Println("signStr:", signStr)
  47. var hashSign []byte
  48. if signType == SignType_MD5 {
  49. hash := md5.New()
  50. hash.Write([]byte(signStr))
  51. hashSign = hash.Sum(nil)
  52. } else {
  53. hash := hmac.New(sha256.New, []byte(secretKey))
  54. hash.Write([]byte(signStr))
  55. hashSign = hash.Sum(nil)
  56. }
  57. sign = strings.ToUpper(hex.EncodeToString(hashSign))
  58. return
  59. }
  60. //获取根据Key排序后的请求参数字符串
  61. func sortSignParams(secretKey string, body BodyMap) string {
  62. keyList := make([]string, 0)
  63. for k := range body {
  64. keyList = append(keyList, k)
  65. }
  66. sort.Strings(keyList)
  67. buffer := new(bytes.Buffer)
  68. for _, k := range keyList {
  69. buffer.WriteString(k)
  70. buffer.WriteString("=")
  71. valueStr := convert2String(body[k])
  72. buffer.WriteString(valueStr)
  73. buffer.WriteString("&")
  74. }
  75. buffer.WriteString("key=")
  76. buffer.WriteString(secretKey)
  77. return buffer.String()
  78. }
  79. //从微信提供的接口获取:SandboxSignKey
  80. func getSanBoxSign(mchId, nonceStr, secretKey, signType string) (key string, err error) {
  81. body := make(BodyMap)
  82. body.Set("mch_id", mchId)
  83. body.Set("nonce_str", nonceStr)
  84. //计算沙箱参数Sign
  85. sanboxSign := getLocalSign(secretKey, signType, body)
  86. //沙箱环境:获取key后,重新计算Sign
  87. key, err = getSanBoxSignKey(mchId, nonceStr, sanboxSign)
  88. if err != nil {
  89. return "", err
  90. }
  91. return
  92. }
  93. //从微信提供的接口获取:SandboxSignkey
  94. func getSanBoxSignKey(mchId, nonceStr, sign string) (key string, err error) {
  95. reqs := make(BodyMap)
  96. reqs.Set("mch_id", mchId)
  97. reqs.Set("nonce_str", nonceStr)
  98. reqs.Set("sign", sign)
  99. reqXml := generateXml(reqs)
  100. //fmt.Println("req:::", reqXml)
  101. _, byteList, errorList := gorequest.New().
  102. Post(wxURL_SanBox_GetSignKey).
  103. Type("xml").
  104. SendString(reqXml).EndBytes()
  105. if len(errorList) > 0 {
  106. return "", errorList[0]
  107. }
  108. keyResponse := new(getSignKeyResponse)
  109. err = xml.Unmarshal(byteList, keyResponse)
  110. if err != nil {
  111. return "", err
  112. }
  113. if keyResponse.ReturnCode == "FAIL" {
  114. return "", errors.New(keyResponse.Retmsg)
  115. }
  116. return keyResponse.SandboxSignkey, nil
  117. }
  118. //生成请求XML的Body体
  119. func generateXml(bm BodyMap) (reqXml string) {
  120. buffer := new(bytes.Buffer)
  121. buffer.WriteString("<xml>")
  122. for k, v := range bm {
  123. buffer.WriteString("<")
  124. buffer.WriteString(k)
  125. buffer.WriteString("><![CDATA[")
  126. valueStr := convert2String(v)
  127. buffer.WriteString(valueStr)
  128. buffer.WriteString("]]></")
  129. buffer.WriteString(k)
  130. buffer.WriteString(">")
  131. }
  132. buffer.WriteString("</xml>")
  133. reqXml = buffer.String()
  134. return
  135. }