蛋蛋星球-制度模式
Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

208 linhas
6.9 KiB

  1. package wechat
  2. import (
  3. "context"
  4. "encoding/xml"
  5. "errors"
  6. "fmt"
  7. "github.com/go-pay/gopay"
  8. )
  9. // 统一下单
  10. // 商户文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
  11. // 服务商文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi_sl.php?chapter=9_1
  12. func (w *Client) UnifiedOrder(ctx context.Context, bm gopay.BodyMap) (wxRsp *UnifiedOrderResponse, err error) {
  13. err = bm.CheckEmptyError("nonce_str", "body", "out_trade_no", "total_fee", "spbill_create_ip", "notify_url", "trade_type")
  14. if err != nil {
  15. return nil, err
  16. }
  17. var bs []byte
  18. if w.IsProd {
  19. bs, err = w.doProdPost(ctx, bm, unifiedOrder)
  20. } else {
  21. bm.Set("total_fee", 101)
  22. bs, err = w.doSanBoxPost(ctx, bm, sandboxUnifiedOrder)
  23. }
  24. if err != nil {
  25. return nil, err
  26. }
  27. wxRsp = new(UnifiedOrderResponse)
  28. if err = xml.Unmarshal(bs, wxRsp); err != nil {
  29. return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
  30. }
  31. return wxRsp, nil
  32. }
  33. // 提交付款码支付
  34. // 商户文档:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_10&index=1
  35. // 服务商文档:https://pay.weixin.qq.com/wiki/doc/api/micropay_sl.php?chapter=9_10&index=1
  36. func (w *Client) Micropay(ctx context.Context, bm gopay.BodyMap) (wxRsp *MicropayResponse, err error) {
  37. err = bm.CheckEmptyError("nonce_str", "body", "out_trade_no", "total_fee", "spbill_create_ip", "auth_code")
  38. if err != nil {
  39. return nil, err
  40. }
  41. var bs []byte
  42. if w.IsProd {
  43. bs, err = w.doProdPost(ctx, bm, microPay)
  44. } else {
  45. bm.Set("total_fee", 1)
  46. bs, err = w.doSanBoxPost(ctx, bm, sandboxMicroPay)
  47. }
  48. if err != nil {
  49. return nil, err
  50. }
  51. wxRsp = new(MicropayResponse)
  52. if err = xml.Unmarshal(bs, wxRsp); err != nil {
  53. return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
  54. }
  55. return wxRsp, nil
  56. }
  57. // 查询订单
  58. // 商户文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_2
  59. // 服务商文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi_sl.php?chapter=9_2
  60. func (w *Client) QueryOrder(ctx context.Context, bm gopay.BodyMap) (wxRsp *QueryOrderResponse, resBm gopay.BodyMap, err error) {
  61. err = bm.CheckEmptyError("nonce_str")
  62. if err != nil {
  63. return nil, nil, err
  64. }
  65. if bm.GetString("out_trade_no") == gopay.NULL && bm.GetString("transaction_id") == gopay.NULL {
  66. return nil, nil, errors.New("out_trade_no and transaction_id are not allowed to be null at the same time")
  67. }
  68. var bs []byte
  69. if w.IsProd {
  70. bs, err = w.doProdPost(ctx, bm, orderQuery)
  71. } else {
  72. bs, err = w.doSanBoxPost(ctx, bm, sandboxOrderQuery)
  73. }
  74. if err != nil {
  75. return nil, nil, err
  76. }
  77. wxRsp = new(QueryOrderResponse)
  78. if err = xml.Unmarshal(bs, wxRsp); err != nil {
  79. return nil, nil, fmt.Errorf("xml.UnmarshalStruct(%s):%w", string(bs), err)
  80. }
  81. resBm = make(gopay.BodyMap)
  82. if err = xml.Unmarshal(bs, &resBm); err != nil {
  83. return nil, nil, fmt.Errorf("xml.UnmarshalBodyMap(%s):%w", string(bs), err)
  84. }
  85. return wxRsp, resBm, nil
  86. }
  87. // 关闭订单
  88. // 商户文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_3
  89. // 服务商文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi_sl.php?chapter=9_3
  90. func (w *Client) CloseOrder(ctx context.Context, bm gopay.BodyMap) (wxRsp *CloseOrderResponse, err error) {
  91. err = bm.CheckEmptyError("nonce_str", "out_trade_no")
  92. if err != nil {
  93. return nil, err
  94. }
  95. var bs []byte
  96. if w.IsProd {
  97. bs, err = w.doProdPost(ctx, bm, closeOrder)
  98. } else {
  99. bs, err = w.doSanBoxPost(ctx, bm, sandboxCloseOrder)
  100. }
  101. if err != nil {
  102. return nil, err
  103. }
  104. wxRsp = new(CloseOrderResponse)
  105. if err = xml.Unmarshal(bs, wxRsp); err != nil {
  106. return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
  107. }
  108. return wxRsp, nil
  109. }
  110. // 申请退款
  111. // 注意:请在初始化client时,调用 client 添加证书的相关方法添加证书
  112. // 商户文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4
  113. // 服务商文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi_sl.php?chapter=9_4
  114. func (w *Client) Refund(ctx context.Context, bm gopay.BodyMap) (wxRsp *RefundResponse, resBm gopay.BodyMap, err error) {
  115. err = bm.CheckEmptyError("nonce_str", "out_refund_no", "total_fee", "refund_fee")
  116. if err != nil {
  117. return nil, nil, err
  118. }
  119. if bm.GetString("out_trade_no") == gopay.NULL && bm.GetString("transaction_id") == gopay.NULL {
  120. return nil, nil, errors.New("out_trade_no and transaction_id are not allowed to be null at the same time")
  121. }
  122. var (
  123. bs []byte
  124. )
  125. if w.IsProd {
  126. bs, err = w.doProdPostTLS(ctx, bm, refund)
  127. } else {
  128. bs, err = w.doSanBoxPost(ctx, bm, sandboxRefund)
  129. }
  130. if err != nil {
  131. return nil, nil, err
  132. }
  133. wxRsp = new(RefundResponse)
  134. if err = xml.Unmarshal(bs, wxRsp); err != nil {
  135. return nil, nil, fmt.Errorf("xml.UnmarshalStruct(%s):%w", string(bs), err)
  136. }
  137. resBm = make(gopay.BodyMap)
  138. if err = xml.Unmarshal(bs, &resBm); err != nil {
  139. return nil, nil, fmt.Errorf("xml.UnmarshalBodyMap(%s):%w", string(bs), err)
  140. }
  141. return wxRsp, resBm, nil
  142. }
  143. // 查询退款
  144. // 商户文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_5
  145. // 服务商文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi_sl.php?chapter=9_5
  146. func (w *Client) QueryRefund(ctx context.Context, bm gopay.BodyMap) (wxRsp *QueryRefundResponse, resBm gopay.BodyMap, err error) {
  147. err = bm.CheckEmptyError("nonce_str")
  148. if err != nil {
  149. return nil, nil, err
  150. }
  151. if bm.GetString("refund_id") == gopay.NULL && bm.GetString("out_refund_no") == gopay.NULL && bm.GetString("transaction_id") == gopay.NULL && bm.GetString("out_trade_no") == gopay.NULL {
  152. return nil, nil, errors.New("refund_id, out_refund_no, out_trade_no, transaction_id are not allowed to be null at the same time")
  153. }
  154. var bs []byte
  155. if w.IsProd {
  156. bs, err = w.doProdPost(ctx, bm, refundQuery)
  157. } else {
  158. bs, err = w.doSanBoxPost(ctx, bm, sandboxRefundQuery)
  159. }
  160. if err != nil {
  161. return nil, nil, err
  162. }
  163. wxRsp = new(QueryRefundResponse)
  164. if err = xml.Unmarshal(bs, wxRsp); err != nil {
  165. return nil, nil, fmt.Errorf("xml.UnmarshalStruct(%s):%w", string(bs), err)
  166. }
  167. resBm = make(gopay.BodyMap)
  168. if err = xml.Unmarshal(bs, &resBm); err != nil {
  169. return nil, nil, fmt.Errorf("xml.UnmarshalBodyMap(%s):%w", string(bs), err)
  170. }
  171. return wxRsp, resBm, nil
  172. }
  173. // 撤销订单
  174. // 注意:请在初始化client时,调用 client 添加证书的相关方法添加证书
  175. // 商户文档:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_11&index=3
  176. // 服务商文档:https://pay.weixin.qq.com/wiki/doc/api/micropay_sl.php?chapter=9_11&index=3
  177. func (w *Client) Reverse(ctx context.Context, bm gopay.BodyMap) (wxRsp *ReverseResponse, err error) {
  178. err = bm.CheckEmptyError("nonce_str", "out_trade_no")
  179. if err != nil {
  180. return nil, err
  181. }
  182. var (
  183. bs []byte
  184. )
  185. if w.IsProd {
  186. bs, err = w.doProdPostTLS(ctx, bm, reverse)
  187. } else {
  188. bs, err = w.doSanBoxPost(ctx, bm, sandboxReverse)
  189. }
  190. if err != nil {
  191. return nil, err
  192. }
  193. wxRsp = new(ReverseResponse)
  194. if err = xml.Unmarshal(bs, wxRsp); err != nil {
  195. return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
  196. }
  197. return wxRsp, nil
  198. }