218 lines
7.3 KiB
Go
218 lines
7.3 KiB
Go
|
package wechat
|
|||
|
|
|||
|
import (
|
|||
|
"context"
|
|||
|
"crypto/tls"
|
|||
|
"encoding/xml"
|
|||
|
"errors"
|
|||
|
"fmt"
|
|||
|
|
|||
|
"github.com/go-pay/gopay"
|
|||
|
"github.com/go-pay/gopay/pkg/util"
|
|||
|
)
|
|||
|
|
|||
|
// 统一下单
|
|||
|
// 商户文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
|
|||
|
// 服务商文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi_sl.php?chapter=9_1
|
|||
|
func (w *Client) UnifiedOrder(ctx context.Context, bm gopay.BodyMap) (wxRsp *UnifiedOrderResponse, err error) {
|
|||
|
err = bm.CheckEmptyError("nonce_str", "body", "out_trade_no", "total_fee", "spbill_create_ip", "notify_url", "trade_type")
|
|||
|
if err != nil {
|
|||
|
return nil, err
|
|||
|
}
|
|||
|
var bs []byte
|
|||
|
if w.IsProd {
|
|||
|
bs, err = w.doProdPost(ctx, bm, unifiedOrder, nil)
|
|||
|
} else {
|
|||
|
bm.Set("total_fee", 101)
|
|||
|
bs, err = w.doSanBoxPost(ctx, bm, sandboxUnifiedOrder)
|
|||
|
}
|
|||
|
if err != nil {
|
|||
|
return nil, err
|
|||
|
}
|
|||
|
wxRsp = new(UnifiedOrderResponse)
|
|||
|
if err = xml.Unmarshal(bs, wxRsp); err != nil {
|
|||
|
return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
|
|||
|
}
|
|||
|
return wxRsp, nil
|
|||
|
}
|
|||
|
|
|||
|
// 提交付款码支付
|
|||
|
// 商户文档:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_10&index=1
|
|||
|
// 服务商文档:https://pay.weixin.qq.com/wiki/doc/api/micropay_sl.php?chapter=9_10&index=1
|
|||
|
func (w *Client) Micropay(ctx context.Context, bm gopay.BodyMap) (wxRsp *MicropayResponse, err error) {
|
|||
|
err = bm.CheckEmptyError("nonce_str", "body", "out_trade_no", "total_fee", "spbill_create_ip", "auth_code")
|
|||
|
if err != nil {
|
|||
|
return nil, err
|
|||
|
}
|
|||
|
var bs []byte
|
|||
|
if w.IsProd {
|
|||
|
bs, err = w.doProdPost(ctx, bm, microPay, nil)
|
|||
|
} else {
|
|||
|
bm.Set("total_fee", 1)
|
|||
|
bs, err = w.doSanBoxPost(ctx, bm, sandboxMicroPay)
|
|||
|
}
|
|||
|
if err != nil {
|
|||
|
return nil, err
|
|||
|
}
|
|||
|
wxRsp = new(MicropayResponse)
|
|||
|
if err = xml.Unmarshal(bs, wxRsp); err != nil {
|
|||
|
return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
|
|||
|
}
|
|||
|
return wxRsp, nil
|
|||
|
}
|
|||
|
|
|||
|
// 查询订单
|
|||
|
// 商户文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_2
|
|||
|
// 服务商文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi_sl.php?chapter=9_2
|
|||
|
func (w *Client) QueryOrder(ctx context.Context, bm gopay.BodyMap) (wxRsp *QueryOrderResponse, resBm gopay.BodyMap, err error) {
|
|||
|
err = bm.CheckEmptyError("nonce_str")
|
|||
|
if err != nil {
|
|||
|
return nil, nil, err
|
|||
|
}
|
|||
|
if bm.GetString("out_trade_no") == util.NULL && bm.GetString("transaction_id") == util.NULL {
|
|||
|
return nil, nil, errors.New("out_trade_no and transaction_id are not allowed to be null at the same time")
|
|||
|
}
|
|||
|
var bs []byte
|
|||
|
if w.IsProd {
|
|||
|
bs, err = w.doProdPost(ctx, bm, orderQuery, nil)
|
|||
|
} else {
|
|||
|
bs, err = w.doSanBoxPost(ctx, bm, sandboxOrderQuery)
|
|||
|
}
|
|||
|
if err != nil {
|
|||
|
return nil, nil, err
|
|||
|
}
|
|||
|
wxRsp = new(QueryOrderResponse)
|
|||
|
if err = xml.Unmarshal(bs, wxRsp); err != nil {
|
|||
|
return nil, nil, fmt.Errorf("xml.UnmarshalStruct(%s):%w", string(bs), err)
|
|||
|
}
|
|||
|
resBm = make(gopay.BodyMap)
|
|||
|
if err = xml.Unmarshal(bs, &resBm); err != nil {
|
|||
|
return nil, nil, fmt.Errorf("xml.UnmarshalBodyMap(%s):%w", string(bs), err)
|
|||
|
}
|
|||
|
return wxRsp, resBm, nil
|
|||
|
}
|
|||
|
|
|||
|
// 关闭订单
|
|||
|
// 商户文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_3
|
|||
|
// 服务商文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi_sl.php?chapter=9_3
|
|||
|
func (w *Client) CloseOrder(ctx context.Context, bm gopay.BodyMap) (wxRsp *CloseOrderResponse, err error) {
|
|||
|
err = bm.CheckEmptyError("nonce_str", "out_trade_no")
|
|||
|
if err != nil {
|
|||
|
return nil, err
|
|||
|
}
|
|||
|
var bs []byte
|
|||
|
if w.IsProd {
|
|||
|
bs, err = w.doProdPost(ctx, bm, closeOrder, nil)
|
|||
|
} else {
|
|||
|
bs, err = w.doSanBoxPost(ctx, bm, sandboxCloseOrder)
|
|||
|
}
|
|||
|
if err != nil {
|
|||
|
return nil, err
|
|||
|
}
|
|||
|
wxRsp = new(CloseOrderResponse)
|
|||
|
if err = xml.Unmarshal(bs, wxRsp); err != nil {
|
|||
|
return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
|
|||
|
}
|
|||
|
return wxRsp, nil
|
|||
|
}
|
|||
|
|
|||
|
// 申请退款
|
|||
|
// 注意:请在初始化client时,调用 client 添加证书的相关方法添加证书
|
|||
|
// 商户文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4
|
|||
|
// 服务商文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi_sl.php?chapter=9_4
|
|||
|
func (w *Client) Refund(ctx context.Context, bm gopay.BodyMap) (wxRsp *RefundResponse, resBm gopay.BodyMap, err error) {
|
|||
|
err = bm.CheckEmptyError("nonce_str", "out_refund_no", "total_fee", "refund_fee")
|
|||
|
if err != nil {
|
|||
|
return nil, nil, err
|
|||
|
}
|
|||
|
if bm.GetString("out_trade_no") == util.NULL && bm.GetString("transaction_id") == util.NULL {
|
|||
|
return nil, nil, errors.New("out_trade_no and transaction_id are not allowed to be null at the same time")
|
|||
|
}
|
|||
|
var (
|
|||
|
bs []byte
|
|||
|
tlsConfig *tls.Config
|
|||
|
)
|
|||
|
if w.IsProd {
|
|||
|
if tlsConfig, err = w.addCertConfig(nil, nil, nil); err != nil {
|
|||
|
return nil, nil, err
|
|||
|
}
|
|||
|
bs, err = w.doProdPost(ctx, bm, refund, tlsConfig)
|
|||
|
} else {
|
|||
|
bs, err = w.doSanBoxPost(ctx, bm, sandboxRefund)
|
|||
|
}
|
|||
|
if err != nil {
|
|||
|
return nil, nil, err
|
|||
|
}
|
|||
|
wxRsp = new(RefundResponse)
|
|||
|
if err = xml.Unmarshal(bs, wxRsp); err != nil {
|
|||
|
return nil, nil, fmt.Errorf("xml.UnmarshalStruct(%s):%w", string(bs), err)
|
|||
|
}
|
|||
|
resBm = make(gopay.BodyMap)
|
|||
|
if err = xml.Unmarshal(bs, &resBm); err != nil {
|
|||
|
return nil, nil, fmt.Errorf("xml.UnmarshalBodyMap(%s):%w", string(bs), err)
|
|||
|
}
|
|||
|
return wxRsp, resBm, nil
|
|||
|
}
|
|||
|
|
|||
|
// 查询退款
|
|||
|
// 商户文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_5
|
|||
|
// 服务商文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi_sl.php?chapter=9_5
|
|||
|
func (w *Client) QueryRefund(ctx context.Context, bm gopay.BodyMap) (wxRsp *QueryRefundResponse, resBm gopay.BodyMap, err error) {
|
|||
|
err = bm.CheckEmptyError("nonce_str")
|
|||
|
if err != nil {
|
|||
|
return nil, nil, err
|
|||
|
}
|
|||
|
if bm.GetString("refund_id") == util.NULL && bm.GetString("out_refund_no") == util.NULL && bm.GetString("transaction_id") == util.NULL && bm.GetString("out_trade_no") == util.NULL {
|
|||
|
return nil, nil, errors.New("refund_id, out_refund_no, out_trade_no, transaction_id are not allowed to be null at the same time")
|
|||
|
}
|
|||
|
var bs []byte
|
|||
|
if w.IsProd {
|
|||
|
bs, err = w.doProdPost(ctx, bm, refundQuery, nil)
|
|||
|
} else {
|
|||
|
bs, err = w.doSanBoxPost(ctx, bm, sandboxRefundQuery)
|
|||
|
}
|
|||
|
if err != nil {
|
|||
|
return nil, nil, err
|
|||
|
}
|
|||
|
wxRsp = new(QueryRefundResponse)
|
|||
|
if err = xml.Unmarshal(bs, wxRsp); err != nil {
|
|||
|
return nil, nil, fmt.Errorf("xml.UnmarshalStruct(%s):%w", string(bs), err)
|
|||
|
}
|
|||
|
resBm = make(gopay.BodyMap)
|
|||
|
if err = xml.Unmarshal(bs, &resBm); err != nil {
|
|||
|
return nil, nil, fmt.Errorf("xml.UnmarshalBodyMap(%s):%w", string(bs), err)
|
|||
|
}
|
|||
|
return wxRsp, resBm, nil
|
|||
|
}
|
|||
|
|
|||
|
// 撤销订单
|
|||
|
// 注意:请在初始化client时,调用 client 添加证书的相关方法添加证书
|
|||
|
// 商户文档:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_11&index=3
|
|||
|
// 服务商文档:https://pay.weixin.qq.com/wiki/doc/api/micropay_sl.php?chapter=9_11&index=3
|
|||
|
func (w *Client) Reverse(ctx context.Context, bm gopay.BodyMap) (wxRsp *ReverseResponse, err error) {
|
|||
|
err = bm.CheckEmptyError("nonce_str", "out_trade_no")
|
|||
|
if err != nil {
|
|||
|
return nil, err
|
|||
|
}
|
|||
|
var (
|
|||
|
bs []byte
|
|||
|
tlsConfig *tls.Config
|
|||
|
)
|
|||
|
if w.IsProd {
|
|||
|
if tlsConfig, err = w.addCertConfig(nil, nil, nil); err != nil {
|
|||
|
return nil, err
|
|||
|
}
|
|||
|
bs, err = w.doProdPost(ctx, bm, reverse, tlsConfig)
|
|||
|
} else {
|
|||
|
bs, err = w.doSanBoxPost(ctx, bm, sandboxReverse)
|
|||
|
}
|
|||
|
if err != nil {
|
|||
|
return nil, err
|
|||
|
}
|
|||
|
wxRsp = new(ReverseResponse)
|
|||
|
if err = xml.Unmarshal(bs, wxRsp); err != nil {
|
|||
|
return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
|
|||
|
}
|
|||
|
return wxRsp, nil
|
|||
|
}
|