mirror of
https://gitee.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat.git
synced 2025-07-15 23:13:32 +08:00
feat(wxapi): 移除 WxBizMsgCryptor 工具类
This commit is contained in:
parent
23d9d247ef
commit
62b871023c
@ -1,6 +1,14 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Security;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
|
using System.Xml;
|
||||||
|
|
||||||
namespace SKIT.FlurlHttpClient.Wechat.Api
|
namespace SKIT.FlurlHttpClient.Wechat.Api
|
||||||
{
|
{
|
||||||
@ -29,7 +37,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api
|
|||||||
public string Signature { get; set; } = default!;
|
public string Signature { get; set; } = default!;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TEvent InnerDeserializeEventFromJson<TEvent>(this WechatApiClient client, string callbackJson)
|
private static TEvent InnerDeserializeEventFromJson<TEvent>(WechatApiClient client, string callbackJson)
|
||||||
where TEvent : WechatApiEvent
|
where TEvent : WechatApiEvent
|
||||||
{
|
{
|
||||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
if (client == null) throw new ArgumentNullException(nameof(client));
|
||||||
@ -40,7 +48,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api
|
|||||||
if (callbackJson.Contains("\"Encrypt\""))
|
if (callbackJson.Contains("\"Encrypt\""))
|
||||||
{
|
{
|
||||||
InnerEncryptedEvent encryptedEvent = client.JsonSerializer.Deserialize<InnerEncryptedEvent>(callbackJson);
|
InnerEncryptedEvent encryptedEvent = client.JsonSerializer.Deserialize<InnerEncryptedEvent>(callbackJson);
|
||||||
callbackJson = Utilities.WxBizMsgCryptor.AESDecrypt(cipherText: encryptedEvent.EncryptedData, encodingAESKey: client.Credentials.PushEncodingAESKey!, out _);
|
callbackJson = Utilities.WechatEventMessageCryptor.AESDecrypt(cipherText: encryptedEvent.EncryptedData, encodingAESKey: client.Credentials.PushEncodingAESKey!, out _);
|
||||||
}
|
}
|
||||||
|
|
||||||
return client.JsonSerializer.Deserialize<TEvent>(callbackJson);
|
return client.JsonSerializer.Deserialize<TEvent>(callbackJson);
|
||||||
@ -55,7 +63,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TEvent InnerDeserializeEventFromXml<TEvent>(this WechatApiClient client, string callbackXml)
|
private static TEvent InnerDeserializeEventFromXml<TEvent>(WechatApiClient client, string callbackXml)
|
||||||
where TEvent : WechatApiEvent
|
where TEvent : WechatApiEvent
|
||||||
{
|
{
|
||||||
if (client == null) throw new ArgumentNullException(nameof(client));
|
if (client == null) throw new ArgumentNullException(nameof(client));
|
||||||
@ -67,7 +75,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api
|
|||||||
{
|
{
|
||||||
XDocument xDocument = XDocument.Parse(callbackXml);
|
XDocument xDocument = XDocument.Parse(callbackXml);
|
||||||
string encryptedData = xDocument.Root.Element("Encrypt").Value;
|
string encryptedData = xDocument.Root.Element("Encrypt").Value;
|
||||||
callbackXml = Utilities.WxBizMsgCryptor.AESDecrypt(cipherText: encryptedData, encodingAESKey: client.Credentials.PushEncodingAESKey!, out _);
|
callbackXml = Utilities.WechatEventMessageCryptor.AESDecrypt(cipherText: encryptedData, encodingAESKey: client.Credentials.PushEncodingAESKey!, out _);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Utilities.XmlUtility.Deserialize<TEvent>(callbackXml);
|
return Utilities.XmlUtility.Deserialize<TEvent>(callbackXml);
|
||||||
@ -163,12 +171,12 @@ namespace SKIT.FlurlHttpClient.Wechat.Api
|
|||||||
{
|
{
|
||||||
string timestamp = DateTimeOffset.Now.ToLocalTime().ToUnixTimeSeconds().ToString();
|
string timestamp = DateTimeOffset.Now.ToLocalTime().ToUnixTimeSeconds().ToString();
|
||||||
string nonce = DateTimeOffset.Now.Ticks.ToString("x");
|
string nonce = DateTimeOffset.Now.Ticks.ToString("x");
|
||||||
string cipher = Utilities.WxBizMsgCryptor.AESEncrypt(
|
string cipher = Utilities.WechatEventMessageCryptor.AESEncrypt(
|
||||||
plainText: json,
|
plainText: json,
|
||||||
encodingAESKey: client.Credentials.PushEncodingAESKey!,
|
encodingAESKey: client.Credentials.PushEncodingAESKey!,
|
||||||
appId: client.Credentials.AppId
|
appId: client.Credentials.AppId
|
||||||
);
|
);
|
||||||
string sign = Utilities.WxBizMsgCryptor.GenerateSignature(
|
string sign = Utilities.WechatEventMessageCryptor.GenerateSignature(
|
||||||
sToken: client.Credentials.PushToken!,
|
sToken: client.Credentials.PushToken!,
|
||||||
sTimestamp: timestamp,
|
sTimestamp: timestamp,
|
||||||
sNonce: nonce,
|
sNonce: nonce,
|
||||||
@ -223,13 +231,13 @@ namespace SKIT.FlurlHttpClient.Wechat.Api
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string cipher = Utilities.WxBizMsgCryptor.AESEncrypt(
|
string cipher = Utilities.WechatEventMessageCryptor.AESEncrypt(
|
||||||
plainText: xml,
|
plainText: xml,
|
||||||
encodingAESKey: client.Credentials.PushEncodingAESKey!,
|
encodingAESKey: client.Credentials.PushEncodingAESKey!,
|
||||||
appId: client.Credentials.AppId
|
appId: client.Credentials.AppId
|
||||||
);
|
);
|
||||||
|
|
||||||
xml = Utilities.WxBizMsgCryptor.WrapXml(sToken: client.Credentials.PushToken!, sMsgEncrypt: cipher);
|
xml = Utilities.WechatEventMessageCryptor.WrapXml(sToken: client.Credentials.PushToken!, sMsgEncrypt: cipher);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -279,7 +287,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var encryptedEvent = client.JsonSerializer.Deserialize<InnerEncryptedEvent>(callbackJson);
|
var encryptedEvent = client.JsonSerializer.Deserialize<InnerEncryptedEvent>(callbackJson);
|
||||||
return Utilities.WxBizMsgCryptor.VerifySignature(
|
return Utilities.WechatEventMessageCryptor.VerifySignature(
|
||||||
sToken: client.Credentials.PushToken!,
|
sToken: client.Credentials.PushToken!,
|
||||||
sTimestamp: callbackTimestamp,
|
sTimestamp: callbackTimestamp,
|
||||||
sNonce: callbackNonce,
|
sNonce: callbackNonce,
|
||||||
@ -313,7 +321,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api
|
|||||||
XDocument xDoc = XDocument.Parse(callbackXml);
|
XDocument xDoc = XDocument.Parse(callbackXml);
|
||||||
string? msgEncrypt = xDoc.Root?.Element("Encrypt")?.Value;
|
string? msgEncrypt = xDoc.Root?.Element("Encrypt")?.Value;
|
||||||
|
|
||||||
return Utilities.WxBizMsgCryptor.VerifySignature(
|
return Utilities.WechatEventMessageCryptor.VerifySignature(
|
||||||
sToken: client.Credentials.PushToken!,
|
sToken: client.Credentials.PushToken!,
|
||||||
sTimestamp: callbackTimestamp,
|
sTimestamp: callbackTimestamp,
|
||||||
sNonce: callbackNonce,
|
sNonce: callbackNonce,
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
[assembly: InternalsVisibleTo("SKIT.FlurlHttpClient.Wechat.Api.UnitTests")]
|
@ -10,7 +10,7 @@ using System.Xml;
|
|||||||
|
|
||||||
namespace SKIT.FlurlHttpClient.Wechat.Api.Utilities
|
namespace SKIT.FlurlHttpClient.Wechat.Api.Utilities
|
||||||
{
|
{
|
||||||
public static class WxBizMsgCryptor
|
internal static class WechatEventMessageCryptor
|
||||||
{
|
{
|
||||||
private const int AES_KEY_SIZE = 256;
|
private const int AES_KEY_SIZE = 256;
|
||||||
private const int AES_BLOCK_SIZE = 128;
|
private const int AES_BLOCK_SIZE = 128;
|
||||||
@ -74,15 +74,15 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.Utilities
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] AESDecrypt(byte[] keyBytes, byte[] ivBytes, byte[] ciperBytes)
|
private static byte[] AESDecrypt(byte[] keyBytes, byte[] ivBytes, byte[] cipherBytes)
|
||||||
{
|
{
|
||||||
if (keyBytes == null) throw new ArgumentNullException(nameof(keyBytes));
|
if (keyBytes == null) throw new ArgumentNullException(nameof(keyBytes));
|
||||||
if (ivBytes == null) throw new ArgumentNullException(nameof(ivBytes));
|
if (ivBytes == null) throw new ArgumentNullException(nameof(ivBytes));
|
||||||
if (ciperBytes == null) throw new ArgumentNullException(nameof(ciperBytes));
|
if (cipherBytes == null) throw new ArgumentNullException(nameof(cipherBytes));
|
||||||
|
|
||||||
using var aes = Aes.Create();
|
using var aes = Aes.Create();
|
||||||
aes.KeySize = 256;
|
aes.KeySize = AES_KEY_SIZE;
|
||||||
aes.BlockSize = 128;
|
aes.BlockSize = AES_BLOCK_SIZE;
|
||||||
aes.Mode = CipherMode.CBC;
|
aes.Mode = CipherMode.CBC;
|
||||||
//aes.Padding = PaddingMode.PKCS7;
|
//aes.Padding = PaddingMode.PKCS7;
|
||||||
aes.Padding = PaddingMode.None;
|
aes.Padding = PaddingMode.None;
|
||||||
@ -93,9 +93,9 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.Utilities
|
|||||||
using (var ms = new MemoryStream())
|
using (var ms = new MemoryStream())
|
||||||
using (var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Write))
|
using (var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Write))
|
||||||
{
|
{
|
||||||
byte[] bMsg = new byte[ciperBytes.Length + 32 - ciperBytes.Length % 32];
|
byte[] msgBytes = new byte[cipherBytes.Length + 32 - cipherBytes.Length % 32];
|
||||||
Array.Copy(ciperBytes, bMsg, ciperBytes.Length);
|
Array.Copy(cipherBytes, msgBytes, cipherBytes.Length);
|
||||||
cs.Write(ciperBytes, 0, ciperBytes.Length);
|
cs.Write(cipherBytes, 0, cipherBytes.Length);
|
||||||
|
|
||||||
byte[] plainBytes = Decode2(ms.ToArray());
|
byte[] plainBytes = Decode2(ms.ToArray());
|
||||||
return plainBytes;
|
return plainBytes;
|
||||||
@ -148,7 +148,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.Utilities
|
|||||||
byte[] keyBytes = Convert.FromBase64String(encodingAESKey + "=");
|
byte[] keyBytes = Convert.FromBase64String(encodingAESKey + "=");
|
||||||
byte[] ivBytes = new byte[16];
|
byte[] ivBytes = new byte[16];
|
||||||
Array.Copy(keyBytes, ivBytes, 16);
|
Array.Copy(keyBytes, ivBytes, 16);
|
||||||
byte[] btmpMsg = AESDecrypt(ciperBytes: cipherBytes, ivBytes: ivBytes, keyBytes: keyBytes);
|
byte[] btmpMsg = AESDecrypt(cipherBytes: cipherBytes, ivBytes: ivBytes, keyBytes: keyBytes);
|
||||||
|
|
||||||
int len = BitConverter.ToInt32(btmpMsg, 16);
|
int len = BitConverter.ToInt32(btmpMsg, 16);
|
||||||
len = IPAddress.NetworkToHostOrder(len);
|
len = IPAddress.NetworkToHostOrder(len);
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
|
namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
|
||||||
{
|
{
|
||||||
public class TestCase_WxBizMsgCryptorUtilityTests
|
public class TestCase_WechatEventMessageCryptorTests
|
||||||
{
|
{
|
||||||
[Fact(DisplayName = "试用例:验签并解密回调数据")]
|
[Fact(DisplayName = "试用例:验签并解密回调数据")]
|
||||||
public void TestVerifyAndDecryptEvent()
|
public void TestVerifyAndDecryptEvent()
|
||||||
@ -15,12 +15,12 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
|
|||||||
string reqNonce = "1372623149";
|
string reqNonce = "1372623149";
|
||||||
string reqCipherText = "RypEvHKD8QQKFhvQ6QleEB4J58tiPdvo+rtK1I9qca6aM/wvqnLSV5zEPeusUiX5L5X/0lWfrf0QADHHhGd3QczcdCUpj911L3vg3W/sYYvuJTs3TUUkSUXxaccAS0qhxchrRYt66wiSpGLYL42aM6A8dTT+6k4aSknmPj48kzJs8qLjvd4Xgpue06DOdnLxAUHzM6+kDZ+HMZfJYuR+LtwGc2hgf5gsijff0ekUNXZiqATP7PF5mZxZ3Izoun1s4zG4LUMnvw2r+KqCKIw+3IQH03v+BCA9nMELNqbSf6tiWSrXJB3LAVGUcallcrw8V2t9EL4EhzJWrQUax5wLVMNS0+rUPA3k22Ncx4XXZS9o0MBH27Bo6BpNelZpS+/uh9KsNlY6bHCmJU9p8g7m3fVKn28H3KDYA5Pl/T8Z1ptDAVe0lXdQ2YoyyH2uyPIGHBZZIs2pDBS8R07+qN+E7Q==";
|
string reqCipherText = "RypEvHKD8QQKFhvQ6QleEB4J58tiPdvo+rtK1I9qca6aM/wvqnLSV5zEPeusUiX5L5X/0lWfrf0QADHHhGd3QczcdCUpj911L3vg3W/sYYvuJTs3TUUkSUXxaccAS0qhxchrRYt66wiSpGLYL42aM6A8dTT+6k4aSknmPj48kzJs8qLjvd4Xgpue06DOdnLxAUHzM6+kDZ+HMZfJYuR+LtwGc2hgf5gsijff0ekUNXZiqATP7PF5mZxZ3Izoun1s4zG4LUMnvw2r+KqCKIw+3IQH03v+BCA9nMELNqbSf6tiWSrXJB3LAVGUcallcrw8V2t9EL4EhzJWrQUax5wLVMNS0+rUPA3k22Ncx4XXZS9o0MBH27Bo6BpNelZpS+/uh9KsNlY6bHCmJU9p8g7m3fVKn28H3KDYA5Pl/T8Z1ptDAVe0lXdQ2YoyyH2uyPIGHBZZIs2pDBS8R07+qN+E7Q==";
|
||||||
|
|
||||||
string actualPlain = Utilities.WxBizMsgCryptor.AESDecrypt(reqCipherText, aesKey, out string actualAppId);
|
string actualPlain = Utilities.WechatEventMessageCryptor.AESDecrypt(reqCipherText, aesKey, out string actualAppId);
|
||||||
string expectedPlain = "<xml><ToUserName><![CDATA[wx5823bf96d3bd56c7]]></ToUserName>\n<FromUserName><![CDATA[mycreate]]></FromUserName>\n<CreateTime>1409659813</CreateTime>\n<MsgType><![CDATA[text]]></MsgType>\n<Content><![CDATA[hello]]></Content>\n<MsgId>4561255354251345929</MsgId>\n<AgentID>218</AgentID>\n</xml>";
|
string expectedPlain = "<xml><ToUserName><![CDATA[wx5823bf96d3bd56c7]]></ToUserName>\n<FromUserName><![CDATA[mycreate]]></FromUserName>\n<CreateTime>1409659813</CreateTime>\n<MsgType><![CDATA[text]]></MsgType>\n<Content><![CDATA[hello]]></Content>\n<MsgId>4561255354251345929</MsgId>\n<AgentID>218</AgentID>\n</xml>";
|
||||||
|
|
||||||
Assert.Equal(expectedPlain, actualPlain);
|
Assert.Equal(expectedPlain, actualPlain);
|
||||||
Assert.Equal(appId, actualAppId);
|
Assert.Equal(appId, actualAppId);
|
||||||
Assert.True(Utilities.WxBizMsgCryptor.VerifySignature(token, reqTimeStamp, reqNonce, reqCipherText, reqMsgSig));
|
Assert.True(Utilities.WechatEventMessageCryptor.VerifySignature(token, reqTimeStamp, reqNonce, reqCipherText, reqMsgSig));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(DisplayName = "试用例:验签回调数据")]
|
[Fact(DisplayName = "试用例:验签回调数据")]
|
||||||
@ -32,7 +32,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
|
|||||||
string reqNonce = "1811081856";
|
string reqNonce = "1811081856";
|
||||||
string reqCipherText = "Q/jUxIL3/jRaFeTKesIr1QSq2SOEApDqlzcRrRM6Jlk4EbMBns3plPOR/W3gThOEq+zYI42fNSoIUb3cQwt9zyD1aLU/7D3WNLute7LQ9LSHjZEfVmx5zcIR9zvrUWGjhe1whTPH4e1WR6vbOYs8o/bDRF0vX/NcE4XK7P83Y6CzQiJoKbjVCne84s0zcw5eh+ZUDB55eaDHPSoS7kAC8kB00pfBoDF0jyfc8CUKLW97e72vJGyUWjZ0BvYN+R+tFjMgEzg/EN1imuuFnf40DMAcvB6y+C97TuaWjpgfRdowGWzn10JAFNukRfQqjdA0e2bfczJ7+t9w/t8/XSMADJOt1xbnP+I5cRX/r7ueBGmG/6ejP3myO9yTXHdujGvwrXHuWw+J7qD4VoUVjbm2vQ1qQKbrweKssr6O+3XSbanZ5R3n26EpN/gfgX+r6rcGViqsFop9Ai9xMnfJUubB6Q==";
|
string reqCipherText = "Q/jUxIL3/jRaFeTKesIr1QSq2SOEApDqlzcRrRM6Jlk4EbMBns3plPOR/W3gThOEq+zYI42fNSoIUb3cQwt9zyD1aLU/7D3WNLute7LQ9LSHjZEfVmx5zcIR9zvrUWGjhe1whTPH4e1WR6vbOYs8o/bDRF0vX/NcE4XK7P83Y6CzQiJoKbjVCne84s0zcw5eh+ZUDB55eaDHPSoS7kAC8kB00pfBoDF0jyfc8CUKLW97e72vJGyUWjZ0BvYN+R+tFjMgEzg/EN1imuuFnf40DMAcvB6y+C97TuaWjpgfRdowGWzn10JAFNukRfQqjdA0e2bfczJ7+t9w/t8/XSMADJOt1xbnP+I5cRX/r7ueBGmG/6ejP3myO9yTXHdujGvwrXHuWw+J7qD4VoUVjbm2vQ1qQKbrweKssr6O+3XSbanZ5R3n26EpN/gfgX+r6rcGViqsFop9Ai9xMnfJUubB6Q==";
|
||||||
|
|
||||||
Assert.True(Utilities.WxBizMsgCryptor.VerifySignature(token, reqTimeStamp, reqNonce, reqCipherText, reqMsgSig));
|
Assert.True(Utilities.WechatEventMessageCryptor.VerifySignature(token, reqTimeStamp, reqNonce, reqCipherText, reqMsgSig));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user