transfer_wallet.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. package transfer
  2. import (
  3. "encoding/xml"
  4. "fmt"
  5. "strconv"
  6. "github.com/silenceper/wechat/v2/pay/config"
  7. "github.com/silenceper/wechat/v2/util"
  8. )
  9. // 付款到零钱
  10. // https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2
  11. var walletTransferGateway = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers"
  12. // Transfer struct extends context
  13. type Transfer struct {
  14. *config.Config
  15. }
  16. // NewTransfer return an instance of Transfer package
  17. func NewTransfer(cfg *config.Config) *Transfer {
  18. transfer := Transfer{cfg}
  19. return &transfer
  20. }
  21. //Params 调用参数
  22. type Params struct {
  23. DeviceInfo string
  24. PartnerTradeNo string
  25. OpenID string
  26. CheckName bool
  27. ReUserName string
  28. Amount int
  29. Desc string
  30. SpbillCreateIP string
  31. RootCa string //ca证书
  32. }
  33. //request 接口请求参数
  34. type request struct {
  35. AppID string `xml:"mch_appid"`
  36. MchID string `xml:"mchid"`
  37. NonceStr string `xml:"nonce_str"`
  38. Sign string `xml:"sign"`
  39. DeviceInfo string `xml:"device_info,omitempty"`
  40. PartnerTradeNo string `xml:"partner_trade_no"`
  41. OpenID string `xml:"openid"`
  42. CheckName string `xml:"check_name"`
  43. ReUserName string `xml:"re_user_name,omitempty"`
  44. Amount int `xml:"amount"`
  45. Desc string `xml:"desc"`
  46. SpbillCreateIP string `xml:"spbill_create_ip,omitempty"`
  47. }
  48. //Response 接口返回
  49. type Response struct {
  50. ReturnCode string `xml:"return_code"`
  51. ReturnMsg string `xml:"return_msg"`
  52. AppID string `xml:"appid,omitempty"`
  53. MchID string `xml:"mch_id,omitempty"`
  54. DeviceInfo string `xml:"device_info,omitempty"`
  55. NonceStr string `xml:"nonce_str,omitempty"`
  56. ResultCode string `xml:"result_code,omitempty"`
  57. ErrCode string `xml:"err_code,omitempty"`
  58. ErrCodeDes string `xml:"err_code_des,omitempty"`
  59. PartnerTradeNo string `xml:"partner_trade_no"`
  60. PaymentNo string `xml:"payment_no"`
  61. PaymentTime string `xml:"payment_time"`
  62. }
  63. //WalletTransfer 付款到零钱
  64. func (transfer *Transfer) WalletTransfer(p *Params) (rsp Response, err error) {
  65. nonceStr := util.RandomStr(32)
  66. param := make(map[string]string)
  67. param["mch_appid"] = transfer.AppID
  68. param["mchid"] = transfer.MchID
  69. param["nonce_str"] = nonceStr
  70. param["partner_trade_no"] = p.PartnerTradeNo
  71. param["openid"] = p.OpenID
  72. param["amount"] = strconv.Itoa(p.Amount)
  73. param["desc"] = p.Desc
  74. if p.DeviceInfo != "" {
  75. param["device_info"] = p.DeviceInfo
  76. }
  77. if p.CheckName {
  78. param["check_name"] = "FORCE_CHECK"
  79. param["re_user_name"] = p.ReUserName
  80. } else {
  81. param["check_name"] = "NO_CHECK"
  82. }
  83. if p.SpbillCreateIP != "" {
  84. param["spbill_create_ip"] = p.SpbillCreateIP
  85. }
  86. sign, err := util.ParamSign(param, transfer.Key)
  87. if err != nil {
  88. return
  89. }
  90. req := request{
  91. AppID: transfer.AppID,
  92. MchID: transfer.MchID,
  93. NonceStr: nonceStr,
  94. Sign: sign,
  95. DeviceInfo: p.DeviceInfo,
  96. PartnerTradeNo: p.PartnerTradeNo,
  97. OpenID: p.OpenID,
  98. Amount: p.Amount,
  99. Desc: p.Desc,
  100. SpbillCreateIP: p.SpbillCreateIP,
  101. }
  102. if p.CheckName {
  103. req.CheckName = "FORCE_CHECK"
  104. req.ReUserName = p.ReUserName
  105. } else {
  106. req.CheckName = "NO_CHECK"
  107. }
  108. rawRet, err := util.PostXMLWithTLS(walletTransferGateway, req, p.RootCa, transfer.MchID)
  109. if err != nil {
  110. return
  111. }
  112. err = xml.Unmarshal(rawRet, &rsp)
  113. if err != nil {
  114. return
  115. }
  116. if rsp.ReturnCode == "SUCCESS" {
  117. if rsp.ResultCode == "SUCCESS" {
  118. err = nil
  119. return
  120. }
  121. err = fmt.Errorf("transfer error, errcode=%s,errmsg=%s", rsp.ErrCode, rsp.ErrCodeDes)
  122. return
  123. }
  124. err = fmt.Errorf("[msg : xmlUnmarshalError] [rawReturn : %s] [sign : %s]", string(rawRet), sign)
  125. return
  126. }