refund.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  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. OutTradeNo string
  22. OutRefundNo string
  23. TotalFee string
  24. RefundFee string
  25. RefundDesc string
  26. RootCa string //ca证书
  27. NotifyURL string
  28. }
  29. //request 接口请求参数
  30. type request struct {
  31. AppID string `xml:"appid"`
  32. MchID string `xml:"mch_id"`
  33. NonceStr string `xml:"nonce_str"`
  34. Sign string `xml:"sign"`
  35. SignType string `xml:"sign_type,omitempty"`
  36. TransactionID string `xml:"transaction_id,omitempty"`
  37. OutTradeNo string `xml:"out_trade_no,omitempty"`
  38. OutRefundNo string `xml:"out_refund_no"`
  39. TotalFee string `xml:"total_fee"`
  40. RefundFee string `xml:"refund_fee"`
  41. RefundDesc string `xml:"refund_desc,omitempty"`
  42. NotifyURL string `xml:"notify_url,omitempty"`
  43. }
  44. //Response 接口返回
  45. type Response struct {
  46. ReturnCode string `xml:"return_code"`
  47. ReturnMsg string `xml:"return_msg"`
  48. AppID string `xml:"appid,omitempty"`
  49. MchID string `xml:"mch_id,omitempty"`
  50. NonceStr string `xml:"nonce_str,omitempty"`
  51. Sign string `xml:"sign,omitempty"`
  52. ResultCode string `xml:"result_code,omitempty"`
  53. ErrCode string `xml:"err_code,omitempty"`
  54. ErrCodeDes string `xml:"err_code_des,omitempty"`
  55. TransactionID string `xml:"transaction_id,omitempty"`
  56. OutTradeNo string `xml:"out_trade_no,omitempty"`
  57. OutRefundNo string `xml:"out_refund_no,omitempty"`
  58. RefundID string `xml:"refund_id,omitempty"`
  59. RefundFee string `xml:"refund_fee,omitempty"`
  60. SettlementRefundFee string `xml:"settlement_refund_fee,omitempty"`
  61. TotalFee string `xml:"total_fee,omitempty"`
  62. SettlementTotalFee string `xml:"settlement_total_fee,omitempty"`
  63. FeeType string `xml:"fee_type,omitempty"`
  64. CashFee string `xml:"cash_fee,omitempty"`
  65. CashFeeType string `xml:"cash_fee_type,omitempty"`
  66. }
  67. //Refund 退款申请
  68. func (refund *Refund) Refund(p *Params) (rsp Response, err error) {
  69. nonceStr := util.RandomStr(32)
  70. param := make(map[string]string)
  71. param["appid"] = refund.AppID
  72. param["mch_id"] = refund.MchID
  73. param["nonce_str"] = nonceStr
  74. param["out_refund_no"] = p.OutRefundNo
  75. param["refund_desc"] = p.RefundDesc
  76. param["refund_fee"] = p.RefundFee
  77. param["total_fee"] = p.TotalFee
  78. param["sign_type"] = util.SignTypeMD5
  79. if p.TransactionID != "" {
  80. param["transaction_id"] = p.TransactionID
  81. }
  82. if p.OutTradeNo != "" {
  83. param["out_trade_no"] = p.OutTradeNo
  84. }
  85. if p.NotifyURL != "" {
  86. param["notify_url"] = p.NotifyURL
  87. }
  88. sign, err := util.ParamSign(param, refund.Key)
  89. if err != nil {
  90. return
  91. }
  92. req := request{
  93. AppID: refund.AppID,
  94. MchID: refund.MchID,
  95. NonceStr: nonceStr,
  96. Sign: sign,
  97. SignType: util.SignTypeMD5,
  98. TransactionID: p.TransactionID,
  99. OutRefundNo: p.OutRefundNo,
  100. OutTradeNo: p.OutTradeNo,
  101. TotalFee: p.TotalFee,
  102. RefundFee: p.RefundFee,
  103. RefundDesc: p.RefundDesc,
  104. NotifyURL: p.NotifyURL,
  105. }
  106. rawRet, err := util.PostXMLWithTLS(refundGateway, req, p.RootCa, refund.MchID)
  107. if err != nil {
  108. return
  109. }
  110. err = xml.Unmarshal(rawRet, &rsp)
  111. if err != nil {
  112. return
  113. }
  114. if rsp.ReturnCode == "SUCCESS" {
  115. if rsp.ResultCode == "SUCCESS" {
  116. err = nil
  117. return
  118. }
  119. err = fmt.Errorf("refund error, errcode=%s,errmsg=%s", rsp.ErrCode, rsp.ErrCodeDes)
  120. return
  121. }
  122. err = fmt.Errorf("[msg : xmlUnmarshalError] [rawReturn : %s] [sign : %s]", string(rawRet), sign)
  123. return
  124. }