You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

138 lines
3.9 KiB
Go

package wechat_pay
import (
"context"
"errors"
"fmt"
"github.com/wechatpay-apiv3/wechatpay-go/core"
"github.com/wechatpay-apiv3/wechatpay-go/core/auth/verifiers"
"github.com/wechatpay-apiv3/wechatpay-go/core/downloader"
"github.com/wechatpay-apiv3/wechatpay-go/core/notify"
"github.com/wechatpay-apiv3/wechatpay-go/core/option"
"github.com/wechatpay-apiv3/wechatpay-go/services/payments"
"github.com/wechatpay-apiv3/wechatpay-go/services/payments/jsapi"
"github.com/wechatpay-apiv3/wechatpay-go/utils"
"log"
"net/http"
)
// Config 微信支付配置
type Config struct {
AppID string // 公众号ID
MchID string // 商户号
APIKey string // API密钥
NotifyURL string // 支付回调通知地址
}
// PayService 微信支付服务
type PayService struct {
Client *core.Client
notifyHandler *notify.Handler
appId string
mchid string
}
/*
NewPayService
arg1:
arg2:AppId
arg3:
arg4:APIv3
arg5:
arg6:
*/
func NewPayService(arg1, arg2, arg3, arg4, arg5, arg6 string) *PayService {
// 使用 utils 提供的函数从本地文件中加载商户私钥,商户私钥会用来生成请求的签名
mchPrivateKey, err := utils.LoadPrivateKeyWithPath(arg5)
if err != nil {
log.Fatal("load merchant private key error", err.Error())
}
cert, err := utils.LoadCertificateWithPath(arg6)
if err != nil {
log.Fatal("load merchant private key error", err.Error())
}
fmt.Println("===============")
fmt.Println(cert.SerialNumber.String())
fmt.Println("===============")
ctx := context.Background()
// 使用商户私钥等初始化 client并使它具有自动定时获取微信支付平台证书的能力
opts := []core.ClientOption{
option.WithWechatPayAutoAuthCipher(arg1, arg3, mchPrivateKey, arg4),
}
client, err := core.NewClient(ctx, opts...)
if err != nil {
log.Fatal(err)
}
//err = downloader.MgrInstance().RegisterDownloaderWithPrivateKey(ctx, mchPrivateKey, arg3, arg1, arg4)
certificateVisitor := downloader.MgrInstance().GetCertificateVisitor(arg1)
handler, err := notify.NewRSANotifyHandler(arg4, verifiers.NewSHA256WithRSAVerifier(certificateVisitor))
if err != nil {
log.Fatal(err)
}
if err != nil {
log.Fatal(err)
}
return &PayService{client, handler, arg2, arg1}
}
type PaymentInfo struct {
Description string
Attach string
AmountTotal int64
OpenId string
OutTradeNo string
}
func (p *PayService) CreatePayment(paymentInfo *PaymentInfo) (*jsapi.PrepayWithRequestPaymentResponse, error) {
svc := jsapi.JsapiApiService{Client: p.Client}
resp, result, err := svc.PrepayWithRequestPayment(context.Background(),
jsapi.PrepayRequest{
Appid: core.String(p.appId),
Mchid: core.String(p.mchid),
Description: core.String(paymentInfo.Description),
OutTradeNo: core.String(paymentInfo.OutTradeNo),
Attach: core.String(paymentInfo.Attach),
NotifyUrl: core.String("http://famyun.com/api/order/order_notify"),
Amount: &jsapi.Amount{
Total: core.Int64(paymentInfo.AmountTotal),
},
Payer: &jsapi.Payer{
Openid: core.String(paymentInfo.OpenId),
},
})
if err != nil {
return nil, err
}
if result.Response.StatusCode != 200 {
return nil, errors.New(resp.String())
}
return resp, nil
}
func (p *PayService) CancelPayment(orderId string) error {
svc := jsapi.JsapiApiService{Client: p.Client}
result, err := svc.CloseOrder(context.Background(), jsapi.CloseOrderRequest{
OutTradeNo: core.String(orderId),
Mchid: core.String(p.mchid),
})
if err != nil {
return err
}
if result.Response.StatusCode == 200 {
return nil
} else {
return errors.New("关闭订单失败")
}
}
func (p *PayService) HandlerNotifyRequest(r *http.Request) (*payments.Transaction, error) {
content := new(payments.Transaction)
_, err := p.notifyHandler.ParseNotifyRequest(context.Background(), r, content)
if err != nil {
return nil, err
}
return content, nil
}