golang 實現微信支付

微信 v3

推薦使用 v3 接口,官方在 v3 接口實現未覆蓋或 gopay 未開發的接口,還繼續用 v2 接口,歡迎參與完善 v3 接口。

1、初始化微信 v3 客戶端並做配置

注意:v3 版本接口持續增加中,不支持沙箱支付,測試請用 1 分錢測試法

具體 API 使用介紹,請參考 gopay/wechat/v3/client_test.go

import (
    "github.com/go-pay/gopay/pkg/xlog"
    "github.com/go-pay/gopay/wechat/v3"
)

// NewClientV3 初始化微信客戶端 v3
//    mchid:商戶ID 或者服務商模式的 sp_mchid
//     serialNo:商戶證書的證書序列號
//    apiV3Key:apiV3Key,商戶平臺獲取
//    privateKey:私鑰 apiclient_key.pem 讀取後的內容
client, err = wechat.NewClientV3(MchId, SerialNo, APIv3Key, PrivateKey)
if err != nil {
    xlog.Error(err)
    return
}

// 啓用自動同步返回驗籤,並定時更新微信平臺API證書
err = client.AutoVerifySign()
if err != nil {
    xlog.Error(err)
    return
}

// 打開Debug開關,輸出日誌,默認是關閉的
client.DebugSwitch = gopay.DebugOn

2、API 方法調用及入參

具體參數請根據不同接口查看:微信支付 V3 的 API 字典概覽

import (
    "github.com/go-pay/gopay"
)

expire := time.Now().Add(10 * time.Minute).Format(time.RFC3339)
// 初始化 BodyMap
bm := make(gopay.BodyMap)
bm.Set("sp_appid", "sp_appid").
    Set("sp_mchid", "sp_mchid").
    Set("sub_mchid", "sub_mchid").
    Set("description", "測試Jsapi支付商品").
    Set("out_trade_no", tradeNo).
    Set("time_expire", expire).
    Set("notify_url", "https://www.fmm.ink").
    SetBodyMap("amount", func(bm gopay.BodyMap) {
        bm.Set("total", 1).
            Set("currency", "CNY")
    }).
    SetBodyMap("payer", func(bm gopay.BodyMap) {
        bm.Set("sp_openid", "asdas")
    })

wxRsp, err := client.V3TransactionJsapi(bm)
if err != nil {
    xlog.Error(err)
    return
}

3、下單後,獲取微信小程序支付、APP 支付、JSAPI 支付所需要的 pay sign

小程序調起支付 API:小程序調起支付 API

APP 調起支付 API:APP 調起支付 API

JSAPI 調起支付 API:JSAPI 調起支付 API

// 小程序
applet, err := client.PaySignOfApplet("appid", "prepayid")
// app
app, err := client.PaySignOfApp("appid", "prepayid")
// jsapi
jsapi, err := client.PaySignOfJSAPI("appid", "prepayid")

4、同步返回參數驗籤 Sign、異步通知參數解析和驗籤 Sign、異步通知返回

異步通知請求參數需要先解析,解析出來的結構體或 BodyMap 再驗籤(此處需要注意,http.Request.Body 只能解析一次,如果需要解析前調試,請處理好 Body 複用問題)

Gin Web 框架(推薦)

Echo Web 框架

import (
    "github.com/go-pay/gopay/wechat/v3"
    "github.com/go-pay/gopay/pkg/xlog"
)

// ========同步返回 手動驗籤(如已開啓自動驗籤,則無需手動驗籤操作)========
wxRsp, err := client.V3TransactionJsapi(bm)
if err != nil {
    xlog.Error(err)
    return
}
err = wechat.V3VerifySign(wxRsp.SignInfo.HeaderTimestamp, wxRsp.SignInfo.HeaderNonce, wxRsp.SignInfo.SignBody, wxRsp.SignInfo.HeaderSignature, WxPkContent)
if err != nil {
    xlog.Error(err)
    return
}

// ========異步通知驗籤========
notifyReq, err := wechat.V3ParseNotify()
if err != nil {
    xlog.Error(err)
    return
}
// WxPkContent 是通過 wechat.GetPlatformCerts() 接口向微信獲取的微信平臺公鑰證書內容
err = notifyReq.VerifySign(WxPkContent)
if err != nil {
    xlog.Error(err)
    return
}

// ========異步通知敏感信息解密========
// 普通支付通知解密
result, err := notifyReq.DecryptCipherText(apiV3Key)
// 合單支付通知解密
result, err := notifyReq.DecryptCombineCipherText(apiV3Key)
// 退款通知解密
result, err := notifyReq.DecryptRefundCipherText(apiV3Key)

// ========異步通知應答========
// 退款通知http應答碼爲200且返回狀態碼爲SUCCESS纔會當做商戶接收成功,否則會重試。
// 注意:重試過多會導致微信支付端積壓過多通知而堵塞,影響其他正常通知。

// 此寫法是 gin 框架返回微信的寫法
c.JSON(http.StatusOK, &wechat.V3NotifyRsp{Code: gopay.SUCCESS, Message: "成功"})
// 此寫法是 echo 框架返回微信的寫法
return c.JSON(http.StatusOK, &wechat.V3NotifyRsp{Code: gopay.SUCCESS, Message: "成功"})
import (
    "github.com/go-pay/gopay/wechat/v3"
    "github.com/go-pay/gopay/pkg/xlog"
)

notifyReq, err := wechat.V3ParseNotify()
if err != nil {
    xlog.Error(err)
    return
}

// WxPkContent 是通過 wechat.GetPlatformCerts() 接口向微信獲取的微信平臺公鑰證書內容
err = notifyReq.VerifySign("WxPkContent")
if err != nil {
    xlog.Error(err)
    return
}

// ========異步通知敏感信息解密========
// 普通支付通知解密
result, err := notifyReq.DecryptCipherText(apiV3Key)
// 合單支付通知解密
result, err := notifyReq.DecryptCombineCipherText(apiV3Key)
// 退款通知解密
result, err := notifyReq.DecryptRefundCipherText(apiV3Key)

// ========異步通知應答========
// 退款通知http應答碼爲200且返回狀態碼爲SUCCESS纔會當做商戶接收成功,否則會重試。
// 注意:重試過多會導致微信支付端積壓過多通知而堵塞,影響其他正常通知。

// 此寫法是 gin 框架返回微信的寫法
c.JSON(http.StatusOK, &wechat.V3NotifyRsp{Code: gopay.SUCCESS, Message: "成功"})

// 此寫法是 echo 框架返回微信的寫法
return c.JSON(http.StatusOK, &wechat.V3NotifyRsp{Code: gopay.SUCCESS, Message: "成功"})

5、微信 v3 公共 API(僅部分說明)

import (
    "github.com/go-pay/gopay/wechat/v3"
)

// 獲取微信平臺證書和序列號信息
wechat.GetPlatformCerts()

// 請求參數 敏感信息加密
wechat.V3EncryptText() 或 client.V3EncryptText()

// 返回參數 敏感信息解密
wechat.V3DecryptText() 或 client.V3DecryptText()

// 回調通知敏感信息解密
wechat.V3DecryptNotifyCipherText()
wechat.V3DecryptRefundNotifyCipherText()
wechat.V3DecryptCombineNotifyCipherText()
...

附錄:

微信支付 v3 API

微信 v3 公共 API

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/6plXxL-9pdcv0RW8XjucNA