package services import ( "context" "encoding/json" "errors" "fmt" "github.com/wechatpay-apiv3/wechatpay-go/core" "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" payUtils "github.com/wechatpay-apiv3/wechatpay-go/utils" "hongze/hongze_web_mfyx/models" "hongze/hongze_web_mfyx/models/order" "hongze/hongze_web_mfyx/utils" "log" "time" ) const ( MchPKFileName = "../hongze_mfyx/utils/cert/apiclient_key.pem" Mchid = "1624495680" MchCertificateSerialNumber = "5ED2719CFAE5205763034AD80BF4B8A33533C418" MchAPIv3Key = "W1tbnzQrzQ7yRRNuQCIHjis8dgdasKVX" ) // 微信商户建立连接 func getWechatClient() (context.Context, *core.Client, error) { // 使用 utils 提供的函数从本地文件中加载商户私钥,商户私钥会用来生成请求的签名 mchPrivateKey, err := payUtils.LoadPrivateKeyWithPath(MchPKFileName) if err != nil { log.Print("load merchant private key error") return nil, nil, err } ctx := context.Background() // 使用商户私钥等初始化 client,并使它具有自动定时获取微信支付平台证书的能力 opts := []core.ClientOption{ option.WithWechatPayAutoAuthCipher(Mchid, MchCertificateSerialNumber, mchPrivateKey, MchAPIv3Key), } client, err := core.NewClient(ctx, opts...) if err != nil { log.Printf("new wechat pay client err:%s", err) return nil, nil, err } return ctx, client, nil } // 生成预支付交易单 func ExampleJsapiApiServicePrepay(orderDetail *order.CygxOrder, unionId string) (JsapiApiResp order.PrepayWithRequestPaymentResponse, err error) { //var err error defer func() { if err != nil { fmt.Println(err) go utils.SendAlarmMsg(fmt.Sprint("生成预支付交易单失败 ExampleJsapiApiServicePrepay, err:", err.Error(), "unionId:", unionId), 2) } }() userRecord, e := models.GetUserRecordByUnionId(unionId) if e != nil && e.Error() != utils.ErrNoRow() { err = errors.New("GetUserRecordByUnionId, Err: " + e.Error()) return } ctx, client, err := getWechatClient() if err != nil { log.Printf("getWechatClientt err:%s", err) return } svc := jsapi.JsapiApiService{Client: client} // 得到prepay_id,以及调起支付所需的参数和签名 resp, _, err := svc.PrepayWithRequestPayment(ctx, jsapi.PrepayRequest{ Appid: core.String(utils.WxAppId), Mchid: core.String(Mchid), Description: core.String(orderDetail.SourceTitle), OutTradeNo: core.String(orderDetail.OrderCode), Attach: core.String(""), NotifyUrl: core.String(utils.WxPayJsapiNotifyUrl), Amount: &jsapi.Amount{ Total: core.Int64(int64(orderDetail.OrderMoney * 100)), // 分 }, Payer: &jsapi.Payer{ Openid: core.String(userRecord.OpenId), }, }, ) JsapiApiResp.PrepayId = *resp.PrepayId JsapiApiResp.Appid = *resp.Appid JsapiApiResp.TimeStamp = *resp.TimeStamp JsapiApiResp.NonceStr = *resp.NonceStr JsapiApiResp.Package = *resp.Package JsapiApiResp.SignType = *resp.SignType JsapiApiResp.PaySign = *resp.PaySign return } //func init() { // ExampleNativeApiService_Prepay() //} func ExampleNativeApiServicePrepay(orderDetail *order.CygxOrder) (codeUrl string, err error) { defer func() { if err != nil { fmt.Println(err) go utils.SendAlarmMsg(fmt.Sprint("生成预支付交易单失败 ExampleNativeApiServicePrepay, err:", err.Error(), "OrderCode:", orderDetail.OrderCode), 2) } }() //如果是试用卡,商品名称就显示日卡月卡,如果是单场付费就显示,单场活动名称 if orderDetail.OrderType == 1 { orderDetail.SourceTitle = "畅读" + orderDetail.GoodsName } ctx, client, _ := getWechatClient() svc := native.NativeApiService{Client: client} resp, _, err := svc.Prepay(ctx, native.PrepayRequest{ Appid: core.String(utils.WxAppId), Mchid: core.String(Mchid), Description: core.String(orderDetail.SourceTitle), OutTradeNo: core.String(orderDetail.OutTradeNo), TimeExpire: core.Time(time.Now().Add(10 * time.Minute)), Attach: core.String(""), NotifyUrl: core.String(utils.WxPayJsapiNotifyUrl), GoodsTag: core.String(""), SupportFapiao: core.Bool(false), Amount: &native.Amount{ Currency: core.String("CNY"), Total: core.Int64(int64(orderDetail.OrderMoney * 100)), // 分 }, }, ) if err != nil { return } codeUrl = *resp.CodeUrl return } type WechatPayCallback struct { MchID string `json:"mchid"` AppID string `json:"appid"` OutTradeNo string `json:"out_trade_no"` TransactionID string `json:"transaction_id"` TradeType string `json:"trade_type"` TradeState string `json:"trade_state"` TradeStateDesc string `json:"trade_state_desc"` BankType string `json:"bank_type"` Attach string `json:"attach"` SuccessTime time.Time `json:"success_time"` Payer struct { OpenID string `json:"openid"` } `json:"payer"` Amount struct { Total int `json:"total"` PayerTotal int `json:"payer_total"` Currency string `json:"currency"` PayerCurrency string `json:"payer_currency"` } `json:"amount"` } // 微信支付回调内容解密 func WxDecodeNotify(body []byte) (wechatPayCallback *WechatPayCallback) { var err error defer func() { if err != nil { fmt.Println(err) go utils.SendAlarmMsg(fmt.Sprint("微信支付回调内容解密失败 WxDecodeNotify, err:", err.Error()), 2) } }() var prepaymap map[string]interface{} _ = json.Unmarshal(body, &prepaymap) var prepaymap2 = prepaymap["resource"].(map[string]interface{}) nonce := prepaymap2["nonce"].(string) associatedData := prepaymap2["associated_data"].(string) ciphertext := prepaymap2["ciphertext"].(string) tx, e := payUtils.DecryptAES256GCM(MchAPIv3Key, associatedData, nonce, ciphertext) if e != nil { log.Println(err) return } if e != nil { err = errors.New("DecryptAES256GCM, Err: " + e.Error()) return } var datamap *WechatPayCallback _ = json.Unmarshal([]byte(tx), &datamap) wechatPayCallback = datamap return }