gosdk/weixin/wxpay_partner.go

195 lines
4.0 KiB
Go
Raw Permalink Normal View History

2024-11-05 20:42:13 +08:00
package weixin
import (
"bytes"
2024-11-05 22:55:25 +08:00
"crypto/tls"
2024-11-05 20:42:13 +08:00
"errors"
"fmt"
"io"
"net/http"
2024-11-05 22:55:25 +08:00
"os"
2024-11-05 20:42:13 +08:00
)
var (
ErrUserPaying = errors.New("USERPAYING")
)
type WxpayPartnerConfig struct {
MchId string
AppId string
ApiKeyV2 string
2024-11-05 22:55:25 +08:00
CertFile string
KeyFile string
2024-11-05 20:42:13 +08:00
}
type WxpayPartner struct {
config *WxpayPartnerConfig
stdClient *http.Client
2024-11-05 22:55:25 +08:00
tlsClient *http.Client
2024-11-05 20:42:13 +08:00
}
type MicroPayRequest struct {
SubMchId string
SubAppId string
GoodsName string
OutTradeNo string
TotalFee int64
AuthCode string
ServerIp string
Attach string
}
2024-11-05 22:55:25 +08:00
type ReversePayRequest struct {
SubMchId string
SubAppId string
OutTradeNo string
}
2024-11-05 20:42:13 +08:00
func NewWxpayPartner(cfg *WxpayPartnerConfig) *WxpayPartner {
2024-11-05 22:55:25 +08:00
if cfg.MchId != "" {
}
c := &WxpayPartner{
2024-11-05 20:42:13 +08:00
config: cfg,
stdClient: &http.Client{},
}
2024-11-05 22:55:25 +08:00
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
2024-11-05 20:42:13 +08:00
}
func (p *WxpayPartner) MicroPay(req *MicroPayRequest) 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("body", req.GoodsName)
params.Set("out_trade_no", req.OutTradeNo)
params.Set("total_fee", req.TotalFee)
params.Set("auth_code", req.AuthCode)
if req.ServerIp == "" {
params.Set("spbill_create_ip", "113.248.223.215")
} else {
params.Set("spbill_create_ip", req.ServerIp)
}
if req.Attach != "" {
params.Set("attach", req.Attach)
}
if req.SubAppId != "" {
params.Set("sub_appid", req.SubAppId)
}
params.Set("sign", params.SignMd5(p.config.ApiKeyV2))
reqUrl := "https://api.mch.weixin.qq.com/pay/micropay"
2024-11-05 22:55:25 +08:00
body, err := p.post(reqUrl, params, false)
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 (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)
2024-11-05 20:42:13 +08:00
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
}
2024-11-05 22:55:25 +08:00
// 附着商户证书
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
}
2024-11-05 20:42:13 +08:00
// 发送请求
2024-11-05 22:55:25 +08:00
func (c *WxpayPartner) post(url string, params Params, tls bool) ([]byte, error) {
2024-11-05 20:42:13 +08:00
var httpc *http.Client
2024-11-05 22:55:25 +08:00
if tls {
if c.tlsClient == nil {
return nil, errors.New("tls wepay is not initialized")
}
httpc = c.tlsClient
} else {
httpc = c.stdClient
}
2024-11-05 20:42:13 +08:00
buf := bytes.NewBuffer(params.Encode())
resp, err := httpc.Post(url, "application/xml; charset=utf-8", buf)
if err != nil {
return nil, err
}
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return body, nil
}