diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Extensions/WechatTenpayClientEventDecryptionExtensions.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Extensions/WechatTenpayClientEventDecryptionExtensions.cs
index 2dea504e..58892659 100644
--- a/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Extensions/WechatTenpayClientEventDecryptionExtensions.cs
+++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Extensions/WechatTenpayClientEventDecryptionExtensions.cs
@@ -1,8 +1,9 @@
using System;
-using System.Text;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV2
{
+ using SKIT.FlurlHttpClient.Primitives;
+
///
/// 为 提供回调通知事件敏感数据解密的扩展方法。
///
@@ -56,11 +57,11 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV2
try
{
- string key = Utilities.MD5Utility.Hash(client.Credentials.MerchantSecret).ToLower();
+ string key = Utilities.MD5Utility.Hash(client.Credentials.MerchantSecret).Value!.ToLower();
string plainXml = Utilities.AESUtility.DecryptWithECB(
- encodingKey: Convert.ToBase64String(Encoding.UTF8.GetBytes(key)),
- encodingCipherText: webhookEvent.EncryptedRequestInfo!
- );
+ encodingKey: new EncodedString(key, EncodingKinds.Literal),
+ encodingCipher: new EncodedString(webhookEvent.EncryptedRequestInfo!, EncodingKinds.Base64)
+ )!;
plainJson = Utilities.XmlHelper.ConvertToJson(plainXml);
}
catch (Exception ex)
diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Extensions/WechatTenpayClientExecuteMerchantMediaExtensions.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Extensions/WechatTenpayClientExecuteMerchantMediaExtensions.cs
index 6af28c45..e564a65c 100644
--- a/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Extensions/WechatTenpayClientExecuteMerchantMediaExtensions.cs
+++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Extensions/WechatTenpayClientExecuteMerchantMediaExtensions.cs
@@ -10,6 +10,8 @@ using Flurl.Http;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV2
{
+ using SKIT.FlurlHttpClient.Primitives;
+
public static class WechatTenpayClientExecuteMerchantMediaExtensions
{
///
@@ -29,7 +31,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV2
request.FileName = Guid.NewGuid().ToString("N").ToLower() + ".jpg";
if (request.FileHash is null)
- request.FileHash = BitConverter.ToString(Utilities.MD5Utility.Hash(request.FileBytes ?? Array.Empty())).Replace("-", string.Empty).ToLower();
+ request.FileHash = EncodedString.ToHexString(Utilities.MD5Utility.Hash(request.FileBytes ?? Array.Empty())).Value!.ToLower();
IFlurlRequest flurlReq = client
.CreateFlurlRequest(request, HttpMethod.Post, "secapi", "mch", "uploadmedia");
diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Models/VehiclePartner/GetTransitPartnerOrderResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Models/VehiclePartner/GetTransitPartnerOrderResponse.cs
index ebfecaa3..d15ff29c 100644
--- a/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Models/VehiclePartner/GetTransitPartnerOrderResponse.cs
+++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Models/VehiclePartner/GetTransitPartnerOrderResponse.cs
@@ -10,7 +10,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV2.Models
[System.Text.Json.Serialization.JsonConverter(typeof(Converters.ResponseClassSystemTextJsonConverter))]
public class GetTransitPartnerOrderResponse : WechatTenpaySignableResponse
{
- public static new class Types
+ public static class Types
{
public class Coupon : GetTransitOrderResponse.Types.Coupon
{
diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Utilities/AESUtility.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Utilities/AESUtility.cs
index 717094f4..18b5f965 100644
--- a/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Utilities/AESUtility.cs
+++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Utilities/AESUtility.cs
@@ -1,9 +1,10 @@
using System;
using System.Security.Cryptography;
-using System.Text;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV2.Utilities
{
+ using SKIT.FlurlHttpClient.Primitives;
+
///
/// AES 算法工具类。
///
@@ -20,33 +21,31 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV2.Utilities
if (keyBytes is null) throw new ArgumentNullException(nameof(keyBytes));
if (cipherBytes is null) throw new ArgumentNullException(nameof(cipherBytes));
- using (SymmetricAlgorithm aes = Aes.Create())
- {
- aes.Mode = CipherMode.ECB;
- aes.Padding = PaddingMode.PKCS7;
- aes.Key = keyBytes;
+ using SymmetricAlgorithm aes = Aes.Create();
+ aes.Mode = CipherMode.ECB;
+ aes.Padding = PaddingMode.PKCS7;
+ aes.Key = keyBytes;
- using ICryptoTransform transform = aes.CreateDecryptor();
- return transform.TransformFinalBlock(cipherBytes, 0, cipherBytes.Length);
- }
+ using ICryptoTransform transform = aes.CreateDecryptor();
+ return transform.TransformFinalBlock(cipherBytes, 0, cipherBytes.Length);
}
///
/// 基于 ECB 模式解密数据。
///
- /// 经 Base64 编码后的 AES 密钥。
- /// 经 Base64 编码后的待解密数据。
- /// 解密后的文本数据。
- public static string DecryptWithECB(string encodingKey, string encodingCipherText)
+ /// 经过编码后的(通常为 Base64)AES 密钥。
+ /// 经过编码后的(通常为 Base64)待解密数据。
+ /// 解密后的数据。
+ public static EncodedString DecryptWithECB(EncodedString encodingKey, EncodedString encodingCipher)
{
- if (encodingKey is null) throw new ArgumentNullException(nameof(encodingKey));
- if (encodingCipherText is null) throw new ArgumentNullException(nameof(encodingCipherText));
+ if (encodingKey.Value is null) throw new ArgumentNullException(nameof(encodingKey));
+ if (encodingCipher.Value is null) throw new ArgumentNullException(nameof(encodingCipher));
byte[] plainBytes = DecryptWithECB(
- keyBytes: Convert.FromBase64String(encodingKey),
- cipherBytes: Convert.FromBase64String(encodingCipherText)
+ keyBytes: EncodedString.FromString(encodingKey, fallbackEncodingKind: EncodingKinds.Base64),
+ cipherBytes: EncodedString.FromString(encodingCipher, fallbackEncodingKind: EncodingKinds.Base64)
);
- return Encoding.UTF8.GetString(plainBytes);
+ return EncodedString.ToLiteralString(plainBytes);
}
}
}
diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Utilities/HMACUtility.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Utilities/HMACUtility.cs
index 88dca83f..b97e7c10 100644
--- a/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Utilities/HMACUtility.cs
+++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Utilities/HMACUtility.cs
@@ -1,44 +1,49 @@
using System;
using System.Security.Cryptography;
-using System.Text;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV2.Utilities
{
+ using SKIT.FlurlHttpClient.Primitives;
+
///
/// HMAC 算法工具类。
///
public static class HMACUtility
{
///
- /// 获取 HMAC-SHA-256 消息认证码。
+ /// 计算 HMAC-SHA-256 哈希值。
///
- /// 密钥字节数组。
- /// 信息字节数组。
- /// 消息认证码字节数组。
- public static byte[] HashWithSHA256(byte[] secretBytes, byte[] msgBytes)
+ /// 密钥字节数组。
+ /// 要计算哈希值的信息字节数组。
+ /// 哈希值字节数组。
+ public static byte[] HashWithSHA256(byte[] keyBytes, byte[] msgBytes)
{
- if (secretBytes is null) throw new ArgumentNullException(nameof(secretBytes));
+ if (keyBytes is null) throw new ArgumentNullException(nameof(keyBytes));
if (msgBytes is null) throw new ArgumentNullException(nameof(msgBytes));
- using HMAC hmac = new HMACSHA256(secretBytes);
+#if NET5_0_OR_GREATER
+ return HMACSHA256.HashData(keyBytes, msgBytes);
+#else
+ using HMAC hmac = new HMACSHA256(keyBytes);
return hmac.ComputeHash(msgBytes);
+#endif
}
///
- /// 获取 HMAC-SHA-256 消息认证码。
+ /// 计算 HMAC-SHA-256 哈希值。
///
- /// 密钥。
- /// 文本信息。
- /// 消息认证码。
- public static string HashWithSHA256(string secret, string message)
+ /// 密钥。
+ /// 要计算哈希值的信息。
+ /// 经过十六进制编码的哈希值。
+ public static EncodedString HashWithSHA256(string key, string message)
{
- if (secret is null) throw new ArgumentNullException(nameof(secret));
+ if (key is null) throw new ArgumentNullException(nameof(key));
if (message is null) throw new ArgumentNullException(nameof(message));
- byte[] secretBytes = Encoding.UTF8.GetBytes(secret);
- byte[] msgBytes = Encoding.UTF8.GetBytes(message);
- byte[] hashBytes = HashWithSHA256(secretBytes, msgBytes);
- return BitConverter.ToString(hashBytes).Replace("-", string.Empty);
+ byte[] keyBytes = EncodedString.FromLiteralString(key);
+ byte[] msgBytes = EncodedString.FromLiteralString(message);
+ byte[] hashBytes = HashWithSHA256(keyBytes, msgBytes);
+ return EncodedString.ToHexString(hashBytes);
}
}
}
diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Utilities/MD5Utility.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Utilities/MD5Utility.cs
index 526fe7ea..3580d9d6 100644
--- a/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Utilities/MD5Utility.cs
+++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Utilities/MD5Utility.cs
@@ -1,39 +1,44 @@
using System;
using System.Security.Cryptography;
-using System.Text;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV2.Utilities
{
+ using SKIT.FlurlHttpClient.Primitives;
+
///
/// MD5 算法工具类。
///
public static class MD5Utility
{
///
- /// 获取 MD5 信息摘要。
+ /// 计算 MD5 哈希值。
///
- /// 信息字节数组。
- /// 信息摘要字节数组。
+ /// 要计算哈希值的信息字节数组。
+ /// 哈希值字节数组。
public static byte[] Hash(byte[] bytes)
{
if (bytes is null) throw new ArgumentNullException(nameof(bytes));
+#if NET5_0_OR_GREATER
+ return MD5.HashData(bytes);
+#else
using MD5 md5 = MD5.Create();
return md5.ComputeHash(bytes);
+#endif
}
///
- /// 获取 MD5 信息摘要。
+ /// 计算 MD5 哈希值。
///
- /// 文本信息。
- /// 信息摘要。
- public static string Hash(string message)
+ /// 要计算哈希值的信息。
+ /// 经过十六进制编码的哈希值。
+ public static EncodedString Hash(string message)
{
if (message is null) throw new ArgumentNullException(nameof(message));
- byte[] msgBytes = Encoding.UTF8.GetBytes(message);
+ byte[] msgBytes = EncodedString.FromLiteralString(message);
byte[] hashBytes = Hash(msgBytes);
- return BitConverter.ToString(hashBytes).Replace("-", string.Empty);
+ return EncodedString.ToHexString(hashBytes);
}
}
}
diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Utilities/__Internal/RequestSigner.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Utilities/__Internal/RequestSigner.cs
index 95afc69a..06003af7 100644
--- a/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Utilities/__Internal/RequestSigner.cs
+++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Utilities/__Internal/RequestSigner.cs
@@ -46,12 +46,12 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV2.Utilities
{
case Constants.SignTypes.MD5:
{
- return MD5Utility.Hash(queryString).ToUpper();
+ return MD5Utility.Hash(queryString).Value!.ToUpper();
}
case Constants.SignTypes.HMAC_SHA256:
{
- return HMACUtility.HashWithSHA256(secretValue, queryString).ToUpper();
+ return HMACUtility.HashWithSHA256(secretValue, queryString).Value!.ToUpper();
}
default:
diff --git a/test/SKIT.FlurlHttpClient.Wechat.TenpayV2.UnitTests/TestCase_ToolsAESUtilityTests.cs b/test/SKIT.FlurlHttpClient.Wechat.TenpayV2.UnitTests/TestCase_ToolsAESUtilityTests.cs
index 636b04d9..1c6bceea 100644
--- a/test/SKIT.FlurlHttpClient.Wechat.TenpayV2.UnitTests/TestCase_ToolsAESUtilityTests.cs
+++ b/test/SKIT.FlurlHttpClient.Wechat.TenpayV2.UnitTests/TestCase_ToolsAESUtilityTests.cs
@@ -4,6 +4,8 @@ using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV2.UnitTests
{
+ using SKIT.FlurlHttpClient.Primitives;
+
public class TestCase_ToolsAESUtilityTests
{
[Fact(DisplayName = "测试用例:AES-ECB 解密")]
@@ -12,7 +14,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV2.UnitTests
string key = "01234567890abcdefedcba9876543210";
string cipherText = "l/aL5GyVfl/tw3Lww6GvCQ==";
- string actualPlain = Utilities.AESUtility.DecryptWithECB(encodingKey: Convert.ToBase64String(Encoding.UTF8.GetBytes(key)), encodingCipherText: cipherText);
+ string actualPlain = Utilities.AESUtility.DecryptWithECB(encodingKey: (EncodedString)Convert.ToBase64String(Encoding.UTF8.GetBytes(key)), encodingCipher: (EncodedString)cipherText)!;
string expectedPlain = "SKIT is great!";
Assert.Equal(expectedPlain, actualPlain);