mirror of
https://gitee.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat.git
synced 2026-03-10 00:13:36 +08:00
docs: 完善文档
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
## 如何在 ASP.NET Core 中与 `IHttpClientFactory` 集成?
|
||||
## 如何与 `IHttpClientFactory` 集成?
|
||||
|
||||
---
|
||||
|
||||
本功能来自于公共组件,请参阅公共组件下的相关文档:
|
||||
|
||||
> [《SKIT.FlurlHttpClient FAQ:如何在 ASP.NET Core 中与 IHttpClientFactory 集成?》](https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient/blob/main/docs/FAQ_IHttpClientFactory.md)
|
||||
> [《SKIT.FlurlHttpClient FAQ:如何与 IHttpClientFactory 集成?》](https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient/blob/main/docs/README.md)
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
本功能来自于公共组件,请参阅公共组件下的相关文档:
|
||||
|
||||
> [《SKIT.FlurlHttpClient FAQ:如何使用拦截器?》](https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient/blob/main/docs/FAQ_Interceptor.md)
|
||||
> [《SKIT.FlurlHttpClient FAQ:如何使用拦截器?》](https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient/blob/main/docs/README.md)
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
本功能来自于公共组件,请参阅公共组件下的相关文档:
|
||||
|
||||
> [《SKIT.FlurlHttpClient FAQ:如何指定 JSON 序列化器?》](https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient/blob/main/docs/FAQ_JsonSerializer.md)
|
||||
> [《SKIT.FlurlHttpClient FAQ:如何指定 JSON 序列化器?》](https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient/blob/main/docs/README.md)
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -26,16 +26,16 @@
|
||||
|
||||
```csharp
|
||||
/* 微信商户平台发来的通知内容 */
|
||||
string callbackJson = "{ ... }";
|
||||
string webhookJson = "{ ... }";
|
||||
/* 将 JSON 反序列化得到通知对象 */
|
||||
/* 你也可以将 WechatTenpayEvent 类型直接绑定到 MVC 模型上,这样就不再需要手动反序列化 */
|
||||
var callbackModel = client.DeserializeEvent(callbackJson);
|
||||
if ("TRANSACTION.SUCCESS".Equals(callbackModel.EventType))
|
||||
var webhookModel = client.DeserializeEvent(webhookJson);
|
||||
if ("TRANSACTION.SUCCESS".Equals(webhookModel.EventType))
|
||||
{
|
||||
/* 根据事件类型,解密得到支付通知敏感数据 */
|
||||
var callbackResource = client.DecryptEventResource<Events.TransactionResource>(callbackModel);
|
||||
string outTradeNumber = callbackResource.OutTradeNumber;
|
||||
string transactionId = callbackResource.TransactionId;
|
||||
var webhookResource = client.DecryptEventResource<Events.TransactionResource>(webhookModel);
|
||||
string outTradeNumber = webhookResource.OutTradeNumber;
|
||||
string transactionId = webhookResource.TransactionId;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -37,11 +37,11 @@
|
||||
|
||||
```csharp
|
||||
bool ret = client.VerifyEventSignature(
|
||||
callbackTimestamp: "微信回调通知中的 Wechatpay-Timestamp 标头",
|
||||
callbackNonce: "微信回调通知中的 Wechatpay-Nonce 标头",
|
||||
callbackBody: "微信回调通知中请求正文",
|
||||
callbackSignature: "微信回调通知中的 Wechatpay-Signature 标头",
|
||||
callbackSerialNumber: "微信回调通知中的 Wechatpay-Serial 标头"
|
||||
webhookTimestamp: "微信回调通知中的 Wechatpay-Timestamp 标头",
|
||||
webhookNonce: "微信回调通知中的 Wechatpay-Nonce 标头",
|
||||
webhookBody: "微信回调通知中请求正文",
|
||||
webhookSignature: "微信回调通知中的 Wechatpay-Signature 标头",
|
||||
webhookSerialNumber: "微信回调通知中的 Wechatpay-Serial 标头"
|
||||
);
|
||||
```
|
||||
|
||||
@@ -51,14 +51,13 @@ bool ret = client.VerifyEventSignature(
|
||||
|
||||
### 调试验签错误:
|
||||
|
||||
由于 `VerifyEventSignature()` 方法内部会 `try-catch` 掉所有异常情况,并直接返回 `false`。为方便开发者在调试阶段排查验签的错误信息,你可以在验证回调通知事件签名时指定接收最后一个 `out` 返回参数,该参数中包含了一些异常的原因和相关堆栈信息。
|
||||
由于 `VerifyEventSignature()` 方法内部会 `try-catch` 掉所有异常情况,并直接返回 `false`。为方便开发者在调试阶段排查验签的错误信息,你可以在验证回调通知事件签名时指定返回值类型为 `ErroredResult` 而非 `Boolean`,该返回值中包含了一些异常的原因和相关堆栈信息。
|
||||
|
||||
```csharp
|
||||
bool ret = client.VerifyEventSignature(timestamp, nonce, body, signature, serialNumber, out Exception error);
|
||||
if (!ret)
|
||||
ErroredResult res = client.VerifyEventSignature(timestamp, nonce, body, signature, serialNumber);
|
||||
if (!res.Result)
|
||||
{
|
||||
Console.WriteLine(error);
|
||||
Console.WriteLine(error?.InnerException);
|
||||
Console.WriteLine(res.Error);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -30,10 +30,10 @@ public static class MyFakeClientExtensions
|
||||
if (request is null) throw new ArgumentNullException(nameof(request));
|
||||
|
||||
IFlurlRequest flurlReq = client
|
||||
.CreateRequest(request, HttpMethod.Post, "my-fake-url")
|
||||
.CreateFlurlRequest(request, HttpMethod.Post, "my-fake-url")
|
||||
.SetQueryParam("access_token", request.AccessToken);
|
||||
|
||||
return await client.SendRequestWithJsonAsync<MyFakeResponse>(flurlReq, request, cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<MyFakeResponse>(flurlReq, request, cancellationToken);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -82,7 +82,7 @@ var options = new WechatTenpayClientOptions()
|
||||
// 其他配置项略
|
||||
AutoEncryptRequestSensitiveProperty = true
|
||||
};
|
||||
var client = new WechatTenpayClient(options);
|
||||
var client = WechatTenpayClientBuilder.Create(options).Build();
|
||||
```
|
||||
|
||||
这样,本库会在实际发出请求前自动为你调用 `EncryptRequestSensitiveProperty()` 方法。
|
||||
@@ -95,7 +95,7 @@ var client = new WechatTenpayClient(options);
|
||||
|
||||
### 通过 `CertificateManager` 管理平台证书信息:
|
||||
|
||||
微信商户平台证书需要通过 API 的方式获取、且可能同时存在多个有效证书,本库提供了一个 `CertificateManager` 类型可用于管理证书信息。
|
||||
微信商户平台证书需要通过 API 的方式获取、且可能同时存在多个有效证书,本库提供了一个 `ICertificateManager` 接口可用于管理证书信息。
|
||||
|
||||
你可以在构造得到 `WechatTenpayClient` 对象时指定证书管理器:
|
||||
|
||||
@@ -106,7 +106,7 @@ var options = new WechatTenpayClientOptions()
|
||||
// 其他配置项略
|
||||
PlatformCertificateManager = manager
|
||||
};
|
||||
var client = new WechatTenpayClient(options);
|
||||
var client = WechatTenpayClientBuilder.Create(options).Build();
|
||||
```
|
||||
|
||||
> 注:`InMemoryCertificateManager` 是本库内置的基于内存实现的证书管理器;你也可自行继承并实现一个 `CertificateManager`,例如利用数据库或 Redis 等方式存取证书信息。
|
||||
@@ -142,7 +142,7 @@ client.EncryptRequestSensitiveProperty(request);
|
||||
```csharp
|
||||
using StackExchange.Redis;
|
||||
|
||||
public class RedisCertificateManager : CertificateManager
|
||||
public class RedisCertificateManager : ICertificateManager
|
||||
{
|
||||
private const string REDIS_KEY_PREFIX = "wxpaypc-";
|
||||
|
||||
@@ -184,7 +184,7 @@ public class RedisCertificateManager : CertificateManager
|
||||
};
|
||||
}
|
||||
|
||||
public override IEnumerable<CertificateEntry> AllEntries()
|
||||
public IEnumerable<CertificateEntry> AllEntries()
|
||||
{
|
||||
// 生产环境中不应该使用 Redis KEYS 命令,这里代码仅作参考
|
||||
// 你可以使用 SCAN + CURSOR 来实现类似功能
|
||||
@@ -203,7 +203,7 @@ public class RedisCertificateManager : CertificateManager
|
||||
return Array.Empty<CertificateEntry>();
|
||||
}
|
||||
|
||||
public override void AddEntry(CertificateEntry entry)
|
||||
public void AddEntry(CertificateEntry entry)
|
||||
{
|
||||
string key = GenerateRedisKey(serialNumber);
|
||||
HashEntry[] values = ConvertCertificateEntryToHashEntries(entry);
|
||||
@@ -211,7 +211,7 @@ public class RedisCertificateManager : CertificateManager
|
||||
Connection.GetDatabase().KeyExpire(key, entry.ExpireTime - DateTimeOffset.Now);
|
||||
}
|
||||
|
||||
public override CertificateEntry? GetEntry(string serialNumber)
|
||||
public CertificateEntry? GetEntry(string serialNumber)
|
||||
{
|
||||
string key = GenerateRedisKey(serialNumber);
|
||||
HashEntry[] values = Connection.GetDatabase().HashGetAll(key);
|
||||
@@ -223,7 +223,7 @@ public class RedisCertificateManager : CertificateManager
|
||||
return null;
|
||||
}
|
||||
|
||||
public override bool RemoveEntry(string serialNumber)
|
||||
public bool RemoveEntry(string serialNumber)
|
||||
{
|
||||
string key = GenerateRedisKey(serialNumber);
|
||||
return Connection.GetDatabase().KeyDelete(key);
|
||||
|
||||
@@ -45,7 +45,7 @@ var options = new WechatTenpayClientOptions()
|
||||
{
|
||||
AutoDecryptResponseSensitiveProperty = true
|
||||
};
|
||||
var client = new WechatTenpayClient(options);
|
||||
var client = WechatTenpayClientBuilder.Create(options).Build();
|
||||
```
|
||||
|
||||
这样,本库会在实际收到响应后自动为你调用 `DecryptResponseSensitiveProperty()` 方法。
|
||||
|
||||
@@ -60,14 +60,13 @@ bool ret = client.VerifyResponseSignature(response);
|
||||
|
||||
### 调试验签错误:
|
||||
|
||||
由于 `VerifyResponseSignature()` 方法内部会 `try-catch` 掉所有异常情况,并直接返回 `false`。为方便开发者在调试阶段排查验签的错误信息,你可以在验证响应签名时指定接收最后一个 `out` 返回参数,该参数中包含了一些异常的原因和相关堆栈信息。
|
||||
由于 `VerifyResponseSignature()` 方法内部会 `try-catch` 掉所有异常情况,并直接返回 `false`。为方便开发者在调试阶段排查验签的错误信息,你可以在验证响应签名时指定返回值类型为 `ErroredResult` 而非 `Boolean`,该返回值中包含了一些异常的原因和相关堆栈信息。
|
||||
|
||||
```csharp
|
||||
bool ret = client.VerifyResponseSignature(response, out Exception error);
|
||||
if (!ret)
|
||||
ErroredResult res = client.VerifyResponseSignature(response);
|
||||
if (!res.Result)
|
||||
{
|
||||
Console.WriteLine(error);
|
||||
Console.WriteLine(error?.InnerException);
|
||||
Console.WriteLine(res.Error);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ var options = new WechatTenpayClientOptions()
|
||||
// 其他配置项略
|
||||
SignScheme = Constants.SignSchemes.WECHATPAY2_SM2_WITH_SM3
|
||||
};
|
||||
var client = new WechatTenpayClient(options);
|
||||
var client = WechatTenpayClientBuilder.Create(options).Build();
|
||||
```
|
||||
|
||||
接着,在获取平台证书时,需指定证书的算法类型:
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
|
||||
## 快速入门
|
||||
|
||||
> [!IMPORTANT]
|
||||
> 此目录下的文档适用于 v3.x 版本的模块。如果你正在使用 2.x 版本,请移步至 GitHub/Gitee 的已归档分支。
|
||||
|
||||
### 安装:
|
||||
|
||||
提示:如果你使用 Visual Studio NuGet 管理器图形化界面,请在搜索结果中勾选“**包括预发行版**”。
|
||||
@@ -33,7 +36,6 @@
|
||||
### 初始化:
|
||||
|
||||
```csharp
|
||||
using SKIT.FlurlHttpClient.Wechat;
|
||||
using SKIT.FlurlHttpClient.Wechat.TenpayV3;
|
||||
using SKIT.FlurlHttpClient.Wechat.TenpayV3.Settings;
|
||||
|
||||
@@ -46,7 +48,7 @@ var options = new WechatTenpayClientOptions()
|
||||
MerchantCertificatePrivateKey = "-----BEGIN PRIVATE KEY-----微信商户证书私钥,即 `apiclient_key.pem` 文件内容-----END PRIVATE KEY-----",
|
||||
PlatformCertificateManager = manager // 平台证书管理器的具体用法请参阅下文的基础用法与加密、验签有关的章节
|
||||
};
|
||||
var client = new WechatTenpayClient(options);
|
||||
var client = WechatTenpayClientBuilder.Create(options).Build();
|
||||
```
|
||||
|
||||
### 请求 & 响应:
|
||||
@@ -88,7 +90,7 @@ else
|
||||
|
||||
## 基础用法
|
||||
|
||||
- [如何快速找到需要调用的 API 模型类名 / 方法名(附完整 API 对照表)?](./Basic_ModelDefinition.md)
|
||||
- ⭐ [如何快速找到需要调用的 API 模型类名 / 方法名(附完整 API 对照表)?](./Basic_ModelDefinition.md)
|
||||
|
||||
- [如何查看商户证书序列号?](./Basic_CertificateSerialNumber.md)
|
||||
|
||||
@@ -102,7 +104,7 @@ else
|
||||
|
||||
- [如何验证回调通知事件签名?](./Basic_EventSignatureVerification.md)
|
||||
|
||||
- [如何生成客户端(JSAPI、App、小程序等)所需的参数及二次签名?](./Basic_Parameters.md)
|
||||
- ⭐ [如何生成客户端(JSAPI、App、小程序等)所需的参数及二次签名?](./Basic_Parameters.md)
|
||||
|
||||
- [如何自定义额外的 API 接口?](./Basic_Extensions.md)
|
||||
|
||||
@@ -112,7 +114,7 @@ else
|
||||
|
||||
## 高级技巧
|
||||
|
||||
- [如何在 ASP.NET Core 中与 `IHttpClientFactory` 集成?](./Advanced_IHttpClientFactory.md)
|
||||
- [如何与 `IHttpClientFactory` 集成?](./Advanced_IHttpClientFactory.md)
|
||||
|
||||
- [如何指定 JSON 序列化器?](./Advanced_JsonSerializer.md)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user