wechat_params.go 3.6 KB

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