From cc832865dc1777afcb754e64a3a115986254f005 Mon Sep 17 00:00:00 2001 From: jiangyong27 Date: Tue, 5 Nov 2024 22:55:25 +0800 Subject: [PATCH] reverse pay --- weixin/wxpay_partner.go | 94 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 90 insertions(+), 4 deletions(-) diff --git a/weixin/wxpay_partner.go b/weixin/wxpay_partner.go index 0bc50f1..daa5e47 100644 --- a/weixin/wxpay_partner.go +++ b/weixin/wxpay_partner.go @@ -2,10 +2,12 @@ package weixin import ( "bytes" + "crypto/tls" "errors" "fmt" "io" "net/http" + "os" ) var ( @@ -16,11 +18,14 @@ type WxpayPartnerConfig struct { MchId string AppId string ApiKeyV2 string + CertFile string + KeyFile string } type WxpayPartner struct { config *WxpayPartnerConfig stdClient *http.Client + tlsClient *http.Client } type MicroPayRequest struct { @@ -34,11 +39,30 @@ type MicroPayRequest struct { Attach string } +type ReversePayRequest struct { + SubMchId string + SubAppId string + OutTradeNo string +} + func NewWxpayPartner(cfg *WxpayPartnerConfig) *WxpayPartner { - return &WxpayPartner{ + if cfg.MchId != "" { + + } + c := &WxpayPartner{ config: cfg, stdClient: &http.Client{}, } + var err error + if cfg.KeyFile != "" && cfg.CertFile != "" { + certBody, _ := os.ReadFile(cfg.CertFile) + keyBody, _ := os.ReadFile(cfg.KeyFile) + c.tlsClient, err = c.withCert(certBody, keyBody) + if err != nil { + panic(err) + } + } + return c } func (p *WxpayPartner) MicroPay(req *MicroPayRequest) error { @@ -67,7 +91,7 @@ func (p *WxpayPartner) MicroPay(req *MicroPayRequest) error { params.Set("sign", params.SignMd5(p.config.ApiKeyV2)) reqUrl := "https://api.mch.weixin.qq.com/pay/micropay" - body, err := p.post(reqUrl, params) + body, err := p.post(reqUrl, params, false) if err != nil { return err } @@ -88,11 +112,73 @@ func (p *WxpayPartner) MicroPay(req *MicroPayRequest) error { return nil } +func (p *WxpayPartner) Reverse(req *ReversePayRequest) error { + params := make(Params) + params.Set("appid", p.config.AppId) + params.Set("mch_id", p.config.MchId) + params.Set("sub_mch_id", req.SubMchId) + params.Set("nonce_str", randomStr(32)) + params.Set("out_trade_no", req.OutTradeNo) + + if req.SubAppId != "" { + params.Set("sub_appid", req.SubAppId) + } + + params.Set("sign", params.SignMd5(p.config.ApiKeyV2)) + reqUrl := "https://api.mch.weixin.qq.com/secapi/pay/reverse" + body, err := p.post(reqUrl, params, true) + if err != nil { + return err + } + result := make(Params) + result.Decode(body) + + if result.GetString("return_code") != "SUCCESS" { + return errors.New(string(body)) + } + + if result.GetString("result_code") != "SUCCESS" { + if result.GetString("err_code") == "USERPAYING" { + return ErrUserPaying + } + return fmt.Errorf("%s:%s", + result.GetString("err_code"), result.GetString("err_code_des")) + } + return nil +} + +// 附着商户证书 +func (c *WxpayPartner) withCert(cert, key []byte) (*http.Client, error) { + tlsCert, err := tls.X509KeyPair(cert, key) + if err != nil { + return nil, err + } + + conf := &tls.Config{ + Certificates: []tls.Certificate{tlsCert}, + } + trans := &http.Transport{ + TLSClientConfig: conf, + } + + return &http.Client{ + Transport: trans, + }, nil + +} + // 发送请求 -func (c *WxpayPartner) post(url string, params Params) ([]byte, error) { +func (c *WxpayPartner) post(url string, params Params, tls bool) ([]byte, error) { var httpc *http.Client - httpc = c.stdClient + if tls { + if c.tlsClient == nil { + return nil, errors.New("tls wepay is not initialized") + } + httpc = c.tlsClient + } else { + httpc = c.stdClient + } buf := bytes.NewBuffer(params.Encode()) resp, err := httpc.Post(url, "application/xml; charset=utf-8", buf)