|
|
|
|
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
|
|
|
|
|
}
|