package lib import ( "context" "encoding/json" "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/jsapi" "github.com/wechatpay-apiv3/wechatpay-go/services/payments/native" "github.com/wechatpay-apiv3/wechatpay-go/utils" "io/ioutil" "log" "net/http" "time" ) type WechatPay struct { AppId string //公众号AppID MchID string //商户号 MchCertificateSerialNumber string //商户证书序列号 MchAPIv3Key string //商户API V3密钥 MchPrivateKey string //商户私钥 NotifyUrl string //回调地址 timeExpire time.Time //订单过期时间 Client *core.Client //client Ctx context.Context } func NewWechatPay(appId, mchID, mchCertificateSerialNumber, mchAPIv3Key, mchPrivateKey, notifyUrl string) (*WechatPay, error) { wp := &WechatPay{ AppId: appId, MchID: mchID, MchCertificateSerialNumber: mchCertificateSerialNumber, MchAPIv3Key: mchAPIv3Key, MchPrivateKey: mchPrivateKey, NotifyUrl: notifyUrl, timeExpire: time.Now().Add(2 * time.Hour), } // 使用 utils 提供的函数从私钥的文本内容中加载商户私钥,商户私钥会用来生成请求的签名 privateKey, err := utils.LoadPrivateKey(mchPrivateKey) if err != nil { return nil, err } ctx := context.Background() // 使用商户私钥等初始化 client,并使它具有自动定时获取微信支付平台证书的能力 opts := []core.ClientOption{ option.WithWechatPayAutoAuthCipher(mchID, mchCertificateSerialNumber, privateKey, mchAPIv3Key), } client, err := core.NewClient(ctx, opts...) if err != nil { return nil, err } wp.Client = client wp.Ctx = ctx return wp, nil } // native支付下单 func (this *WechatPay) NativePayPreOrder(amount int64, description, orderSn string) (string, error) { svc := native.NativeApiService{Client: this.Client} resp, result, err := svc.Prepay(this.Ctx, native.PrepayRequest{ Appid: core.String(this.AppId), Mchid: core.String(this.MchID), Description: core.String(description), OutTradeNo: core.String(orderSn), TimeExpire: core.Time(this.timeExpire), NotifyUrl: core.String(this.NotifyUrl), Amount: &native.Amount{ Currency: core.String("CNY"), Total: core.Int64(amount), }, }, ) if err != nil { return "", err } // 处理返回结果 log.Println(resp, result) return *resp.CodeUrl, nil } // jsapi支付下单 func (this *WechatPay) JsApiPreOrder(openId string, amount int64, description, orderSn string) (string, error) { svc := jsapi.JsapiApiService{Client: this.Client} resp, result, err := svc.PrepayWithRequestPayment(this.Ctx, jsapi.PrepayRequest{ Appid: core.String(this.AppId), Mchid: core.String(this.MchID), Description: core.String(description), OutTradeNo: core.String(orderSn), TimeExpire: core.Time(this.timeExpire), NotifyUrl: core.String(this.NotifyUrl), Amount: &jsapi.Amount{ Currency: core.String("CNY"), Total: core.Int64(amount), }, Payer: &jsapi.Payer{ Openid: core.String(openId), }, }, ) if err != nil { return "", err } // 处理返回结果 log.Println(resp, result) if err != nil { return "", err } respBody, err := json.Marshal(map[string]interface{}{ "prepayId": resp.PrepayId, "appId": resp.Appid, "timeStamp": resp.TimeStamp, "nonceStr": resp.NonceStr, //随机串 "package": resp.Package, "signType": resp.SignType, //微信签名方式: "paySign": resp.PaySign, //微信签名 }) return string(respBody), nil } // native支付查询 func (this *WechatPay) NativePayQueryOrder(orderSn string) (string, string, error) { svc := native.NativeApiService{Client: this.Client} resp, result, err := svc.QueryOrderByOutTradeNo(this.Ctx, native.QueryOrderByOutTradeNoRequest{ OutTradeNo: core.String(orderSn), Mchid: core.String(this.MchID), }, ) if err != nil { return "", "", err } body, _ := ioutil.ReadAll(result.Response.Body) return string(body), *resp.TradeState, nil } // jsapi支付查询 func (this *WechatPay) JsApiQueryOrder(orderSn string) (string, string, error) { svc := jsapi.JsapiApiService{Client: this.Client} resp, result, err := svc.QueryOrderById(this.Ctx, jsapi.QueryOrderByIdRequest{ TransactionId: core.String(orderSn), Mchid: core.String(this.MchID), }, ) if err != nil { return "", "", err } body, _ := ioutil.ReadAll(result.Response.Body) return string(body), *resp.TradeState, nil } // 解密回调 func (this *WechatPay) ParseNotifyRequest(request *http.Request) (map[string]interface{}, error) { ctx := context.Background() content := make(map[string]interface{}) // 1. 使用 `RegisterDownloaderWithPrivateKey` 注册下载器 // 使用 utils 提供的函数从私钥的文本内容中加载商户私钥,商户私钥会用来生成请求的签名 mchPrivateKey, err := utils.LoadPrivateKey(this.MchPrivateKey) if err != nil { return content, err } err = downloader.MgrInstance().RegisterDownloaderWithPrivateKey(ctx, mchPrivateKey, this.MchCertificateSerialNumber, this.MchID, this.MchAPIv3Key) if err != nil { return content, err } // 2. 获取商户号对应的微信支付平台证书访问器 certificateVisitor := downloader.MgrInstance().GetCertificateVisitor(this.MchID) // 3. 使用证书访问器初始化 `notify.Handler` handler := notify.NewNotifyHandler(this.MchAPIv3Key, verifiers.NewSHA256WithRSAVerifier(certificateVisitor)) notifyReq, err := handler.ParseNotifyRequest(ctx, request, &content) log.Println(notifyReq, content) return content, nil }