wechat_params.go 2.8 KB

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