Przeglądaj źródła

修改退款 bug 及增加付款到零钱的支付 (#373)

* fix refund bug and add transfer to wallet support

* fmt code

* fix golangci-lint

* fix golangci-lint
baiyuxiong 5 lat temu
rodzic
commit
ad3cc913b0
2 zmienionych plików z 149 dodań i 2 usunięć
  1. 11 2
      pay/refund/refund.go
  2. 138 0
      pay/transfer/transfer_wallet.go

+ 11 - 2
pay/refund/refund.go

@@ -24,6 +24,7 @@ func NewRefund(cfg *config.Config) *Refund {
 //Params 调用参数
 type Params struct {
 	TransactionID string
+	OutTradeNo    string
 	OutRefundNo   string
 	TotalFee      string
 	RefundFee     string
@@ -39,7 +40,8 @@ type request struct {
 	NonceStr      string `xml:"nonce_str"`
 	Sign          string `xml:"sign"`
 	SignType      string `xml:"sign_type,omitempty"`
-	TransactionID string `xml:"transaction_id"`
+	TransactionID string `xml:"transaction_id,omitempty"`
+	OutTradeNo    string `xml:"out_trade_no,omitempty"`
 	OutRefundNo   string `xml:"out_refund_no"`
 	TotalFee      string `xml:"total_fee"`
 	RefundFee     string `xml:"refund_fee"`
@@ -83,7 +85,12 @@ func (refund *Refund) Refund(p *Params) (rsp Response, err error) {
 	param["refund_fee"] = p.RefundFee
 	param["total_fee"] = p.TotalFee
 	param["sign_type"] = util.SignTypeMD5
-	param["transaction_id"] = p.TransactionID
+	if p.TransactionID != "" {
+		param["transaction_id"] = p.TransactionID
+	}
+	if p.OutTradeNo != "" {
+		param["out_trade_no"] = p.OutTradeNo
+	}
 	if p.NotifyURL != "" {
 		param["notify_url"] = p.NotifyURL
 	}
@@ -101,9 +108,11 @@ func (refund *Refund) Refund(p *Params) (rsp Response, err error) {
 		SignType:      util.SignTypeMD5,
 		TransactionID: p.TransactionID,
 		OutRefundNo:   p.OutRefundNo,
+		OutTradeNo:    p.OutTradeNo,
 		TotalFee:      p.TotalFee,
 		RefundFee:     p.RefundFee,
 		RefundDesc:    p.RefundDesc,
+		NotifyURL:     p.NotifyURL,
 	}
 	rawRet, err := util.PostXMLWithTLS(refundGateway, req, p.RootCa, refund.MchID)
 	if err != nil {

+ 138 - 0
pay/transfer/transfer_wallet.go

@@ -0,0 +1,138 @@
+package transfer
+
+import (
+	"encoding/xml"
+	"fmt"
+	"strconv"
+
+	"github.com/silenceper/wechat/v2/pay/config"
+	"github.com/silenceper/wechat/v2/util"
+)
+
+// 付款到零钱
+// https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2
+var walletTransferGateway = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers"
+
+// Transfer struct extends context
+type Transfer struct {
+	*config.Config
+}
+
+// NewTransfer return an instance of Transfer package
+func NewTransfer(cfg *config.Config) *Transfer {
+	transfer := Transfer{cfg}
+	return &transfer
+}
+
+//Params 调用参数
+type Params struct {
+	DeviceInfo     string
+	PartnerTradeNo string
+	OpenID         string
+	CheckName      bool
+	ReUserName     string
+	Amount         int
+	Desc           string
+	SpbillCreateIP string
+	RootCa         string //ca证书
+}
+
+//request 接口请求参数
+type request struct {
+	AppID          string `xml:"mch_appid"`
+	MchID          string `xml:"mchid"`
+	NonceStr       string `xml:"nonce_str"`
+	Sign           string `xml:"sign"`
+	DeviceInfo     string `xml:"device_info,omitempty"`
+	PartnerTradeNo string `xml:"partner_trade_no"`
+	OpenID         string `xml:"openid"`
+	CheckName      string `xml:"check_name"`
+	ReUserName     string `xml:"re_user_name,omitempty"`
+	Amount         int    `xml:"amount"`
+	Desc           string `xml:"desc"`
+	SpbillCreateIP string `xml:"spbill_create_ip,omitempty"`
+}
+
+//Response 接口返回
+type Response struct {
+	ReturnCode     string `xml:"return_code"`
+	ReturnMsg      string `xml:"return_msg"`
+	AppID          string `xml:"appid,omitempty"`
+	MchID          string `xml:"mch_id,omitempty"`
+	DeviceInfo     string `xml:"device_info,omitempty"`
+	NonceStr       string `xml:"nonce_str,omitempty"`
+	ResultCode     string `xml:"result_code,omitempty"`
+	ErrCode        string `xml:"err_code,omitempty"`
+	ErrCodeDes     string `xml:"err_code_des,omitempty"`
+	PartnerTradeNo string `xml:"partner_trade_no"`
+	PaymentNo      string `xml:"payment_no"`
+	PaymentTime    string `xml:"payment_time"`
+}
+
+//WalletTransfer 付款到零钱
+func (transfer *Transfer) WalletTransfer(p *Params) (rsp Response, err error) {
+	nonceStr := util.RandomStr(32)
+	param := make(map[string]string)
+	param["mch_appid"] = transfer.AppID
+	param["mchid"] = transfer.MchID
+	param["nonce_str"] = nonceStr
+	param["partner_trade_no"] = p.PartnerTradeNo
+	param["openid"] = p.OpenID
+	param["amount"] = strconv.Itoa(p.Amount)
+	param["desc"] = p.Desc
+	if p.DeviceInfo != "" {
+		param["device_info"] = p.DeviceInfo
+	}
+	if p.CheckName {
+		param["check_name"] = "FORCE_CHECK"
+		param["re_user_name"] = p.ReUserName
+	} else {
+		param["check_name"] = "NO_CHECK"
+	}
+	if p.SpbillCreateIP != "" {
+		param["spbill_create_ip"] = p.SpbillCreateIP
+	}
+
+	sign, err := util.ParamSign(param, transfer.Key)
+	if err != nil {
+		return
+	}
+
+	req := request{
+		AppID:          transfer.AppID,
+		MchID:          transfer.MchID,
+		NonceStr:       nonceStr,
+		Sign:           sign,
+		DeviceInfo:     p.DeviceInfo,
+		PartnerTradeNo: p.PartnerTradeNo,
+		OpenID:         p.OpenID,
+		Amount:         p.Amount,
+		Desc:           p.Desc,
+		SpbillCreateIP: p.SpbillCreateIP,
+	}
+	if p.CheckName {
+		req.CheckName = "FORCE_CHECK"
+		req.ReUserName = p.ReUserName
+	} else {
+		req.CheckName = "NO_CHECK"
+	}
+
+	rawRet, err := util.PostXMLWithTLS(walletTransferGateway, req, p.RootCa, transfer.MchID)
+	if err != nil {
+		return
+	}
+	err = xml.Unmarshal(rawRet, &rsp)
+	if err != nil {
+		return
+	}
+	if rsp.ReturnCode == "SUCCESS" {
+		if rsp.ResultCode == "SUCCESS" {
+			err = nil
+			return
+		}
+		err = fmt.Errorf("transfer error, errcode=%s,errmsg=%s", rsp.ErrCode, rsp.ErrCodeDes)
+		return
+	}
+	err = fmt.Errorf("[msg : xmlUnmarshalError] [rawReturn : %s] [sign : %s]", string(rawRet), sign)
+	return
+}