wechat_params.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  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. "sort"
  11. "strings"
  12. )
  13. type Country int
  14. //设置支付国家(默认:中国国内)
  15. // 根据支付地区情况设置国家
  16. // country:<China:中国国内,China2:中国国内(冗灾方案),SoutheastAsia:东南亚,Other:其他国家>
  17. func (this *weChatClient) SetCountry(country Country) (client *weChatClient) {
  18. switch country {
  19. case China:
  20. this.baseURL = wx_base_url_ch
  21. case China2:
  22. this.baseURL = wx_base_url_ch2
  23. case SoutheastAsia:
  24. this.baseURL = wx_base_url_hk
  25. case Other:
  26. this.baseURL = wx_base_url_us
  27. default:
  28. this.baseURL = wx_base_url_ch
  29. }
  30. return this
  31. }
  32. //本地通过支付参数计算Sign值
  33. func getLocalSign(apiKey string, signType string, body BodyMap) (sign string) {
  34. signStr := sortWeChatSignParams(apiKey, body)
  35. //fmt.Println("signStr:", signStr)
  36. var hashSign []byte
  37. if signType == SignType_HMAC_SHA256 {
  38. hash := hmac.New(sha256.New, []byte(apiKey))
  39. hash.Write([]byte(signStr))
  40. hashSign = hash.Sum(nil)
  41. } else {
  42. hash := md5.New()
  43. hash.Write([]byte(signStr))
  44. hashSign = hash.Sum(nil)
  45. }
  46. sign = strings.ToUpper(hex.EncodeToString(hashSign))
  47. return
  48. }
  49. //获取根据Key排序后的请求参数字符串
  50. func sortWeChatSignParams(apiKey string, body BodyMap) string {
  51. keyList := make([]string, 0)
  52. for k := range body {
  53. keyList = append(keyList, k)
  54. }
  55. sort.Strings(keyList)
  56. buffer := new(bytes.Buffer)
  57. for _, k := range keyList {
  58. buffer.WriteString(k)
  59. buffer.WriteString("=")
  60. buffer.WriteString(body.Get(k))
  61. buffer.WriteString("&")
  62. }
  63. buffer.WriteString("key=")
  64. buffer.WriteString(apiKey)
  65. return buffer.String()
  66. }
  67. //从微信提供的接口获取:SandboxSignKey
  68. func getSanBoxSign(mchId, nonceStr, apiKey, signType string) (key string, err error) {
  69. body := make(BodyMap)
  70. body.Set("mch_id", mchId)
  71. body.Set("nonce_str", nonceStr)
  72. //计算沙箱参数Sign
  73. sanboxSign := getLocalSign(apiKey, signType, body)
  74. //沙箱环境:获取key后,重新计算Sign
  75. key, err = getSanBoxSignKey(mchId, nonceStr, sanboxSign)
  76. if err != nil {
  77. return null, err
  78. }
  79. return
  80. }
  81. //从微信提供的接口获取:SandboxSignkey
  82. func getSanBoxSignKey(mchId, nonceStr, sign string) (key string, err error) {
  83. reqs := make(BodyMap)
  84. reqs.Set("mch_id", mchId)
  85. reqs.Set("nonce_str", nonceStr)
  86. reqs.Set("sign", sign)
  87. reqXml := generateXml(reqs)
  88. //fmt.Println("req:::", reqXml)
  89. _, byteList, errorList := HttpAgent().
  90. Post(wx_SanBox_GetSignKey).
  91. Type("xml").
  92. SendString(reqXml).EndBytes()
  93. if len(errorList) > 0 {
  94. return null, errorList[0]
  95. }
  96. keyResponse := new(getSignKeyResponse)
  97. err = xml.Unmarshal(byteList, keyResponse)
  98. if err != nil {
  99. return null, err
  100. }
  101. if keyResponse.ReturnCode == "FAIL" {
  102. return null, errors.New(keyResponse.Retmsg)
  103. }
  104. return keyResponse.SandboxSignkey, nil
  105. }
  106. //生成请求XML的Body体
  107. func generateXml(bm BodyMap) (reqXml string) {
  108. buffer := new(bytes.Buffer)
  109. buffer.WriteString("<xml>")
  110. for key := range bm {
  111. buffer.WriteString("<")
  112. buffer.WriteString(key)
  113. buffer.WriteString("><![CDATA[")
  114. buffer.WriteString(bm.Get(key))
  115. buffer.WriteString("]]></")
  116. buffer.WriteString(key)
  117. buffer.WriteString(">")
  118. }
  119. buffer.WriteString("</xml>")
  120. reqXml = buffer.String()
  121. return
  122. }