緣起
今年公司某個專案需要全面接入微信支付 V3 版 API。起初覺得,2014 年微信支付就已上線了 V3 版 API,這都 2021 年了,就算官方不給力,怎麼著社群也該有幾個造好的 .NET 的輪子了吧?於是興沖沖地到 NuGet 上開始搜尋“微信支付”四個大字,結果……
倒不是沒有現成的輪子,但基本都是隻包含一些簡單 API(如下單、查單、退款等等),與需求不符;偶爾有一些看似封裝全的,點進去一看卻是基於 V2 版 API 的。
沒辦法,自己動手,豐衣足食!
接入了微信支付後想著,既然微信支付都有了,為啥不把公眾號、小程式、企業微信之類的也接入了呢?
於是乎 SKIT.FlurlHttpClient.Wechat
這個專案就誕生了。
專案介紹
SKIT.FlurlHttpClient.Wechat
是一個基於 Flurl.Http
的微信 API HTTP 客戶端。
包含以下特性:
- 支援 .NET Framework 4.6.1+、.NET Standard 2.0+、.NET Core 2.0+、.NET 5。
- 支援 Windows / Linux / macOS 多平臺部署。
- 支援 System.Text.Json(預設)和 Newtonsoft.Json 兩種序列化方式。
- 非同步式程式設計。
- 強型別介面模型。
- 提供攔截器功能。
- 提供微信 API 所需的 MD5、SHA-1、SHA-256、AES、RSA 等演算法工具類。
- 提供 SourceLink,方便專案無原始碼除錯。
- 完整、完善、完全的微信 API 封裝,同時可靈活自行擴充套件。
現有以下模組:
- 公眾平臺(公眾號、小程式、小遊戲、小商店) & 開放平臺模組:
SKIT.FlurlHttpClient.Wechat.Api
- 商戶平臺(微信支付)模組:
SKIT.FlurlHttpClient.Wechat.TenpayV3
- 企業微信(企業號)模組:
SKIT.FlurlHttpClient.Wechat.Work
- 廣告平臺(廣點通)模組:
SKIT.FlurlHttpClient.Wechat.Ads
快速開始
以接入微信支付為例,其他模組的開發流程與之十分類似。完整開發文件請前往倉庫(連結在最下方)閱讀。
安裝:
dotnet add package SKIT.FlurlHttpClient.Wechat.TenpayV3
初始化:
using SKIT.FlurlHttpClient.Wechat;
using SKIT.FlurlHttpClient.Wechat.TenpayV3;
using SKIT.FlurlHttpClient.Wechat.TenpayV3.Settings;
/* 平臺證書管理器,具體用法請參見文件 */
var certManager = new InMemoryCertificateManager();
/* 僅列出必須配置項。也包含一些諸如超時時間、UserAgent 等的配置項 */
var options = new WechatTenpayClientOptions()
{
MerchantId = "微信商戶號",
MerchantV3Secret = "微信商戶 v3 API 金鑰",
MerchantCertSerialNumber = "微信商戶證書序列號",
MerchantCertPrivateKey = "-----BEGIN PRIVATE KEY-----微信商戶證書私鑰-----END PRIVATE KEY-----",
CertificateManager = certManager
};
var client = new WechatTenpayClient(options);
傳送請求:
using SKIT.FlurlHttpClient.Wechat.TenpayV3;
using SKIT.FlurlHttpClient.Wechat.TenpayV3.Models;
/* 以 JSAPI 統一下單介面為例 */
var request = new CreatePayTransactionJsapiRequest()
{
OutTradeNumber = "商戶訂單號",
AppId = "微信 AppId",
Description = "訂單描述",
ExpireTime = DateTimeOffset.Now.AddMinutes(15),
NotifyUrl = "https://example.com",
Amount = new CreatePayTransactionJsapiRequest.Types.Amount()
{
Total = 100
},
Payer = new CreatePayTransactionJsapiRequest.Types.Payer()
{
OpenId = "微信 OpenId"
}
};
var response = await client.ExecuteCreatePayTransactionJsapiAsync(request);
if (response.IsSuccessful())
{
Console.WriteLine("PrepayId:" + response.PrepayId);
}
else
{
Console.WriteLine("HTTP 狀態:" + response.RawStatus);
Console.WriteLine("錯誤程式碼:" + response.ErrorCode);
Console.WriteLine("錯誤描述:" + response.ErrorMessage);
}
驗證響應簽名:
/* 一般情況下可以跳過驗證響應的簽名 */
bool valid = client.VerifyResponseSignature(response);
生成客戶端 JS-SDK 調起支付所需引數:
/* 字典結構,包含客戶端 JS-SDK 調起支付所需的完整引數 */
var paramMap = client.GenerateParametersForJsapiPayRequest(request.AppId, response.PrepayId);
驗籤、解析並解密微信回撥通知中的敏感資訊:
string callbackJson = "{ 微信商戶平臺發來的 JSON 格式的通知內容 }";
string callbackTimestamp = "微信回撥通知中的 Wechatpay-Timestamp 標頭";
string callbackNonce = "微信回撥通知中的 Wechatpay-Nonce 標頭";
string callbackSignature = "微信回撥通知中的 Wechatpay-Signature 標頭";
string callbackSerialNumber = "微信回撥通知中的 Wechatpay-Serial 標頭";
bool valid = client.VerifyEventSignature(callbackTimestamp, callbackNonce, callbackJson, callbackSignature, callbackSerialNumber);
if (valid)
{
/* 將 JSON 反序列化得到通知物件 */
/* 你也可以將 WechatTenpayEvent 型別直接繫結到 MVC 模型上,這樣就不再需要手動反序列化 */
var callbackModel = client.DeserializeEvent(callbackJson);
if ("TRANSACTION.SUCCESS".Equals(callbackModel.EventType))
{
/* 根據事件型別,解密得到支付通知敏感資料 */
var callbackResource = client.DecryptEventResource<Events.TransactionResource>(callbackModel);
string outTradeNumber = callbackResource.OutTradeNumber;
string transactionId = callbackResource.TransactionId;
Console.WriteLine("訂單 {0} 已完成支付,交易單號為 {1}", outTradeNumber, transactionId);
}
}
更多使用說明請閱讀專案倉庫中的開發文件。
專案倉庫中還包含了一個示例專案,以供開發者快速掌握本庫的使用方法。
FAQ
1. Flurl.Http 是什麼?
Flurl.Http
是一個輕量級 HTTP 庫,是 .NET 中最受歡迎擴充套件庫之一,在 NuGet 上的累計下載量超過 1700 萬、日均下載量超過 6 千、GitHub 2.6k Stars(資料統計截至 2021-06-01)。
與另一個流行的 HTTP 庫 RestSharp
相比,Flurl.Http
底層基於 System.Net.Http.HttpClient
,而 RestSharp
底層則基於 System.Net.HttpWebRequest
,前者在多核多執行緒環境下的效能基準測試中表現要遠優於後者,同時也是微軟官方目前推薦的 HTTP 客戶端方案。
2. 本庫與盛派微信 SDK(Senparc.Weixin)有什麼區別?
- 本庫專注於 API 本身的封裝,捎帶提供了一些用於加解密、序列化的工具類,使用更靈活;盛派微信 SDK 提供了大而全的功能,可與 MVC / WebAPI 深度整合。
- 本庫遵循微軟官方推薦的 C# 屬性命名方式(大駝峰命名法)對介面模型進行定義;盛派微信 SDK 提供的是微信介面本身的命名方式(蛇形命名法和小駝峰命名法混雜)。
- 本庫封裝了目前微信官方提供的所有 API;盛派微信 SDK 只提供了常用的 API。
- 本庫只支援微信支付 v3 版 API;盛派微信 SDK 只支援微信支付 v2 版 API(作者開了新坑似乎是想提供 v3 版支援,不過目前只封裝了部分介面,進展還比較緩慢)。原則上微信官方已經停止更新 v2 版 API,現在介面只做日常維護,所以有條件的話還是應該儘快升級。如果你有使用 v2 版 API 的需求(比如企業提現、紅包等幾個尚未提供 v3 版 API 的介面),建議使用盛派微信 SDK。
3. 為什麼不支援 .NET Framework 4.0 / .NET Framework 4.5?
直接原因是本庫的依賴庫最低支援到 .NET Framework 4.6.1。
間接原因是為了支援跨平臺的 .NET Standard 2.0,只能相容到 .NET Framework 4.6.1。
根本原因是微軟官方已於 2016 年 1 月 12 日終止了對 .NET Framework 4.6.1 以下版本的技術支援。也就是說,微軟已經不再為此提供安全更新,在大部分技術合規要求中這一點都是扣分項,所以建議各位開發者目標框架能升級就升級。
倉庫
- GitHub:https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat
- Gitee:https://gitee.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat
以上倉庫地址同步更新,均可接受 Issue 或 Pull Request。