wechat_client.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. package gopay
  2. import (
  3. "encoding/xml"
  4. "github.com/parnurzeal/gorequest"
  5. )
  6. type weChatClient struct {
  7. AppId string
  8. MchId string
  9. secretKey string
  10. isProd bool
  11. }
  12. //初始化微信客户端 ok
  13. // appId:应用ID
  14. // mchID:商户ID
  15. // secretKey:Key值
  16. // isProd:是否是正式环境
  17. func NewWeChatClient(appId, mchId, secretKey string, isProd bool) *weChatClient {
  18. client := new(weChatClient)
  19. client.AppId = appId
  20. client.MchId = mchId
  21. client.secretKey = secretKey
  22. client.isProd = isProd
  23. return client
  24. }
  25. //统一下单 ok
  26. // 文档地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
  27. func (this *weChatClient) UnifiedOrder(body BodyMap) (wxRsp *WeChatUnifiedOrderResponse, err error) {
  28. var bytes []byte
  29. if this.isProd {
  30. //正式环境
  31. bytes, err = this.doWeChat(body, wxURL_UnifiedOrder)
  32. if err != nil {
  33. return nil, err
  34. }
  35. } else {
  36. body.Set("total_fee", 101)
  37. bytes, err = this.doWeChat(body, wxURL_SanBox_UnifiedOrder)
  38. if err != nil {
  39. return nil, err
  40. }
  41. }
  42. wxRsp = new(WeChatUnifiedOrderResponse)
  43. err = xml.Unmarshal(bytes, wxRsp)
  44. if err != nil {
  45. return nil, err
  46. }
  47. return wxRsp, nil
  48. }
  49. //查询订单 ok
  50. // 文档地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_2
  51. func (this *weChatClient) QueryOrder(body BodyMap) (wxRsp *WeChatQueryOrderResponse, err error) {
  52. var bytes []byte
  53. if this.isProd {
  54. //正式环境
  55. bytes, err = this.doWeChat(body, wxURL_OrderQuery)
  56. if err != nil {
  57. return nil, err
  58. }
  59. } else {
  60. bytes, err = this.doWeChat(body, wxURL_SanBox_OrderQuery)
  61. if err != nil {
  62. return nil, err
  63. }
  64. }
  65. wxRsp = new(WeChatQueryOrderResponse)
  66. err = xml.Unmarshal(bytes, wxRsp)
  67. if err != nil {
  68. return nil, err
  69. }
  70. return wxRsp, nil
  71. }
  72. //关闭订单 ok
  73. // 文档地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_3
  74. func (this *weChatClient) CloseOrder(body BodyMap) (wxRsp *WeChatCloseOrderResponse, err error) {
  75. var bytes []byte
  76. if this.isProd {
  77. //正式环境
  78. bytes, err = this.doWeChat(body, wxURL_CloseOrder)
  79. if err != nil {
  80. return nil, err
  81. }
  82. } else {
  83. bytes, err = this.doWeChat(body, wxURL_SanBox_CloseOrder)
  84. if err != nil {
  85. return nil, err
  86. }
  87. }
  88. wxRsp = new(WeChatCloseOrderResponse)
  89. err = xml.Unmarshal(bytes, wxRsp)
  90. if err != nil {
  91. return nil, err
  92. }
  93. return wxRsp, nil
  94. }
  95. //申请退款 ok
  96. // 文档地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4
  97. func (this *weChatClient) Refund(body BodyMap) (wxRsp *WeChatRefundResponse, err error) {
  98. var bytes []byte
  99. if this.isProd {
  100. //正式环境
  101. bytes, err = this.doWeChat(body, wxURL_Refund)
  102. if err != nil {
  103. return nil, err
  104. }
  105. } else {
  106. bytes, err = this.doWeChat(body, wxURL_SanBox_Refund)
  107. if err != nil {
  108. return nil, err
  109. }
  110. }
  111. wxRsp = new(WeChatRefundResponse)
  112. err = xml.Unmarshal(bytes, wxRsp)
  113. if err != nil {
  114. return nil, err
  115. }
  116. return wxRsp, nil
  117. }
  118. //查询退款 ok
  119. // 文档地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_5
  120. func (this *weChatClient) QueryRefund(body BodyMap) (wxRsp *WeChatQueryRefundResponse, err error) {
  121. var bytes []byte
  122. if this.isProd {
  123. //正式环境
  124. bytes, err = this.doWeChat(body, wxURL_RefundQuery)
  125. if err != nil {
  126. return nil, err
  127. }
  128. } else {
  129. bytes, err = this.doWeChat(body, wxURL_SanBox_RefundQuery)
  130. if err != nil {
  131. return nil, err
  132. }
  133. }
  134. wxRsp = new(WeChatQueryRefundResponse)
  135. err = xml.Unmarshal(bytes, wxRsp)
  136. if err != nil {
  137. return nil, err
  138. }
  139. return wxRsp, nil
  140. }
  141. //下载对账单 ok
  142. // 文档地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_6
  143. func (this *weChatClient) DownloadBill(body BodyMap) (wxRsp string, err error) {
  144. var bytes []byte
  145. if this.isProd {
  146. //正式环境
  147. bytes, err = this.doWeChat(body, wxURL_DownloadBill)
  148. } else {
  149. bytes, err = this.doWeChat(body, wxURL_SanBox_DownloadBill)
  150. }
  151. wxRsp = string(bytes)
  152. if err != nil {
  153. return wxRsp, err
  154. }
  155. return wxRsp, nil
  156. }
  157. //下载资金账单 ok
  158. // 文档地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_18&index=7
  159. // 好像不支持沙箱环境,因为沙箱环境默认需要用MD5签名,但是此接口仅支持HMAC-SHA256签名
  160. func (this *weChatClient) DownloadFundFlow(body BodyMap) (wxRsp string, err error) {
  161. var bytes []byte
  162. if this.isProd {
  163. //正式环境
  164. bytes, err = this.doWeChat(body, wxURL_DownloadFundFlow)
  165. } else {
  166. bytes, err = this.doWeChat(body, wxURL_SanBox_DownloadFundFlow)
  167. }
  168. wxRsp = string(bytes)
  169. if err != nil {
  170. return wxRsp, err
  171. }
  172. return wxRsp, nil
  173. }
  174. //拉取订单评价数据
  175. // 文档地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_17&index=11
  176. // 好像不支持沙箱环境,因为沙箱环境默认需要用MD5签名,但是此接口仅支持HMAC-SHA256签名
  177. func (this *weChatClient) BatchQueryComment(body BodyMap) (wxRsp string, err error) {
  178. var bytes []byte
  179. if this.isProd {
  180. //正式环境
  181. body.Set("sign_type", SignType_HMAC_SHA256)
  182. bytes, err = this.doWeChat(body, wxURL_BatchQueryComment)
  183. } else {
  184. bytes, err = this.doWeChat(body, wxURL_SanBox_BatchQueryComment)
  185. }
  186. wxRsp = string(bytes)
  187. if err != nil {
  188. return wxRsp, err
  189. }
  190. return wxRsp, nil
  191. }
  192. //向微信发送请求 ok
  193. func (this *weChatClient) doWeChat(body BodyMap, url string) (bytes []byte, err error) {
  194. var sign string
  195. body.Set("appid", this.AppId)
  196. body.Set("mch_id", this.MchId)
  197. //===============生成参数===================
  198. if !this.isProd {
  199. //沙箱环境
  200. body.Set("sign_type", SignType_MD5)
  201. //从微信接口获取SanBoxSignKey
  202. key, err := getSanBoxSign(this.MchId, body.Get("nonce_str"), this.secretKey, body.Get("sign_type"))
  203. if err != nil {
  204. return nil, err
  205. }
  206. sign = getLocalSign(key, body.Get("sign_type"), body)
  207. } else {
  208. //正式环境
  209. //本地计算Sign
  210. sign = getLocalSign(this.secretKey, body.Get("sign_type"), body)
  211. }
  212. body.Set("sign", sign)
  213. reqXML := generateXml(body)
  214. //===============发起请求===================
  215. agent := gorequest.New()
  216. if this.isProd {
  217. agent.Post(url)
  218. } else {
  219. agent.Post(url)
  220. }
  221. agent.Type("xml")
  222. agent.SendString(reqXML)
  223. _, bytes, errs := agent.EndBytes()
  224. if len(errs) > 0 {
  225. return nil, errs[0]
  226. }
  227. return bytes, nil
  228. }