refund.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. package refund
  2. import (
  3. "encoding/xml"
  4. "fmt"
  5. "github.com/silenceper/wechat/v2/pay/config"
  6. "github.com/silenceper/wechat/v2/util"
  7. )
  8. var refundGateway = "https://api.mch.weixin.qq.com/secapi/pay/refund"
  9. // Refund struct extends context
  10. type Refund struct {
  11. *config.Config
  12. }
  13. // NewRefund return an instance of refund package
  14. func NewRefund(cfg *config.Config) *Refund {
  15. refund := Refund{cfg}
  16. return &refund
  17. }
  18. //Params 调用参数
  19. type Params struct {
  20. TransactionID string
  21. OutRefundNo string
  22. TotalFee string
  23. RefundFee string
  24. RefundDesc string
  25. RootCa string //ca证书
  26. NotifyURL string
  27. }
  28. //request 接口请求参数
  29. type request struct {
  30. AppID string `xml:"appid"`
  31. MchID string `xml:"mch_id"`
  32. NonceStr string `xml:"nonce_str"`
  33. Sign string `xml:"sign"`
  34. SignType string `xml:"sign_type,omitempty"`
  35. TransactionID string `xml:"transaction_id"`
  36. OutRefundNo string `xml:"out_refund_no"`
  37. TotalFee string `xml:"total_fee"`
  38. RefundFee string `xml:"refund_fee"`
  39. RefundDesc string `xml:"refund_desc,omitempty"`
  40. NotifyURL string `xml:"notify_url,omitempty"`
  41. }
  42. //Response 接口返回
  43. type Response struct {
  44. ReturnCode string `xml:"return_code"`
  45. ReturnMsg string `xml:"return_msg"`
  46. AppID string `xml:"appid,omitempty"`
  47. MchID string `xml:"mch_id,omitempty"`
  48. NonceStr string `xml:"nonce_str,omitempty"`
  49. Sign string `xml:"sign,omitempty"`
  50. ResultCode string `xml:"result_code,omitempty"`
  51. ErrCode string `xml:"err_code,omitempty"`
  52. ErrCodeDes string `xml:"err_code_des,omitempty"`
  53. TransactionID string `xml:"transaction_id,omitempty"`
  54. OutTradeNo string `xml:"out_trade_no,omitempty"`
  55. OutRefundNo string `xml:"out_refund_no,omitempty"`
  56. RefundID string `xml:"refund_id,omitempty"`
  57. RefundFee string `xml:"refund_fee,omitempty"`
  58. SettlementRefundFee string `xml:"settlement_refund_fee,omitempty"`
  59. TotalFee string `xml:"total_fee,omitempty"`
  60. SettlementTotalFee string `xml:"settlement_total_fee,omitempty"`
  61. FeeType string `xml:"fee_type,omitempty"`
  62. CashFee string `xml:"cash_fee,omitempty"`
  63. CashFeeType string `xml:"cash_fee_type,omitempty"`
  64. }
  65. //Refund 退款申请
  66. func (refund *Refund) Refund(p *Params) (rsp Response, err error) {
  67. nonceStr := util.RandomStr(32)
  68. param := make(map[string]string)
  69. param["appid"] = refund.AppID
  70. param["mch_id"] = refund.MchID
  71. param["nonce_str"] = nonceStr
  72. param["out_refund_no"] = p.OutRefundNo
  73. param["refund_desc"] = p.RefundDesc
  74. param["refund_fee"] = p.RefundFee
  75. param["total_fee"] = p.TotalFee
  76. param["sign_type"] = util.SignTypeMD5
  77. param["transaction_id"] = p.TransactionID
  78. if p.NotifyURL != "" {
  79. param["notify_url"] = p.NotifyURL
  80. }
  81. sign, err := util.ParamSign(param, refund.Key)
  82. if err != nil {
  83. return
  84. }
  85. req := request{
  86. AppID: refund.AppID,
  87. MchID: refund.MchID,
  88. NonceStr: nonceStr,
  89. Sign: sign,
  90. SignType: util.SignTypeMD5,
  91. TransactionID: p.TransactionID,
  92. OutRefundNo: p.OutRefundNo,
  93. TotalFee: p.TotalFee,
  94. RefundFee: p.RefundFee,
  95. RefundDesc: p.RefundDesc,
  96. }
  97. rawRet, err := util.PostXMLWithTLS(refundGateway, req, p.RootCa, refund.MchID)
  98. if err != nil {
  99. return
  100. }
  101. err = xml.Unmarshal(rawRet, &rsp)
  102. if err != nil {
  103. return
  104. }
  105. if rsp.ReturnCode == "SUCCESS" {
  106. if rsp.ResultCode == "SUCCESS" {
  107. err = nil
  108. return
  109. }
  110. err = fmt.Errorf("refund error, errcode=%s,errmsg=%s", rsp.ErrCode, rsp.ErrCodeDes)
  111. return
  112. }
  113. err = fmt.Errorf("[msg : xmlUnmarshalError] [rawReturn : %s] [sign : %s]", string(rawRet), sign)
  114. return
  115. }