diff --git a/src/SKIT.FlurlHttpClient.Wechat.Api/Extensions/WechatApiClientEventSerializationExtensions.cs b/src/SKIT.FlurlHttpClient.Wechat.Api/Extensions/WechatApiClientEventExtensions.cs
similarity index 75%
rename from src/SKIT.FlurlHttpClient.Wechat.Api/Extensions/WechatApiClientEventSerializationExtensions.cs
rename to src/SKIT.FlurlHttpClient.Wechat.Api/Extensions/WechatApiClientEventExtensions.cs
index df8b867f..e5c64149 100644
--- a/src/SKIT.FlurlHttpClient.Wechat.Api/Extensions/WechatApiClientEventSerializationExtensions.cs
+++ b/src/SKIT.FlurlHttpClient.Wechat.Api/Extensions/WechatApiClientEventExtensions.cs
@@ -4,14 +4,15 @@ using System.IO;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
+using System.Xml.Linq;
using System.Xml.Serialization;
namespace SKIT.FlurlHttpClient.Wechat.Api
{
///
- /// 为 提供回调通知事件序列化相关的扩展方法。
+ /// 为 提供回调通知事件的扩展方法。
///
- public static class WechatApiClientEventSerializationExtensions
+ public static class WechatApiClientEventExtensions
{
private class EncryptedWechatApiEvent
{
@@ -270,5 +271,89 @@ namespace SKIT.FlurlHttpClient.Wechat.Api
return xml;
}
+
+ ///
+ /// 验证回调通知事件签名。
+ /// REF: https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.html
+ ///
+ ///
+ /// 微信回调通知中的 timestamp 字段。
+ /// 微信回调通知中的 nonce 字段。
+ /// 微信回调通知中的 signature 字段。
+ ///
+ public static bool VerifyEventSignatureForEcho(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);
+ }
+
+ ///
+ /// 验证回调通知事件签名。
+ /// REF: https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.html
+ ///
+ ///
+ ///
+ ///
+ public static bool VerifyEventSignatureFromJson(this WechatApiClient client, string callbackJson)
+ {
+ if (client == null) throw new ArgumentNullException(nameof(client));
+ if (callbackJson == null) throw new ArgumentNullException(nameof(callbackJson));
+
+ try
+ {
+ var encryptedEvent = client.JsonSerializer.Deserialize(callbackJson);
+ return Utilities.WxBizMsgCryptor.VerifySignature(
+ sToken: client.Credentials.PushToken!,
+ sTimestamp: encryptedEvent.Timestamp,
+ sNonce: encryptedEvent.Nonce,
+ sMsgEncrypt: encryptedEvent.EncryptedData,
+ sMsgSign: encryptedEvent.Signature
+ );
+ }
+ catch
+ {
+ return false;
+ }
+ }
+
+ ///
+ /// 验证回调通知事件签名。
+ /// REF: https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.html
+ ///
+ ///
+ ///
+ ///
+ public static bool VerifyEventSignatureFromXml(this WechatApiClient client, string callbackXml)
+ {
+ if (client == null) throw new ArgumentNullException(nameof(client));
+ if (callbackXml == null) throw new ArgumentNullException(nameof(callbackXml));
+
+ try
+ {
+ XDocument xDoc = XDocument.Load(callbackXml);
+ string? timestamp = xDoc.Root?.Element("TimeStamp")?.Value;
+ string? nonce = xDoc.Root?.Element("Nonce")?.Value;
+ string? msgEncrypt = xDoc.Root?.Element("Encrypt")?.Value;
+ string? msgSignature = xDoc.Root?.Element("MsgSignature")?.Value;
+
+ return Utilities.WxBizMsgCryptor.VerifySignature(
+ sToken: client.Credentials.PushToken!,
+ sTimestamp: timestamp!,
+ sNonce: nonce!,
+ sMsgEncrypt: msgEncrypt!,
+ sMsgSign: msgEncrypt!
+ );
+ }
+ catch
+ {
+ return false;
+ }
+ }
}
}
diff --git a/src/SKIT.FlurlHttpClient.Wechat.Api/Extensions/WechatApiClientEventVerificationExtensions.cs b/src/SKIT.FlurlHttpClient.Wechat.Api/Extensions/WechatApiClientEventVerificationExtensions.cs
deleted file mode 100644
index 7a8c50ae..00000000
--- a/src/SKIT.FlurlHttpClient.Wechat.Api/Extensions/WechatApiClientEventVerificationExtensions.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-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);
- }
- }
-}