diff --git a/src/SKIT.FlurlHttpClient.Wechat.Work/ExtendedSDK/Finance/Settings/EncryptionKeyEntry.cs b/src/SKIT.FlurlHttpClient.Wechat.Work/ExtendedSDK/Finance/Settings/EncryptionKeyEntry.cs index 1d228ea8..3046e601 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.Work/ExtendedSDK/Finance/Settings/EncryptionKeyEntry.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.Work/ExtendedSDK/Finance/Settings/EncryptionKeyEntry.cs @@ -17,6 +17,11 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.ExtendedSDK.Finance.Settings /// public string PrivateKey { get; } + /// + /// + /// + /// + /// [Newtonsoft.Json.JsonConstructor] [System.Text.Json.Serialization.JsonConstructor] public EncryptionKeyEntry(int version, string privateKey) @@ -32,12 +37,14 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.ExtendedSDK.Finance.Settings PrivateKey = privateKey; } + /// public bool Equals(EncryptionKeyEntry other) { return int.Equals(Version, other.Version) && string.Equals(PrivateKey, other.PrivateKey); } + /// public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) @@ -48,20 +55,23 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.ExtendedSDK.Finance.Settings return Equals((EncryptionKeyEntry)obj); } + /// public override int GetHashCode() { -#if NETFRAMEWORK || NETSTANDARD2_0 - return (Version.GetHashCode(), PrivateKey?.GetHashCode()).GetHashCode(); -#else +#if NETCOREAPP || NET5_0_OR_GREATER return HashCode.Combine(Version.GetHashCode(), PrivateKey?.GetHashCode()); +#else + return (Version.GetHashCode(), PrivateKey?.GetHashCode()).GetHashCode(); #endif } + /// public static bool operator ==(EncryptionKeyEntry left, EncryptionKeyEntry right) { return left.Equals(right); } + /// public static bool operator !=(EncryptionKeyEntry left, EncryptionKeyEntry right) { return !left.Equals(right); diff --git a/src/SKIT.FlurlHttpClient.Wechat.Work/ExtendedSDK/Finance/Settings/EncryptionKeyManager.cs b/src/SKIT.FlurlHttpClient.Wechat.Work/ExtendedSDK/Finance/Settings/EncryptionKeyManager.cs index caef0aaf..205dc05a 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.Work/ExtendedSDK/Finance/Settings/EncryptionKeyManager.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.Work/ExtendedSDK/Finance/Settings/EncryptionKeyManager.cs @@ -1,45 +1,70 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; +using System.Threading; +using System.Threading.Tasks; namespace SKIT.FlurlHttpClient.Wechat.Work.ExtendedSDK.Finance.Settings { /// /// 企业微信会话内容存档的消息加解密密钥管理器接口。 /// - public abstract class EncryptionKeyManager + public interface IEncryptionKeyManager { - /// - /// 获取存储的全部消息加解密密钥实体。 - /// - /// - public abstract IEnumerable AllEntries(); - /// /// 添加一个消息加解密密钥实体。 /// /// - public abstract void AddEntry(EncryptionKeyEntry entry); + void AddEntry(EncryptionKeyEntry entry); /// /// 根据版本号获取消息加解密密钥实体。 /// /// /// - public abstract EncryptionKeyEntry? GetEntry(int version); + EncryptionKeyEntry? GetEntry(int version); /// /// 根据版本号移除消息加解密密钥实体。 /// /// /// - public abstract bool RemoveEntry(int version); + bool RemoveEntry(int version); } /// - /// 一个基于内存实现的 。 + /// 企业微信会话内容存档的消息加解密密钥管理器接口。 /// - public class InMemoryEncryptionKeyManager : EncryptionKeyManager + public interface IEncryptionKeyManagerAsync : IEncryptionKeyManager + { + /// + /// 异步添加一个消息加解密密钥实体。 + /// + /// + /// + Task AddEntryAsync(EncryptionKeyEntry entry, CancellationToken cancellationToken = default); + + /// + /// 异步根据版本号获取消息加解密密钥实体。 + /// + /// + /// + /// + Task GetEntryAsync(int version, CancellationToken cancellationToken = default); + + /// + /// 异步根据版本号移除消息加解密密钥实体。 + /// + /// + /// + /// + Task RemoveEntryAsync(int version, CancellationToken cancellationToken = default); + } + + /// + /// 一个基于内存实现的 。 + /// + public sealed class InMemoryEncryptionKeyManager : IEncryptionKeyManager { private readonly ConcurrentDictionary _dict; @@ -48,20 +73,14 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.ExtendedSDK.Finance.Settings _dict = new ConcurrentDictionary(); } - public override IEnumerable AllEntries() + public void AddEntry(EncryptionKeyEntry entry) { - return _dict.Values.ToArray(); + _dict.AddOrUpdate(entry.Version, (_) => entry, (_, _) => entry); } - public override void AddEntry(EncryptionKeyEntry entry) + public EncryptionKeyEntry? GetEntry(int version) { - _dict.TryRemove(entry.Version, out _); - _dict.TryAdd(entry.Version, entry); - } - - public override EncryptionKeyEntry? GetEntry(int version) - { - if (_dict.TryGetValue(version, out var entry)) + if (_dict.TryGetValue(version, out EncryptionKeyEntry entry)) { return entry; } @@ -69,7 +88,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.ExtendedSDK.Finance.Settings return null; } - public override bool RemoveEntry(int version) + public bool RemoveEntry(int version) { return _dict.TryRemove(version, out _); } diff --git a/src/SKIT.FlurlHttpClient.Wechat.Work/ExtendedSDK/Finance/WechatWorkFinanceClient.cs b/src/SKIT.FlurlHttpClient.Wechat.Work/ExtendedSDK/Finance/WechatWorkFinanceClient.cs index 871d5009..d1dac7b4 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.Work/ExtendedSDK/Finance/WechatWorkFinanceClient.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.Work/ExtendedSDK/Finance/WechatWorkFinanceClient.cs @@ -9,6 +9,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.ExtendedSDK.Finance { using SKIT.FlurlHttpClient.Primitives; using SKIT.FlurlHttpClient.Wechat.Work.ExtendedSDK.Finance.InteropServices; + using SKIT.FlurlHttpClient.Wechat.Work.ExtendedSDK.Finance.Settings; /// /// 一个企业微信会话内容存档 API HTTP 客户端。 @@ -28,12 +29,12 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.ExtendedSDK.Finance /// /// 获取当前客户端使用的企业微信会话内容存档凭证。 /// - public Settings.Credentials Credentials { get; } + public Credentials Credentials { get; } /// /// 获取当前客户端使用的企业微信会话内容存档消息加解密密钥管理器。 /// - public Settings.EncryptionKeyManager EncryptionKeyManager { get; } + public IEncryptionKeyManager EncryptionKeyManager { get; } /// /// 用指定的配置项初始化 类的新实例。 @@ -44,7 +45,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.ExtendedSDK.Finance { if (options is null) throw new ArgumentNullException(nameof(options)); - Credentials = new Settings.Credentials(options); + Credentials = new Credentials(options); EncryptionKeyManager = options.EncryptionKeyManager; _timeout = options.Timeout; @@ -190,13 +191,15 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.ExtendedSDK.Finance EnsureInitialized(); - return Task.Run(() => + return Task.Run(async () => { string encryptKey; try { - Settings.EncryptionKeyEntry? encryptionKeyEntry = EncryptionKeyManager.GetEntry(request.PublicKeyVersion); + EncryptionKeyEntry? encryptionKeyEntry = (EncryptionKeyManager is IEncryptionKeyManagerAsync asyncMananger) + ? await asyncMananger.GetEntryAsync(request.PublicKeyVersion, cancellationToken).ConfigureAwait(false) + : EncryptionKeyManager.GetEntry(request.PublicKeyVersion); if (!encryptionKeyEntry.HasValue) throw new WechatWorkFinanceException($"Failed to decrypt random key of the encrypted chat data, because there is no private key matched the verion: \"{request.PublicKeyVersion}\"."); diff --git a/src/SKIT.FlurlHttpClient.Wechat.Work/ExtendedSDK/Finance/WechatWorkFinanceClientOptions.cs b/src/SKIT.FlurlHttpClient.Wechat.Work/ExtendedSDK/Finance/WechatWorkFinanceClientOptions.cs index 3115b286..211b2367 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.Work/ExtendedSDK/Finance/WechatWorkFinanceClientOptions.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.Work/ExtendedSDK/Finance/WechatWorkFinanceClientOptions.cs @@ -35,6 +35,6 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.ExtendedSDK.Finance /// 获取或设置企业微信会话内容存档消息加解密密钥管理器。 /// 默认值: /// - public Settings.EncryptionKeyManager EncryptionKeyManager { get; set; } = new Settings.InMemoryEncryptionKeyManager(); + public Settings.IEncryptionKeyManager EncryptionKeyManager { get; set; } = new Settings.InMemoryEncryptionKeyManager(); } }