wechat_params.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. package gopay
  2. import (
  3. "crypto/hmac"
  4. "crypto/md5"
  5. "crypto/sha256"
  6. "encoding/hex"
  7. "encoding/xml"
  8. "errors"
  9. "hash"
  10. "strings"
  11. )
  12. type Country int
  13. //设置支付国家(默认:中国国内)
  14. // 根据支付地区情况设置国家
  15. // country:<China:中国国内,China2:中国国内(冗灾方案),SoutheastAsia:东南亚,Other:其他国家>
  16. func (w *WeChatClient) SetCountry(country Country) (client *WeChatClient) {
  17. switch country {
  18. case China:
  19. w.BaseURL = wxBaseUrlCh
  20. case China2:
  21. w.BaseURL = wxBaseUrlCh2
  22. case SoutheastAsia:
  23. w.BaseURL = wxBaseUrlHk
  24. case Other:
  25. w.BaseURL = wxBaseUrlUs
  26. default:
  27. w.BaseURL = wxBaseUrlCh
  28. }
  29. return w
  30. }
  31. //获取微信支付正式环境Sign值
  32. func getWeChatReleaseSign(apiKey string, signType string, bm BodyMap) (sign string) {
  33. var h hash.Hash
  34. if signType == SignType_HMAC_SHA256 {
  35. h = hmac.New(sha256.New, []byte(apiKey))
  36. } else {
  37. h = md5.New()
  38. }
  39. h.Write([]byte(bm.EncodeWeChatSignParams(apiKey)))
  40. sign = strings.ToUpper(hex.EncodeToString(h.Sum(nil)))
  41. return
  42. }
  43. //获取微信支付沙箱环境Sign值
  44. func getWeChatSignBoxSign(mchId, apiKey string, bm BodyMap) (sign string, err error) {
  45. var (
  46. sandBoxApiKey string
  47. h hash.Hash
  48. )
  49. if sandBoxApiKey, err = getSanBoxKey(mchId, GetRandomString(32), apiKey, SignType_MD5); err != nil {
  50. return
  51. }
  52. h = md5.New()
  53. h.Write([]byte(bm.EncodeWeChatSignParams(sandBoxApiKey)))
  54. sign = strings.ToUpper(hex.EncodeToString(h.Sum(nil)))
  55. return
  56. }
  57. //从微信提供的接口获取:SandboxSignKey
  58. func getSanBoxKey(mchId, nonceStr, apiKey, signType string) (key string, err error) {
  59. body := make(BodyMap)
  60. body.Set("mch_id", mchId)
  61. body.Set("nonce_str", nonceStr)
  62. //沙箱环境:获取沙箱环境ApiKey
  63. if key, err = getSanBoxSignKey(mchId, nonceStr, getWeChatReleaseSign(apiKey, signType, body)); err != nil {
  64. return
  65. }
  66. return
  67. }
  68. //从微信提供的接口获取:SandboxSignkey
  69. func getSanBoxSignKey(mchId, nonceStr, sign string) (key string, err error) {
  70. reqs := make(BodyMap)
  71. reqs.Set("mch_id", mchId)
  72. reqs.Set("nonce_str", nonceStr)
  73. reqs.Set("sign", sign)
  74. var (
  75. byteList []byte
  76. errorList []error
  77. keyResponse *getSignKeyResponse
  78. )
  79. if _, byteList, errorList = HttpAgent().Post(wxSandboxGetsignkey).Type("xml").SendString(generateXml(reqs)).EndBytes(); len(errorList) > 0 {
  80. return null, errorList[0]
  81. }
  82. keyResponse = new(getSignKeyResponse)
  83. if err = xml.Unmarshal(byteList, keyResponse); err != nil {
  84. return
  85. }
  86. if keyResponse.ReturnCode == "FAIL" {
  87. return null, errors.New(keyResponse.ReturnMsg)
  88. }
  89. return keyResponse.SandboxSignkey, nil
  90. }
  91. //生成请求XML的Body体
  92. func generateXml(bm BodyMap) (reqXml string) {
  93. var buffer strings.Builder
  94. buffer.WriteString("<xml>")
  95. for key := range bm {
  96. buffer.WriteByte('<')
  97. buffer.WriteString(key)
  98. buffer.WriteString("><![CDATA[")
  99. buffer.WriteString(bm.Get(key))
  100. buffer.WriteString("]]></")
  101. buffer.WriteString(key)
  102. buffer.WriteByte('>')
  103. }
  104. buffer.WriteString("</xml>")
  105. reqXml = buffer.String()
  106. return
  107. }