diff --git a/src/SKIT.FlurlHttpClient.Wechat.Api/Extensions/WechatApiClientEventVerificationExtensions.cs b/src/SKIT.FlurlHttpClient.Wechat.Api/Extensions/WechatApiClientEventVerificationExtensions.cs new file mode 100644 index 00000000..c2403cdf --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.Api/Extensions/WechatApiClientEventVerificationExtensions.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Text; +using System.Text.RegularExpressions; + +namespace SKIT.FlurlHttpClient.Wechat.Api +{ + /// + /// 为 提供回调通知事件验证的扩展方法。 + /// + public static class WechatApiClientEventVerificationExtensions + { + /// + /// 验证回调通知事件签名。 + /// REF: https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.html + /// + /// + /// 微信回调通知中的 timestamp 字段。 + /// 微信回调通知中的 nonce 字段。 + /// 微信回调通知中的 signature 字段。 + /// + public static bool VerifyEventSignature( + this WechatApiClient client, + string callbackTimestamp, + string callbackNonce, + string callbackSignature) + { + if (client == null) throw new ArgumentNullException(nameof(client)); + if (callbackTimestamp == null) throw new ArgumentNullException(nameof(callbackTimestamp)); + if (callbackNonce == null) throw new ArgumentNullException(nameof(callbackNonce)); + if (callbackSignature == null) throw new ArgumentNullException(nameof(callbackSignature)); + + ISet set = new SortedSet() { client.Credentials.PushToken!, callbackTimestamp, callbackNonce }; + string sign = Security.SHA1Utility.Hash(string.Concat(set)); + return string.Equals(sign, callbackSignature, StringComparison.InvariantCultureIgnoreCase); + } + } +}