wechat_params.go 2.8 KB

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