refund.go 3.4 KB

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