mirror of
https://gitee.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat.git
synced 2025-09-20 02:29:40 +08:00
docs: 完善文档
This commit is contained in:
@@ -129,7 +129,7 @@ client.EncryptRequestSensitiveProperty(request);
|
|||||||
|
|
||||||
上一小节提到,你可自行继承并实现一个 `CertificateManager`,例如利用数据库或 Redis 等方式存取证书信息。
|
上一小节提到,你可自行继承并实现一个 `CertificateManager`,例如利用数据库或 Redis 等方式存取证书信息。
|
||||||
|
|
||||||
下面给出一个利用 Redis 存储的示例代码:
|
下面给出一个利用 Redis 的 HASH 数据结构存储的示例代码:
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
using StackExchange.Redis;
|
using StackExchange.Redis;
|
||||||
@@ -139,41 +139,76 @@ public class RedisCertificateManager : CertificateManager
|
|||||||
{
|
{
|
||||||
private const string REDIS_KEY_PREFIX = "wxpaypc-";
|
private const string REDIS_KEY_PREFIX = "wxpaypc-";
|
||||||
|
|
||||||
protected ConnectionMultiplexer Connection { get; }
|
private readonly ConnectionMultiplexer Connection { get; }
|
||||||
|
|
||||||
public RedisCertificateManager(string connectionString)
|
public RedisCertificateManager(string connectionString)
|
||||||
{
|
{
|
||||||
Connection = ConnectionMultiplexer.Connect(connectionString);
|
Connection = ConnectionMultiplexer.Connect(connectionString);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected string GenerateRedisKey(string serialNumber)
|
private string GenerateRedisKey(string serialNumber)
|
||||||
{
|
{
|
||||||
return $"{REDIS_KEY_PREFIX}{serialNumber}";
|
return $"{REDIS_KEY_PREFIX}{serialNumber}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private CertificateEntry ConvertHashEntriesToCertificateEntry(HashEntry[] values)
|
||||||
|
{
|
||||||
|
if (values == null) throw new ArgumentNullException(nameof(values));
|
||||||
|
|
||||||
|
IDictionary<string, string> map = values.ToDictionary(k => k.Name.ToString(), v => v.Value.ToString());
|
||||||
|
return new CertificateEntry(
|
||||||
|
serialNumber: map[nameof(CertificateEntry.SerialNumber)],
|
||||||
|
certificate: map[nameof(CertificateEntry.Certificate)],
|
||||||
|
effectiveTime: DateTimeOffset.Parse(map[nameof(CertificateEntry.EffectiveTime)]),
|
||||||
|
expireTime: DateTimeOffset.Parse(map[nameof(CertificateEntry.ExpireTime)])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private HashEntry[] ConvertCertificateEntryToHashEntries(CertificateEntry entry)
|
||||||
|
{
|
||||||
|
return new HashEntry[]
|
||||||
|
{
|
||||||
|
new HashEntry(nameof(CertificateEntry.SerialNumber), entry.SerialNumber),
|
||||||
|
new HashEntry(nameof(CertificateEntry.Certificate), entry.Certificate),
|
||||||
|
new HashEntry(nameof(CertificateEntry.EffectiveTime), entry.EffectiveTime.ToString()),
|
||||||
|
new HashEntry(nameof(CertificateEntry.ExpireTime), entry.ExpireTime.ToString())
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
public override IEnumerable<CertificateEntry> AllEntries()
|
public override IEnumerable<CertificateEntry> AllEntries()
|
||||||
{
|
{
|
||||||
// 生产环境中不应该使用 Redis KEYS 命令,这里代码仅作参考
|
// 生产环境中不应该使用 Redis KEYS 命令,这里代码仅作参考
|
||||||
|
// 你可以使用 SCAN + CURSOR 来实现类似功能
|
||||||
RedisKey[] keys = Connection.GetServer().Keys($"{REDIS_KEY_PREFIX}*");
|
RedisKey[] keys = Connection.GetServer().Keys($"{REDIS_KEY_PREFIX}*");
|
||||||
RedisValue[] values = Connection.GetDatabase().StringGet(keys);
|
if (keys.Any())
|
||||||
return values.Where(e => e.HasValue).Select(e => JsonConvert.DeserializeObject<CertificateEntry>(e.ToString()));
|
{
|
||||||
|
Task[] pipelineTasks = keys.Select(key => Connection.GetDatabase().HashGetAllAsync(key)).ToArray();
|
||||||
|
Connection.WaitAll(pipelineTasks);
|
||||||
|
|
||||||
|
return pipelineTasks
|
||||||
|
.Where(t => t.IsCompletedSuccessfully && t.Result.Any())
|
||||||
|
.Select(t => ConvertHashEntriesToCertificateEntry(t.Result))
|
||||||
|
.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Array.Empty<CertificateEntry>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void AddEntry(CertificateEntry entry)
|
public override void AddEntry(CertificateEntry entry)
|
||||||
{
|
{
|
||||||
string key = GenerateRedisKey(serialNumber);
|
string key = GenerateRedisKey(serialNumber);
|
||||||
string value = JsonConvert.SerializeObject(entry);
|
HashEntry[] values = ConvertCertificateEntryToHashEntries(entry);
|
||||||
TimeSpan expiresIn = entry.ExpireTime - DateTimeOffset.Now;
|
Connection.GetDatabase().HashSet(key, values);
|
||||||
Connection.GetDatabase().StringSet(key, value, expiresIn);
|
Connection.GetDatabase().KeyExpire(key, entry.ExpireTime - DateTimeOffset.Now);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override CertificateEntry? GetEntry(string serialNumber)
|
public override CertificateEntry? GetEntry(string serialNumber)
|
||||||
{
|
{
|
||||||
string key = GenerateRedisKey(serialNumber);
|
string key = GenerateRedisKey(serialNumber);
|
||||||
string value = Connection.GetDatabase().StringGet(GenerateRedisKey(serialNumber));
|
HashEntry[] values = Connection.GetDatabase().HashGetAll(key);
|
||||||
if (!string.IsNullOrEmpty(value))
|
if (values.Any())
|
||||||
{
|
{
|
||||||
return JsonConvert.DeserializeObject<CertificateEntry>(value);
|
return ConvertHashEntriesToCertificateEntry(values);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
Reference in New Issue
Block a user