diff --git a/src/SKIT.FlurlHttpClient.Wechat.Api/Extensions/WechatApiClientEventExtensions.cs b/src/SKIT.FlurlHttpClient.Wechat.Api/Extensions/WechatApiClientEventExtensions.cs index ef0dbb6d..d3b2de87 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.Api/Extensions/WechatApiClientEventExtensions.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.Api/Extensions/WechatApiClientEventExtensions.cs @@ -9,7 +9,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api /// public static class WechatApiClientEventExtensions { - private class EncryptedWechatApiEvent + private class InnerEncryptedEvent { [Newtonsoft.Json.JsonProperty("Encrypt")] [System.Text.Json.Serialization.JsonPropertyName("Encrypt")] @@ -18,7 +18,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api [Newtonsoft.Json.JsonProperty("TimeStamp")] [System.Text.Json.Serialization.JsonPropertyName("TimeStamp")] [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.NumericalStringConverter))] - public string Timestamp { get; set; } = default!; + public string TimestampString { get; set; } = default!; [Newtonsoft.Json.JsonProperty("Nonce")] [System.Text.Json.Serialization.JsonPropertyName("Nonce")] @@ -29,7 +29,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api public string Signature { get; set; } = default!; } - private static TEvent InnerDeserializeEventFromJson(this WechatApiClient client, string callbackJson, bool safety) + private static TEvent InnerDeserializeEventFromJson(this WechatApiClient client, string callbackJson) where TEvent : WechatApiEvent { if (client == null) throw new ArgumentNullException(nameof(client)); @@ -37,15 +37,9 @@ namespace SKIT.FlurlHttpClient.Wechat.Api try { - if (safety) + if (callbackJson.Contains("\"Encrypt\"")) { - if (string.IsNullOrEmpty(client.Credentials.PushEncodingAESKey)) - throw new Exceptions.WechatApiEventSerializationException("Encrypt event failed, because there is no encoding AES key."); - - var encryptedEvent = client.JsonSerializer.Deserialize(callbackJson); - if (string.IsNullOrEmpty(encryptedEvent.EncryptedData)) - throw new Exceptions.WechatApiEventSerializationException("Encrypt event failed, because of empty encrypted data."); - + InnerEncryptedEvent encryptedEvent = client.JsonSerializer.Deserialize(callbackJson); callbackJson = Utilities.WxBizMsgCryptor.AESDecrypt(cipherText: encryptedEvent.EncryptedData, encodingAESKey: client.Credentials.PushEncodingAESKey!, out _); } @@ -61,7 +55,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api } } - private static TEvent InnerDeserializeEventFromXml(this WechatApiClient client, string callbackXml, bool safety) + private static TEvent InnerDeserializeEventFromXml(this WechatApiClient client, string callbackXml) where TEvent : WechatApiEvent { if (client == null) throw new ArgumentNullException(nameof(client)); @@ -69,12 +63,11 @@ namespace SKIT.FlurlHttpClient.Wechat.Api try { - if (safety) + if (callbackXml.Contains("") && callbackXml.Contains("")) { - if (!Utilities.WxBizMsgCryptor.TryParseXml(callbackXml, out string? encryptedXml)) - throw new Exceptions.WechatApiEventSerializationException("Encrypt event failed, because of empty encrypted data."); - - callbackXml = Utilities.WxBizMsgCryptor.AESDecrypt(cipherText: encryptedXml!, encodingAESKey: client.Credentials.PushEncodingAESKey!, out _); + XDocument xDocument = XDocument.Parse(callbackXml); + string encryptedData = xDocument.Root.Element("Encrypt").Value; + callbackXml = Utilities.WxBizMsgCryptor.AESDecrypt(cipherText: encryptedData, encodingAESKey: client.Credentials.PushEncodingAESKey!, out _); } return Utilities.XmlUtility.Deserialize(callbackXml); @@ -95,12 +88,11 @@ namespace SKIT.FlurlHttpClient.Wechat.Api /// /// /// - /// 是否是安全模式(即是否需要解密)。 /// - public static TEvent DeserializeEventFromJson(this WechatApiClient client, string callbackJson, bool safety = false) + public static TEvent DeserializeEventFromJson(this WechatApiClient client, string callbackJson) where TEvent : WechatApiEvent, WechatApiEvent.Serialization.IJsonSerializable, new() { - return InnerDeserializeEventFromJson(client, callbackJson, safety); + return InnerDeserializeEventFromJson(client, callbackJson); } /// @@ -108,11 +100,10 @@ namespace SKIT.FlurlHttpClient.Wechat.Api /// /// /// - /// 是否是安全模式(即是否需要解密)。 /// - public static WechatApiEvent DeserializeEventFromJson(this WechatApiClient client, string callbackJson, bool safety = false) + public static WechatApiEvent DeserializeEventFromJson(this WechatApiClient client, string callbackJson) { - return InnerDeserializeEventFromJson(client, callbackJson, safety); + return InnerDeserializeEventFromJson(client, callbackJson); } /// @@ -121,12 +112,11 @@ namespace SKIT.FlurlHttpClient.Wechat.Api /// /// /// - /// 是否是安全模式(即是否需要解密)。 /// - public static TEvent DeserializeEventFromXml(this WechatApiClient client, string callbackXml, bool safety = false) + public static TEvent DeserializeEventFromXml(this WechatApiClient client, string callbackXml) where TEvent : WechatApiEvent, WechatApiEvent.Serialization.IXmlSerializable, new() { - return InnerDeserializeEventFromXml(client, callbackXml, safety); + return InnerDeserializeEventFromXml(client, callbackXml); } /// @@ -134,11 +124,10 @@ namespace SKIT.FlurlHttpClient.Wechat.Api /// /// /// - /// 是否是安全模式(即是否需要解密)。 /// - public static WechatApiEvent DeserializeEventFromXml(this WechatApiClient client, string callbackXml, bool safety = false) + public static WechatApiEvent DeserializeEventFromXml(this WechatApiClient client, string callbackXml) { - return InnerDeserializeEventFromXml(client, callbackXml, safety); + return InnerDeserializeEventFromXml(client, callbackXml); } /// @@ -149,7 +138,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api /// /// 是否是安全模式(即是否需要加密)。 /// - public static string SerializeEventToJson(this WechatApiClient client, TEvent callbackModel, bool safety = false) + public static string SerializeEventToJson(this WechatApiClient client, TEvent callbackModel, bool safety = true) where TEvent : WechatApiEvent, WechatApiEvent.Serialization.IJsonSerializable, new() { string json; @@ -186,10 +175,10 @@ namespace SKIT.FlurlHttpClient.Wechat.Api sMsgEncrypt: cipher ); - json = client.JsonSerializer.Serialize(new EncryptedWechatApiEvent() + json = client.JsonSerializer.Serialize(new InnerEncryptedEvent() { EncryptedData = cipher, - Timestamp = timestamp, + TimestampString = timestamp, Nonce = nonce, Signature = sign }); @@ -211,7 +200,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api /// /// 是否是安全模式(即是否需要加密)。 /// - public static string SerializeEventToXml(this WechatApiClient client, TEvent callbackModel, bool safety = false) + public static string SerializeEventToXml(this WechatApiClient client, TEvent callbackModel, bool safety = true) where TEvent : WechatApiEvent, WechatApiEvent.Serialization.IXmlSerializable, new() { string xml; @@ -289,7 +278,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api try { - var encryptedEvent = client.JsonSerializer.Deserialize(callbackJson); + var encryptedEvent = client.JsonSerializer.Deserialize(callbackJson); return Utilities.WxBizMsgCryptor.VerifySignature( sToken: client.Credentials.PushToken!, sTimestamp: callbackTimestamp, diff --git a/test/SKIT.FlurlHttpClient.Wechat.Api.UnitTests/TestCase_EventVerificationTests.cs b/test/SKIT.FlurlHttpClient.Wechat.Api.UnitTests/TestCase_EventVerificationTests.cs index 76fa5db2..463b2a98 100644 --- a/test/SKIT.FlurlHttpClient.Wechat.Api.UnitTests/TestCase_EventVerificationTests.cs +++ b/test/SKIT.FlurlHttpClient.Wechat.Api.UnitTests/TestCase_EventVerificationTests.cs @@ -4,8 +4,8 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests { public class TestCase_EventVerificationTests { - [Fact(DisplayName = "测试用例:验签并解密回调数据")] - public void TestVerifyEvent() + [Fact(DisplayName = "测试用例:验签并解密 XML 回调数据")] + public void TestVerifyXmlEvent() { string callbacMsgSig = "477715d11cdb4164915debcba66cb864d751f3e6"; string callbacTimeStamp = "1409659813"; @@ -19,7 +19,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests PushToken = "QDG6eK" }; var client = new WechatApiClient(options); - var eventModel = client.DeserializeEventFromXml(callbackXml, safety: true); + var eventModel = client.DeserializeEventFromXml(callbackXml); Assert.True(client.VerifyEventSignatureFromXml(callbacTimeStamp, callbacNonce, callbackXml, callbacMsgSig)); Assert.Equal("text", eventModel.MessageType, ignoreCase: true);