diff --git a/docs/WechatTenpayV3/Basic_RequestSensitiveDataEncryption.md b/docs/WechatTenpayV3/Basic_RequestSensitiveDataEncryption.md index d70b87f6..362f7330 100644 --- a/docs/WechatTenpayV3/Basic_RequestSensitiveDataEncryption.md +++ b/docs/WechatTenpayV3/Basic_RequestSensitiveDataEncryption.md @@ -122,14 +122,14 @@ manager.AddEntry(new CertificateEntry("证书算法,支持 RSA/SM2 两种类 当然,现在的平台证书离过期还有很久,你也可以选择“偷懒”:提前下载好平台证书,在程序启动时记录一次即可。 -每个请求模型对象会包含一个名为 `WechatpayCertificateSerialNumber` 的公共字段,本库会根据该字段的值自动尝试在证书管理器中读取证书内容,并完成请求中敏感信息字段加密: +每个请求模型对象会包含一个名为 `WechatpaySerialNumber` 的公共字段,本库会根据该字段的值自动尝试在证书管理器中读取证书内容,并完成请求中敏感信息字段加密: ```csharp -request.WechatpayCertificateSerialNumber = "平台证书序列号"; +request.WechatpaySerialNumber = "平台证书序列号"; client.EncryptRequestSensitiveProperty(request); ``` -对于存在待加密敏感信息字段的请求模型对象而言,如果你不指定 `WechatpayCertificateSerialNumber` 字段的值,本库会自动从 `CertificateManager` 挑选一个离过期时间最远的证书。 +对于存在待加密敏感信息字段的请求模型对象而言,如果你不指定 `WechatpaySerialNumber` 字段的值,本库会自动从 `CertificateManager` 挑选一个离过期时间最远的证书。 --- diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Extensions/WechatTenpayClientRequestEncryptionExtensions.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Extensions/WechatTenpayClientRequestEncryptionExtensions.cs index 7656c256..22124548 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Extensions/WechatTenpayClientRequestEncryptionExtensions.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Extensions/WechatTenpayClientRequestEncryptionExtensions.cs @@ -25,6 +25,48 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3 if (client is null) throw new ArgumentNullException(nameof(client)); if (request is null) throw new ArgumentNullException(nameof(request)); + switch (client.PlatformAuthScheme) + { + case PlatformAuthScheme.Certificate: + return EncryptRequestSensitivePropertyByCertificate(client, request); + + case PlatformAuthScheme.PublicKey: + return EncryptRequestSensitivePropertyByPublicKey(client, request); + + default: + throw new WechatTenpayException($"Unsupported platform auth scheme: \"{client.PlatformAuthScheme}\"."); + } + } + + /// + /// 异步加密请求中传入的敏感数据。该方法会改变传入的请求模型对象。 + /// + /// + /// + /// + /// + public static Task EncryptRequestSensitivePropertyAsync(this WechatTenpayClient client, TRequest request, CancellationToken cancellationToken = default) + where TRequest : WechatTenpayRequest + { + if (client is null) throw new ArgumentNullException(nameof(client)); + if (request is null) throw new ArgumentNullException(nameof(request)); + + switch (client.PlatformAuthScheme) + { + case PlatformAuthScheme.Certificate: + return EncryptRequestSensitivePropertyByCertificateAsync(client, request); + + case PlatformAuthScheme.PublicKey: + return EncryptRequestSensitivePropertyByPublicKeyAsync(client, request); + + default: + throw new WechatTenpayException($"Unsupported platform auth scheme: \"{client.PlatformAuthScheme}\"."); + } + } + + private static TRequest EncryptRequestSensitivePropertyByCertificate(this WechatTenpayClient client, TRequest request) + where TRequest : WechatTenpayRequest + { try { bool requireEncrypt = request.GetType().IsDefined(typeof(WechatTenpaySensitiveAttribute)); @@ -37,6 +79,34 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3 SignSchemes.WECHATPAY2_SM2_WITH_SM3.Equals(signScheme) ? CertificateEntry.ALGORITHM_TYPE_SM2 : throw new WechatTenpayException($"Failed to encrypt request. Unsupported signing scheme: \"{signScheme}\"."); + string certificate; + if (string.IsNullOrEmpty(request.WechatpaySerialNumber)) + { + // 如果未在请求中指定特定的平台证书序列号,从管理器中取过期时间最远的 + IEnumerable entries = client.PlatformCertificateManager.AllEntries() + .Where(e => e.AlgorithmType == algorithmType) + .OrderByDescending(e => e.ExpireTime); + if (!entries.Any()) + { + throw new WechatTenpayException("Failed to encrypt request, because the platform certificate manager is empty. Please make sure you have downloaded platform (NOT merchant) certificates first."); + } + + CertificateEntry entry = entries.First(); + certificate = entry.Certificate; + request.WechatpaySerialNumber = entry.SerialNumber; + } + else + { + // 如果已在请求中指定特定的平台证书序列号,直接从管理器中取值 + CertificateEntry? entry = client.PlatformCertificateManager.GetEntry(request.WechatpaySerialNumber!); + if (!entry.HasValue) + { + throw new WechatTenpayException($"Failed to encrypt request, because the platform certificate manager does not contain a certificate matched the serial number \"{request.WechatpaySerialNumber}\". Please make sure you have downloaded platform (NOT merchant) certificates first."); + } + + certificate = entry.Value.Certificate; + } + ReflectionHelper.ReplaceObjectStringProperties(request, (_, currentProp, oldValue) => { if (currentProp is null || !currentProp.IsDefined(typeof(WechatTenpaySensitivePropertyAttribute))) @@ -48,34 +118,6 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3 if (attribute is null) return (false, oldValue); - string certificate; - if (string.IsNullOrEmpty(request.WechatpayCertificateSerialNumber)) - { - // 如果未在请求中指定特定的平台证书序列号,从管理器中取过期时间最远的 - IEnumerable entries = client.PlatformCertificateManager.AllEntries() - .Where(e => e.AlgorithmType == algorithmType) - .OrderByDescending(e => e.ExpireTime); - if (!entries.Any()) - { - throw new WechatTenpayException("Failed to encrypt request, because the platform certificate manager is empty. Please make sure you have downloaded platform (NOT merchant) certificates first."); - } - - CertificateEntry entry = entries.First(); - certificate = entry.Certificate; - request.WechatpayCertificateSerialNumber = entry.SerialNumber; - } - else - { - // 如果已在请求中指定特定的平台证书序列号,直接从管理器中取值 - CertificateEntry? entry = client.PlatformCertificateManager.GetEntry(request.WechatpayCertificateSerialNumber!); - if (!entry.HasValue) - { - throw new WechatTenpayException($"Failed to encrypt request, because the platform certificate manager does not contain a certificate matched the serial number \"{request.WechatpayCertificateSerialNumber}\". Please make sure you have downloaded platform (NOT merchant) certificates first."); - } - - certificate = entry.Value.Certificate; - } - string newValue = GenerateEncryptedValueByCertificate(attribute.Algorithm, certificate, oldValue); return (true, newValue); }); @@ -92,30 +134,20 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3 } } - /// - /// 异步加密请求中传入的敏感数据。该方法会改变传入的请求模型对象。 - /// - /// - /// - /// - /// - public static Task EncryptRequestSensitivePropertyAsync(this WechatTenpayClient client, TRequest request, CancellationToken cancellationToken = default) + private static async Task EncryptRequestSensitivePropertyByCertificateAsync(this WechatTenpayClient client, TRequest request, CancellationToken cancellationToken = default) where TRequest : WechatTenpayRequest { - if (client is null) throw new ArgumentNullException(nameof(client)); - if (request is null) throw new ArgumentNullException(nameof(request)); - if (client.PlatformCertificateManager is not ICertificateManagerAsync) { // 降级为同步调用 - return Task.FromResult(EncryptRequestSensitiveProperty(client, request)); + return EncryptRequestSensitivePropertyByCertificate(client, request); } try { bool requireEncrypt = request.GetType().IsDefined(typeof(WechatTenpaySensitiveAttribute)); if (!requireEncrypt) - return Task.FromResult(request); + return request; string signScheme = client.Credentials.SignScheme; string algorithmType = // 签名方式与加密算法保持一致:RSA_SHA256 签名需 RSA 加密,SM3 签名需 SM2 加密 @@ -123,6 +155,36 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3 SignSchemes.WECHATPAY2_SM2_WITH_SM3.Equals(signScheme) ? CertificateEntry.ALGORITHM_TYPE_SM2 : throw new WechatTenpayException($"Failed to encrypt request. Unsupported signing scheme: \"{signScheme}\"."); + string certificate; + if (string.IsNullOrEmpty(request.WechatpaySerialNumber)) + { + if (client.PlatformCertificateManager is null) + throw new WechatTenpayException("Failed to encrypt request, because the platform certificate manager is not initialized."); + + // 如果未在请求中指定特定的平台证书序列号,从管理器中取过期时间最远的 + IEnumerable entries = await ((ICertificateManagerAsync)client.PlatformCertificateManager).AllEntriesAsync(cancellationToken).ConfigureAwait(false); + entries = entries.Where(e => e.AlgorithmType == algorithmType).OrderByDescending(e => e.ExpireTime); + if (!entries.Any()) + { + throw new WechatTenpayException("Failed to encrypt request, because the platform certificate manager is empty. Please make sure you have downloaded platform (NOT merchant) certificates first."); + } + + CertificateEntry entry = entries.First(); + certificate = entry.Certificate; + request.WechatpaySerialNumber = entry.SerialNumber; + } + else + { + // 如果已在请求中指定特定的平台证书序列号,直接从管理器中取值 + CertificateEntry? entry = await ((ICertificateManagerAsync)client.PlatformCertificateManager).GetEntryAsync(request.WechatpaySerialNumber!, cancellationToken).ConfigureAwait(false); + if (!entry.HasValue) + { + throw new WechatTenpayException($"Failed to encrypt request, because the platform certificate manager does not contain a certificate matched the serial number \"{request.WechatpaySerialNumber}\". Please make sure you have downloaded platform (NOT merchant) certificates first."); + } + + certificate = entry.Value.Certificate; + } + ReflectionHelper.ReplaceObjectStringProperties(request, (_, currentProp, oldValue) => { if (currentProp is null || !currentProp.IsDefined(typeof(WechatTenpaySensitivePropertyAttribute))) @@ -134,50 +196,158 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3 if (attribute is null) return (false, oldValue); - string certificate; - if (string.IsNullOrEmpty(request.WechatpayCertificateSerialNumber)) - { - if (client.PlatformCertificateManager is null) - throw new WechatTenpayException("Failed to encrypt request, because the platform certificate manager is not initialized."); - - // 如果未在请求中指定特定的平台证书序列号,从管理器中取过期时间最远的 - IEnumerable entries = ((ICertificateManagerAsync)client.PlatformCertificateManager) - .AllEntriesAsync(cancellationToken) - .ConfigureAwait(false) - .GetAwaiter() - .GetResult() - .Where(e => e.AlgorithmType == algorithmType) - .OrderByDescending(e => e.ExpireTime); - if (!entries.Any()) - { - throw new WechatTenpayException("Failed to encrypt request, because the platform certificate manager is empty. Please make sure you have downloaded platform (NOT merchant) certificates first."); - } - - CertificateEntry entry = entries.First(); - certificate = entry.Certificate; - request.WechatpayCertificateSerialNumber = entry.SerialNumber; - } - else - { - // 如果已在请求中指定特定的平台证书序列号,直接从管理器中取值 - CertificateEntry? entry = ((ICertificateManagerAsync)client.PlatformCertificateManager) - .GetEntryAsync(request.WechatpayCertificateSerialNumber!, cancellationToken) - .ConfigureAwait(false) - .GetAwaiter() - .GetResult(); - if (!entry.HasValue) - { - throw new WechatTenpayException($"Failed to encrypt request, because the platform certificate manager does not contain a certificate matched the serial number \"{request.WechatpayCertificateSerialNumber}\". Please make sure you have downloaded platform (NOT merchant) certificates first."); - } - - certificate = entry.Value.Certificate; - } - string newValue = GenerateEncryptedValueByCertificate(attribute.Algorithm, certificate, oldValue); return (true, newValue); }); - return Task.FromResult(request); + return request; + } + catch (WechatTenpayException) + { + throw; + } + catch (Exception ex) + { + throw new WechatTenpayException("Failed to encrypt request. Please see the inner exception for more details.", ex); + } + } + + private static TRequest EncryptRequestSensitivePropertyByPublicKey(this WechatTenpayClient client, TRequest request) + where TRequest : WechatTenpayRequest + { + try + { + bool requireEncrypt = request.GetType().IsDefined(typeof(WechatTenpaySensitiveAttribute)); + if (!requireEncrypt) + return request; + + string signScheme = client.Credentials.SignScheme; + string algorithmType = // 签名方式与加密算法保持一致:RSA_SHA256 签名需 RSA 加密,SM3 签名需 SM2 加密 + SignSchemes.WECHATPAY2_RSA_2048_WITH_SHA256.Equals(signScheme) ? PublicKeyEntry.ALGORITHM_TYPE_RSA : + SignSchemes.WECHATPAY2_SM2_WITH_SM3.Equals(signScheme) ? PublicKeyEntry.ALGORITHM_TYPE_SM2 : + throw new WechatTenpayException($"Failed to encrypt request. Unsupported signing scheme: \"{signScheme}\"."); + + string publicKey; + if (string.IsNullOrEmpty(request.WechatpaySerialNumber)) + { + // 如果未在请求中指定特定的平台公钥序列号,从管理器中取第一个 + IEnumerable entries = client.PlatformPublicKeyManager.AllEntries() + .Where(e => e.AlgorithmType == algorithmType); + if (!entries.Any()) + { + throw new WechatTenpayException("Failed to encrypt request, because the platform public key manager is empty."); + } + + PublicKeyEntry entry = entries.First(); + publicKey = entry.PublicKey; + request.WechatpaySerialNumber = entry.SerialNumber; + } + else + { + // 如果已在请求中指定特定的平台公钥序列号,直接从管理器中取值 + PublicKeyEntry? entry = client.PlatformPublicKeyManager.GetEntry(request.WechatpaySerialNumber!); + if (!entry.HasValue) + { + throw new WechatTenpayException($"Failed to encrypt request, because the platform public key manager does not contain a key matched the serial number \"{request.WechatpaySerialNumber}\"."); + } + + publicKey = entry.Value.PublicKey; + } + + ReflectionHelper.ReplaceObjectStringProperties(request, (_, currentProp, oldValue) => + { + if (currentProp is null || !currentProp.IsDefined(typeof(WechatTenpaySensitivePropertyAttribute))) + return (false, oldValue); + + WechatTenpaySensitivePropertyAttribute? attribute = currentProp + .GetCustomAttributes() + .FirstOrDefault(attr => attr.Scheme == signScheme); + if (attribute is null) + return (false, oldValue); + + string newValue = GenerateEncryptedValueByPublicKey(attribute.Algorithm, publicKey, oldValue); + return (true, newValue); + }); + + return request; + } + catch (WechatTenpayException) + { + throw; + } + catch (Exception ex) + { + throw new WechatTenpayException("Failed to encrypt request. Please see the inner exception for more details.", ex); + } + } + + private static async Task EncryptRequestSensitivePropertyByPublicKeyAsync(this WechatTenpayClient client, TRequest request, CancellationToken cancellationToken = default) + where TRequest : WechatTenpayRequest + { + if (client.PlatformPublicKeyManager is not IPublicKeyManagerAsync) + { + // 降级为同步调用 + return EncryptRequestSensitivePropertyByPublicKey(client, request); + } + + try + { + bool requireEncrypt = request.GetType().IsDefined(typeof(WechatTenpaySensitiveAttribute)); + if (!requireEncrypt) + return request; + + string signScheme = client.Credentials.SignScheme; + string algorithmType = // 签名方式与加密算法保持一致:RSA_SHA256 签名需 RSA 加密,SM3 签名需 SM2 加密 + SignSchemes.WECHATPAY2_RSA_2048_WITH_SHA256.Equals(signScheme) ? PublicKeyEntry.ALGORITHM_TYPE_RSA : + SignSchemes.WECHATPAY2_SM2_WITH_SM3.Equals(signScheme) ? PublicKeyEntry.ALGORITHM_TYPE_SM2 : + throw new WechatTenpayException($"Failed to encrypt request. Unsupported signing scheme: \"{signScheme}\"."); + + string publicKey; + if (string.IsNullOrEmpty(request.WechatpaySerialNumber)) + { + if (client.PlatformPublicKeyManager is null) + throw new WechatTenpayException("Failed to encrypt request, because the platform public key manager is not initialized."); + + // 如果未在请求中指定特定的平台公钥序列号,从管理器中第一个 + IEnumerable entries = await ((IPublicKeyManagerAsync)client.PlatformPublicKeyManager).AllEntriesAsync(cancellationToken).ConfigureAwait(false); + entries = entries.Where(e => e.AlgorithmType == algorithmType); + if (!entries.Any()) + { + throw new WechatTenpayException("Failed to encrypt request, because the platform public key manager is empty."); + } + + PublicKeyEntry entry = entries.First(); + publicKey = entry.PublicKey; + request.WechatpaySerialNumber = entry.SerialNumber; + } + else + { + // 如果已在请求中指定特定的平台公钥序列号,直接从管理器中取值 + PublicKeyEntry? entry = await ((IPublicKeyManagerAsync)client.PlatformPublicKeyManager).GetEntryAsync(request.WechatpaySerialNumber!, cancellationToken).ConfigureAwait(false); + if (!entry.HasValue) + { + throw new WechatTenpayException($"Failed to encrypt request, because the platform public key manager does not contain a key matched the serial number \"{request.WechatpaySerialNumber}\"."); + } + + publicKey = entry.Value.PublicKey; + } + + ReflectionHelper.ReplaceObjectStringProperties(request, (_, currentProp, oldValue) => + { + if (currentProp is null || !currentProp.IsDefined(typeof(WechatTenpaySensitivePropertyAttribute))) + return (false, oldValue); + + WechatTenpaySensitivePropertyAttribute? attribute = currentProp + .GetCustomAttributes() + .FirstOrDefault(attr => attr.Scheme == signScheme); + if (attribute is null) + return (false, oldValue); + + string newValue = GenerateEncryptedValueByPublicKey(attribute.Algorithm, publicKey, oldValue); + return (true, newValue); + }); + + return request; } catch (WechatTenpayException) { @@ -194,22 +364,44 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3 switch (algorithm) { case EncryptionAlgorithms.RSA_2048_ECB_PKCS8_OAEP_WITH_SHA1_AND_MGF1: - return RSAUtility.EncryptWithECBByCertificate( - certificatePem: certificate, + case EncryptionAlgorithms.RSA_2048_ECB_PKCS1: + { + string publicKey = RSAUtility.ExportPublicKeyFromCertificate(certificate); + return GenerateEncryptedValueByPublicKey(algorithm, publicKey, value); + } + + case EncryptionAlgorithms.SM2_C1C3C2_ASN1: + { + string publicKey = SM2Utility.ExportPublicKeyFromCertificate(certificate); + return GenerateEncryptedValueByPublicKey(algorithm, publicKey, value); + } + + default: + throw new WechatTenpayException($"Failed to encrypt request. Unsupported encryption algorithm: \"{algorithm}\"."); + } + } + + private static string GenerateEncryptedValueByPublicKey(string algorithm, string publicKey, string value) + { + switch (algorithm) + { + case EncryptionAlgorithms.RSA_2048_ECB_PKCS8_OAEP_WITH_SHA1_AND_MGF1: + return RSAUtility.EncryptWithECB( + publicKeyPem: publicKey, plainData: value, paddingMode: RSAUtility.PADDING_MODE_OAEPWITHSHA1ANDMGF1 )!; case EncryptionAlgorithms.RSA_2048_ECB_PKCS1: - return RSAUtility.EncryptWithECBByCertificate( - certificatePem: certificate, + return RSAUtility.EncryptWithECB( + publicKeyPem: publicKey, plainData: value, paddingMode: RSAUtility.PADDING_MODE_PKCS1 )!; case EncryptionAlgorithms.SM2_C1C3C2_ASN1: - return SM2Utility.EncryptByCertificate( - certificatePem: certificate, + return SM2Utility.Encrypt( + publicKeyPem: publicKey, plainData: value, asn1Encoding: true )!; diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Extensions/WechatTenpayClientResponseVerificationExtensions.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Extensions/WechatTenpayClientResponseVerificationExtensions.cs index 7affbcf3..57fd4637 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Extensions/WechatTenpayClientResponseVerificationExtensions.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Extensions/WechatTenpayClientResponseVerificationExtensions.cs @@ -35,7 +35,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3 responseBody: Encoding.UTF8.GetString(response.GetRawBytes()), responseSignature: response.WechatpaySignature, responseSignatureType: response.WechatpaySignatureType, - responseSerialNumber: response.WechatpayCertificateSerialNumber + responseSerialNumber: response.WechatpaySerialNumber ); } @@ -124,7 +124,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3 responseBody: Encoding.UTF8.GetString(response.GetRawBytes()), responseSignature: response.WechatpaySignature, responseSignatureType: response.WechatpaySignatureType, - responseSerialNumber: response.WechatpayCertificateSerialNumber, + responseSerialNumber: response.WechatpaySerialNumber, cancellationToken: cancellationToken ); } diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Extensions/__Internal/WechatTenpayClientSigningExtensions.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Extensions/__Internal/WechatTenpayClientSigningExtensions.cs index 284fab0f..3f741c0f 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Extensions/__Internal/WechatTenpayClientSigningExtensions.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Extensions/__Internal/WechatTenpayClientSigningExtensions.cs @@ -14,42 +14,98 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3 { if (client is null) throw new ArgumentNullException(nameof(client)); - CertificateEntry? entry = client.PlatformCertificateManager.GetEntry(strSerialNumber); - if (!entry.HasValue) + switch (client.PlatformAuthScheme) { - return ErroredResult.Fail(new Exception($"The platform certificate manager does not contain a certificate matched the serial number \"{strSerialNumber}\".")); - } + case PlatformAuthScheme.Certificate: + { + CertificateEntry? entry = client.PlatformCertificateManager.GetEntry(strSerialNumber); + if (!entry.HasValue) + { + return ErroredResult.Fail(new Exception($"The platform certificate manager does not contain a certificate matched the serial number \"{strSerialNumber}\".")); + } - return GenerateSignatureResultByCertificate( - scheme: strSignScheme, - certificate: entry.Value.Certificate, - message: GenerateMessageForSignature(timestamp: strTimestamp, nonce: strNonce, body: strContent), - signature: strSignature - ); + return GenerateSignatureResultByCertificate( + scheme: strSignScheme, + certificate: entry.Value.Certificate, + message: GenerateMessageForSignature(timestamp: strTimestamp, nonce: strNonce, body: strContent), + signature: strSignature + ); + } + + case PlatformAuthScheme.PublicKey: + { + PublicKeyEntry? entry = client.PlatformPublicKeyManager.GetEntry(strSerialNumber); + if (!entry.HasValue) + { + return ErroredResult.Fail(new Exception($"The platform public key manager does not contain a key matched the serial number \"{strSerialNumber}\".")); + } + + return GenerateSignatureResultByPublicKey( + scheme: strSignScheme, + publicKey: entry.Value.PublicKey, + message: GenerateMessageForSignature(timestamp: strTimestamp, nonce: strNonce, body: strContent), + signature: strSignature + ); + } + + default: + return ErroredResult.Fail(new Exception($"Unsupported platform auth scheme: \"{client.PlatformAuthScheme}\".")); + } } public static async Task VerifySignatureAsync(this WechatTenpayClient client, string strTimestamp, string strNonce, string strContent, string strSignature, string strSignScheme, string strSerialNumber, CancellationToken cancellationToken = default) { if (client is null) throw new ArgumentNullException(nameof(client)); - if (client.PlatformCertificateManager is not ICertificateManagerAsync) + switch (client.PlatformAuthScheme) { - // 降级为同步调用 - return VerifySignature(client, strTimestamp, strNonce, strContent, strSignature, strSignScheme, strSerialNumber); - } + case PlatformAuthScheme.Certificate: + { + if (client.PlatformCertificateManager is not ICertificateManagerAsync) + { + // 降级为同步调用 + return VerifySignature(client, strTimestamp, strNonce, strContent, strSignature, strSignScheme, strSerialNumber); + } - CertificateEntry? entry = await ((ICertificateManagerAsync)client.PlatformCertificateManager).GetEntryAsync(strSerialNumber, cancellationToken).ConfigureAwait(false); - if (!entry.HasValue) - { - return ErroredResult.Fail(new Exception($"The platform certificate manager does not contain a certificate matched the serial number \"{strSerialNumber}\".")); - } + CertificateEntry? entry = await ((ICertificateManagerAsync)client.PlatformCertificateManager).GetEntryAsync(strSerialNumber, cancellationToken).ConfigureAwait(false); + if (!entry.HasValue) + { + return ErroredResult.Fail(new Exception($"The platform certificate manager does not contain a certificate matched the serial number \"{strSerialNumber}\".")); + } - return GenerateSignatureResultByCertificate( - scheme: strSignScheme, - certificate: entry.Value.Certificate, - message: GenerateMessageForSignature(timestamp: strTimestamp, nonce: strNonce, body: strContent), - signature: strSignature - ); + return GenerateSignatureResultByCertificate( + scheme: strSignScheme, + certificate: entry.Value.Certificate, + message: GenerateMessageForSignature(timestamp: strTimestamp, nonce: strNonce, body: strContent), + signature: strSignature + ); + } + + case PlatformAuthScheme.PublicKey: + { + if (client.PlatformCertificateManager is not IPublicKeyManagerAsync) + { + // 降级为同步调用 + return VerifySignature(client, strTimestamp, strNonce, strContent, strSignature, strSignScheme, strSerialNumber); + } + + PublicKeyEntry? entry = await ((IPublicKeyManagerAsync)client.PlatformPublicKeyManager).GetEntryAsync(strSerialNumber, cancellationToken).ConfigureAwait(false); + if (!entry.HasValue) + { + return ErroredResult.Fail(new Exception($"The platform public key manager does not contain a key matched the serial number \"{strSerialNumber}\".")); + } + + return GenerateSignatureResultByPublicKey( + scheme: strSignScheme, + publicKey: entry.Value.PublicKey, + message: GenerateMessageForSignature(timestamp: strTimestamp, nonce: strNonce, body: strContent), + signature: strSignature + ); + } + + default: + return ErroredResult.Fail(new Exception($"Unsupported platform auth scheme: \"{client.PlatformAuthScheme}\".")); + } } private static string GenerateMessageForSignature(string timestamp, string nonce, string body) @@ -58,6 +114,42 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3 } private static ErroredResult GenerateSignatureResultByCertificate(string scheme, string certificate, string message, string signature) + { + string publicKey = string.Empty; + + switch (scheme) + { + case SignSchemes.WECHATPAY2_RSA_2048_WITH_SHA256: + { + try + { + publicKey = Utilities.RSAUtility.ExportPublicKeyFromCertificate(certificate); + } + catch (Exception ex) + { + return ErroredResult.Fail(ex); + } + } + break; + + case SignSchemes.WECHATPAY2_SM2_WITH_SM3: + { + try + { + publicKey = Utilities.SM2Utility.ExportPublicKeyFromCertificate(certificate); + } + catch (Exception ex) + { + return ErroredResult.Fail(ex); + } + } + break; + } + + return GenerateSignatureResultByPublicKey(scheme, publicKey, message, signature); + } + + private static ErroredResult GenerateSignatureResultByPublicKey(string scheme, string publicKey, string message, string signature) { ErroredResult result; @@ -67,8 +159,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3 { try { - bool valid = Utilities.RSAUtility.VerifyWithSHA256ByCertificate( - certificatePem: certificate, + bool valid = Utilities.RSAUtility.VerifyWithSHA256( + publicKeyPem: publicKey, messageData: message, encodingSignature: new EncodedString(signature, EncodingKinds.Base64) ); @@ -88,8 +180,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3 { try { - bool valid = Utilities.SM2Utility.VerifyWithSM3ByCertificate( - certificatePem: certificate, + bool valid = Utilities.SM2Utility.VerifyWithSM3( + publicKeyPem: publicKey, messageData: message, encodingSignature: new EncodedString(signature, EncodingKinds.Base64) ); diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Settings/CertificateEntry.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Settings/CertificateEntry.cs index efcae55f..996b2335 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Settings/CertificateEntry.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Settings/CertificateEntry.cs @@ -23,16 +23,16 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Settings /// public string AlgorithmType { get; } - /// - /// 获取证书内容(CRT/CER PEM 格式,即 -----BEGIN CERTIFICATE----- ... -----END CERTIFICATE-----) - /// - public string Certificate { get; } - /// /// 获取证书序列号。 /// public string SerialNumber { get; } + /// + /// 获取证书内容(CRT/CER PEM 格式,即 -----BEGIN CERTIFICATE----- ... -----END CERTIFICATE-----) + /// + public string Certificate { get; } + /// /// 获取生效时间。 /// diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Settings/PlatformAuthScheme.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Settings/PlatformAuthScheme.cs new file mode 100644 index 00000000..5ca20561 --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Settings/PlatformAuthScheme.cs @@ -0,0 +1,18 @@ +namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Settings +{ + /// + /// 微信支付平台认证方案。 + /// + public enum PlatformAuthScheme + { + /// + /// 使用平台证书进行认证。 + /// + Certificate = 0, + + /// + /// 使用平台公钥进行认证。 + /// + PublicKey = 1 + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Settings/PublicKeyEntry.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Settings/PublicKeyEntry.cs new file mode 100644 index 00000000..74e4143a --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Settings/PublicKeyEntry.cs @@ -0,0 +1,109 @@ +using System; + +namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Settings +{ + /// + /// 表示一个微信商户平台公钥实体。 + /// + public partial struct PublicKeyEntry : IEquatable + { + /// + /// 公钥算法类型:RSA。 + /// + public const string ALGORITHM_TYPE_RSA = CertificateEntry.ALGORITHM_TYPE_RSA; + + /// + /// 公钥算法类型:SM2。 + /// + public const string ALGORITHM_TYPE_SM2 = CertificateEntry.ALGORITHM_TYPE_SM2; + + /// + /// 获取公钥算法类型。 + /// 取值范围:RSA、SM2。 + /// + public string AlgorithmType { get; } + + /// + /// 获取公钥序列号。 + /// + public string SerialNumber { get; } + + /// + /// 获取公钥内容(CRT/CER PEM 格式,即 -----BEGIN PUBLIC KEY----- ... -----END PUBLIC KEY-----) + /// + public string PublicKey { get; } + + /// + /// + /// + /// + /// + /// + [Newtonsoft.Json.JsonConstructor] + [System.Text.Json.Serialization.JsonConstructor] + public PublicKeyEntry(string algorithmType, string serialNumber, string publicKey) + { + publicKey = publicKey?.Trim()!; + + if (string.IsNullOrEmpty(algorithmType)) + throw new ArgumentException("The value of `algorithmType` can not be empty.", nameof(algorithmType)); + if (string.IsNullOrEmpty(publicKey)) + throw new ArgumentException("The value of `publicKey` can not be empty.", nameof(publicKey)); + if (string.IsNullOrEmpty(serialNumber)) + throw new ArgumentException("The value of `serialNumber` can not be empty.", nameof(serialNumber)); + if (!ALGORITHM_TYPE_RSA.Equals(algorithmType) && !ALGORITHM_TYPE_SM2.Equals(algorithmType)) + throw new ArgumentException("The value of `algorithmType` an invalid value.", nameof(algorithmType)); + if (!(publicKey.StartsWith("-----BEGIN PUBLIC KEY-----") && publicKey.EndsWith("-----END PUBLIC KEY-----"))) + throw new ArgumentException("The value of `publicKey` is an invalid public key file content.", nameof(publicKey)); + + AlgorithmType = algorithmType; + SerialNumber = serialNumber.ToUpper(); + PublicKey = publicKey; + } + + /// + /// + /// + /// + /// + public bool Equals(PublicKeyEntry other) + { + return string.Equals(AlgorithmType, other.AlgorithmType) && + string.Equals(PublicKey, other.PublicKey) && + string.Equals(SerialNumber, other.SerialNumber); + } + + /// + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) + return false; + if (GetType() != obj.GetType()) + return false; + + return Equals((PublicKeyEntry)obj); + } + + /// + public override int GetHashCode() + { +#if NETCOREAPP || NET5_0_OR_GREATER + return HashCode.Combine(AlgorithmType?.GetHashCode(), PublicKey?.GetHashCode(), SerialNumber?.GetHashCode()); +#else + return (AlgorithmType?.GetHashCode(), PublicKey?.GetHashCode(), SerialNumber?.GetHashCode()).GetHashCode(); +#endif + } + + /// + public static bool operator ==(PublicKeyEntry left, PublicKeyEntry right) + { + return left.Equals(right); + } + + /// + public static bool operator !=(PublicKeyEntry left, PublicKeyEntry right) + { + return !left.Equals(right); + } + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Settings/PublicKeyManager.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Settings/PublicKeyManager.cs new file mode 100644 index 00000000..bdda0919 --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Settings/PublicKeyManager.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Settings +{ + /// + /// 微信商户平台公钥管理器接口。 + /// + public interface IPublicKeyManager + { + /// + /// 获取存储的全部公钥实体。 + /// + /// + IEnumerable AllEntries(); + + /// + /// 添加一个公钥实体。 + /// + /// + void AddEntry(PublicKeyEntry entry); + + /// + /// 根据公钥序列号获取公钥实体。 + /// + /// + /// + PublicKeyEntry? GetEntry(string serialNumber); + + /// + /// 根据公钥序列号移除公钥实体。 + /// + /// + /// + bool RemoveEntry(string serialNumber); + } + + /// + /// 微信商户平台公钥管理器异步接口。 + /// + public interface IPublicKeyManagerAsync : IPublicKeyManager + { + /// + /// 异步获取存储的全部公钥实体。 + /// + /// + /// + Task> AllEntriesAsync(CancellationToken cancellationToken = default); + + /// + /// 异步添加一个公钥实体。 + /// + /// + /// + /// + Task AddEntryAsync(PublicKeyEntry entry, CancellationToken cancellationToken = default); + + /// + /// 异步根据公钥序列号获取公钥实体。 + /// + /// + /// + /// + Task GetEntryAsync(string serialNumber, CancellationToken cancellationToken = default); + + /// + /// 异步根据公钥序列号移除公钥实体。 + /// + /// + /// + /// + Task RemoveEntryAsync(string serialNumber, CancellationToken cancellationToken = default); + } + + /// + /// 一个基于内存实现的 。 + /// + public sealed class InMemoryPublicKeyManager : IPublicKeyManager + { + private readonly ConcurrentDictionary _dict; + + public InMemoryPublicKeyManager() + { + _dict = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); + } + + /// + public IEnumerable AllEntries() + { + return _dict.Values.ToArray(); + } + + /// + public void AddEntry(PublicKeyEntry entry) + { + _dict.AddOrUpdate(entry.SerialNumber, (_) => entry, (_, _) => entry); + } + + /// + public PublicKeyEntry? GetEntry(string serialNumber) + { + if (_dict.TryGetValue(serialNumber, out PublicKeyEntry entry)) + { + return entry; + } + + return null; + } + + /// + public bool RemoveEntry(string serialNumber) + { + return _dict.TryRemove(serialNumber, out _); + } + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/WechatTenpayClient.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/WechatTenpayClient.cs index b284c764..324266b6 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/WechatTenpayClient.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/WechatTenpayClient.cs @@ -12,16 +12,28 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3 /// public class WechatTenpayClient : CommonClientBase, ICommonClient { + private static readonly string ASSEMBLY_VERSION = Assembly.GetAssembly(typeof(WechatTenpayClient))!.GetName()!.Version!.ToString(); + /// /// 获取当前客户端使用的微信支付商户凭证。 /// public Settings.Credentials Credentials { get; } + /// + /// 获取当前客户端使用的微信支付平台认证方案。 + /// + public Settings.PlatformAuthScheme PlatformAuthScheme { get; } + /// /// 获取当前客户端使用的微信支付平台证书管理器。 /// public Settings.ICertificateManager PlatformCertificateManager { get; } + /// + /// 获取当前客户端使用的微信支付平台公钥管理器。 + /// + public Settings.IPublicKeyManager PlatformPublicKeyManager { get; } + /// /// 获取是否自动加密请求中的敏感信息字段。 /// @@ -53,14 +65,16 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3 if (options is null) throw new ArgumentNullException(nameof(options)); Credentials = new Settings.Credentials(options); + PlatformAuthScheme = options.PlatformAuthScheme; PlatformCertificateManager = options.PlatformCertificateManager; + PlatformPublicKeyManager = options.PlatformPublicKeyManager; AutoEncryptRequestSensitiveProperty = options.AutoEncryptRequestSensitiveProperty; AutoDecryptResponseSensitiveProperty = options.AutoDecryptResponseSensitiveProperty; FlurlClient.BaseUrl = options.Endpoint ?? WechatTenpayEndpoints.DEFAULT; FlurlClient.WithHeader(HttpHeaders.Accept, "application/json"); FlurlClient.WithHeader(HttpHeaders.AcceptLanguage, options.AcceptLanguage); - FlurlClient.WithHeader(HttpHeaders.UserAgent, $"OS/{Environment.OSVersion.Platform} SKIT.FlurlHttpClient.Wechat.Tenpay/{Assembly.GetAssembly(typeof(WechatTenpayClient))!.GetName().Version}"); + FlurlClient.WithHeader(HttpHeaders.UserAgent, $"OS/{Environment.OSVersion.Platform} SKIT.FlurlHttpClient.Wechat.Tenpay/{ASSEMBLY_VERSION}"); FlurlClient.WithTimeout(options.Timeout <= 0 ? Timeout.InfiniteTimeSpan : TimeSpan.FromMilliseconds(options.Timeout)); Interceptors.Add(new Interceptors.WechatTenpayRequestSigningInterceptor( @@ -87,9 +101,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3 this.EncryptRequestSensitiveProperty(request); } - if (request.WechatpayCertificateSerialNumber is not null) + if (request.WechatpaySerialNumber is not null) { - flurlRequest.WithHeader("Wechatpay-Serial", request.WechatpayCertificateSerialNumber); + flurlRequest.WithHeader("Wechatpay-Serial", request.WechatpaySerialNumber); } return flurlRequest; diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/WechatTenpayClientOptions.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/WechatTenpayClientOptions.cs index cc367aa1..4ea93076 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/WechatTenpayClientOptions.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/WechatTenpayClientOptions.cs @@ -73,12 +73,32 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3 /// public bool AutoDecryptResponseSensitiveProperty { get; set; } + /// + /// 获取或设置微信支付平台认证方案。 + /// 默认值: + /// + public Settings.PlatformAuthScheme PlatformAuthScheme { get; set; } = Settings.PlatformAuthScheme.Certificate; + /// /// 获取或设置微信支付平台证书管理器。 /// + /// 仅当 的值为 时有效。 + /// + /// /// 默认值: /// /// public Settings.ICertificateManager PlatformCertificateManager { get; set; } = new Settings.InMemoryCertificateManager(); + + /// + /// 获取或设置微信支付平台公钥管理器。 + /// + /// 仅当 的值为 时有效。 + /// + /// + /// 默认值: + /// + /// + public Settings.IPublicKeyManager PlatformPublicKeyManager { get; set; } = new Settings.InMemoryPublicKeyManager(); } } diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/WechatTenpayRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/WechatTenpayRequest.cs index 9cc0d639..5e250565 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/WechatTenpayRequest.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/WechatTenpayRequest.cs @@ -1,3 +1,5 @@ +using System; + namespace SKIT.FlurlHttpClient.Wechat.TenpayV3 { /// @@ -8,8 +10,16 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3 /// /// 获取或设置微信请求使用的微信支付平台证书序列号。 /// + [Obsolete("后续版本该属性将被移除,请使用 `WechatpaySerialNumber` 属性替代。", error: true)] [Newtonsoft.Json.JsonIgnore] [System.Text.Json.Serialization.JsonIgnore] - public virtual string? WechatpayCertificateSerialNumber { get; set; } + public virtual string? WechatpayCertificateSerialNumber { get { return WechatpaySerialNumber; } set { WechatpaySerialNumber = value; } } + + /// + /// 获取或设置微信请求使用的微信支付平台证书或公钥序列号。 + /// + [Newtonsoft.Json.JsonIgnore] + [System.Text.Json.Serialization.JsonIgnore] + public virtual string? WechatpaySerialNumber { get; set; } } } diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/WechatTenpayResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/WechatTenpayResponse.cs index 50086f86..d21d7a01 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/WechatTenpayResponse.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/WechatTenpayResponse.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; namespace SKIT.FlurlHttpClient.Wechat.TenpayV3 @@ -66,9 +67,17 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3 /// /// 获取微信应答签名使用的微信支付平台证书序列号。 /// + [Obsolete("后续版本该属性将被移除,请使用 `WechatpaySerialNumber` 属性替代。", error: true)] [Newtonsoft.Json.JsonIgnore] [System.Text.Json.Serialization.JsonIgnore] - public string WechatpayCertificateSerialNumber { get { return GetRawHeaders().GetFirstValueOrEmpty("Wechatpay-Serial"); } } + public string WechatpayCertificateSerialNumber { get { return WechatpaySerialNumber; } } + + /// + /// 获取微信应答签名使用的微信支付平台证书或公钥序列号。 + /// + [Newtonsoft.Json.JsonIgnore] + [System.Text.Json.Serialization.JsonIgnore] + public string WechatpaySerialNumber { get { return GetRawHeaders().GetFirstValueOrEmpty("Wechatpay-Serial"); } } /// /// 获取一个值,该值指示调用微信 API 是否成功。 diff --git a/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/TestCase_RequestEncryptionForGlobalTests.cs b/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/TestCase_RequestEncryptionForGlobalTests.cs index c51112df..259108f1 100644 --- a/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/TestCase_RequestEncryptionForGlobalTests.cs +++ b/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/TestCase_RequestEncryptionForGlobalTests.cs @@ -38,7 +38,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests Assert.NotEqual(MOCK_PLAIN_STR, request.CertificateName!); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.CertificateId!)); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.CertificateName!)); - Assert.Equal(MOCK_CERT_SN, request.WechatpayCertificateSerialNumber!, ignoreCase: true); + Assert.Equal(MOCK_CERT_SN, request.WechatpaySerialNumber!, ignoreCase: true); } if (!string.IsNullOrEmpty(TestConfigs.WechatMerchantRSACertificatePrivateKey)) @@ -83,7 +83,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.Contact!.ContactName!)); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.Contact!.MobileNumber!)); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.Contact!.Email!)); - Assert.Equal(MOCK_CERT_SN, request.WechatpayCertificateSerialNumber!, ignoreCase: true); + Assert.Equal(MOCK_CERT_SN, request.WechatpaySerialNumber!, ignoreCase: true); } if (!string.IsNullOrEmpty(TestConfigs.WechatMerchantRSACertificatePrivateKey)) diff --git a/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/TestCase_RequestEncryptionTests.cs b/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/TestCase_RequestEncryptionTests.cs index 17ec4d45..b3d6e9dd 100644 --- a/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/TestCase_RequestEncryptionTests.cs +++ b/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/TestCase_RequestEncryptionTests.cs @@ -41,7 +41,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests Assert.NotEqual(MOCK_PLAIN_STR, request.AccountNumber!); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.AccountName!)); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.AccountNumber!)); - Assert.Equal(MOCK_CERT_SN, request.WechatpayCertificateSerialNumber!, ignoreCase: true); + Assert.Equal(MOCK_CERT_SN, request.WechatpaySerialNumber!, ignoreCase: true); } if (!string.IsNullOrEmpty(TestConfigs.WechatMerchantRSACertificatePrivateKey)) @@ -130,7 +130,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.UBOList![0].IdName!)); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.UBOList![0].IdNumber!)); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.UBOList![0].IdAddress!)); - Assert.Equal(MOCK_CERT_SN, request.WechatpayCertificateSerialNumber!, ignoreCase: true); + Assert.Equal(MOCK_CERT_SN, request.WechatpaySerialNumber!, ignoreCase: true); } if (!string.IsNullOrEmpty(TestConfigs.WechatMerchantRSACertificatePrivateKey)) @@ -249,7 +249,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.Subject!.UBOList![0].IdAddress!)); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.BankAccount!.AccountName!)); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.BankAccount!.AccountNumber!)); - Assert.Equal(MOCK_CERT_SN, request.WechatpayCertificateSerialNumber!, ignoreCase: true); + Assert.Equal(MOCK_CERT_SN, request.WechatpaySerialNumber!, ignoreCase: true); } if (!string.IsNullOrEmpty(TestConfigs.WechatMerchantRSACertificatePrivateKey)) @@ -308,7 +308,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests { Assert.NotEqual(MOCK_PLAIN_STR, request.ReceiverList![0].Name!); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.ReceiverList![0].Name!)); - Assert.Equal(MOCK_CERT_SN, request.WechatpayCertificateSerialNumber!, ignoreCase: true); + Assert.Equal(MOCK_CERT_SN, request.WechatpaySerialNumber!, ignoreCase: true); } if (!string.IsNullOrEmpty(TestConfigs.WechatMerchantRSACertificatePrivateKey)) @@ -361,7 +361,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests { Assert.NotEqual(MOCK_PLAIN_STR, request.AccountNumber!); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.AccountNumber!)); - Assert.Equal(MOCK_CERT_SN, request.WechatpayCertificateSerialNumber!, ignoreCase: true); + Assert.Equal(MOCK_CERT_SN, request.WechatpaySerialNumber!, ignoreCase: true); } if (!string.IsNullOrEmpty(TestConfigs.WechatMerchantRSACertificatePrivateKey)) @@ -474,7 +474,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.UBOList![0].IdAddress!)); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.BankAccount!.AccountName!)); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.BankAccount!.AccountNumber!)); - Assert.Equal(MOCK_CERT_SN, request.WechatpayCertificateSerialNumber!, ignoreCase: true); + Assert.Equal(MOCK_CERT_SN, request.WechatpaySerialNumber!, ignoreCase: true); } if (!string.IsNullOrEmpty(TestConfigs.WechatMerchantRSACertificatePrivateKey)) @@ -527,7 +527,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests { Assert.NotEqual(MOCK_PLAIN_STR, request.UserName!); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.UserName!)); - Assert.Equal(MOCK_CERT_SN, request.WechatpayCertificateSerialNumber!, ignoreCase: true); + Assert.Equal(MOCK_CERT_SN, request.WechatpaySerialNumber!, ignoreCase: true); } if (!string.IsNullOrEmpty(TestConfigs.WechatMerchantRSACertificatePrivateKey)) @@ -586,7 +586,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests { Assert.NotEqual(MOCK_PLAIN_STR, request.ReceiverList![0].Name!); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.ReceiverList![0].Name!)); - Assert.Equal(MOCK_CERT_SN, request.WechatpayCertificateSerialNumber!, ignoreCase: true); + Assert.Equal(MOCK_CERT_SN, request.WechatpaySerialNumber!, ignoreCase: true); } if (!string.IsNullOrEmpty(TestConfigs.WechatMerchantRSACertificatePrivateKey)) @@ -639,7 +639,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests { Assert.NotEqual(MOCK_PLAIN_STR, request.UserName!); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.UserName!)); - Assert.Equal(MOCK_CERT_SN, request.WechatpayCertificateSerialNumber!, ignoreCase: true); + Assert.Equal(MOCK_CERT_SN, request.WechatpaySerialNumber!, ignoreCase: true); } if (!string.IsNullOrEmpty(TestConfigs.WechatMerchantRSACertificatePrivateKey)) @@ -695,7 +695,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests Assert.NotEqual(MOCK_PLAIN_STR, request.RealName!); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.BankAccountNumber!)); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.RealName!)); - Assert.Equal(MOCK_CERT_SN, request.WechatpayCertificateSerialNumber!, ignoreCase: true); + Assert.Equal(MOCK_CERT_SN, request.WechatpaySerialNumber!, ignoreCase: true); } if (!string.IsNullOrEmpty(TestConfigs.WechatMerchantRSACertificatePrivateKey)) @@ -763,7 +763,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.Identity!.CredentialNumber!)); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.BankCard!.BankCardNumber!)); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.BankCard!.MobileNumber!)); - Assert.Equal(MOCK_CERT_SN, request.WechatpayCertificateSerialNumber!, ignoreCase: true); + Assert.Equal(MOCK_CERT_SN, request.WechatpaySerialNumber!, ignoreCase: true); } if (!string.IsNullOrEmpty(TestConfigs.WechatMerchantRSACertificatePrivateKey)) @@ -816,7 +816,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests { Assert.NotEqual(MOCK_PLAIN_STR, request.MobileNumber!); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.MobileNumber!)); - Assert.Equal(MOCK_CERT_SN, request.WechatpayCertificateSerialNumber!, ignoreCase: true); + Assert.Equal(MOCK_CERT_SN, request.WechatpaySerialNumber!, ignoreCase: true); } if (!string.IsNullOrEmpty(TestConfigs.WechatMerchantRSACertificatePrivateKey)) @@ -872,7 +872,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests { Assert.NotEqual(MOCK_PLAIN_STR, request.MerchantContactInformation!.ConsultationPhoneNumber!); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.MerchantContactInformation!.ConsultationPhoneNumber!)); - Assert.Equal(MOCK_CERT_SN, request.WechatpayCertificateSerialNumber!, ignoreCase: true); + Assert.Equal(MOCK_CERT_SN, request.WechatpaySerialNumber!, ignoreCase: true); } if (!string.IsNullOrEmpty(TestConfigs.WechatMerchantRSACertificatePrivateKey)) @@ -944,7 +944,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.PayeeInfo!.BankAccount!.AccountNumber)); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.PayeeInfo!.Identity!.IdName!)); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.PayeeInfo!.Identity!.IdNumber!)); - Assert.Equal(MOCK_CERT_SN, request.WechatpayCertificateSerialNumber!, ignoreCase: true); + Assert.Equal(MOCK_CERT_SN, request.WechatpaySerialNumber!, ignoreCase: true); } if (!string.IsNullOrEmpty(TestConfigs.WechatMerchantRSACertificatePrivateKey)) @@ -1000,7 +1000,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests Assert.NotEqual(MOCK_PLAIN_STR, request.IdCardNumber!); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.PhoneNumber!)); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.IdCardNumber!)); - Assert.Equal(MOCK_CERT_SN, request.WechatpayCertificateSerialNumber!, ignoreCase: true); + Assert.Equal(MOCK_CERT_SN, request.WechatpaySerialNumber!, ignoreCase: true); } if (!string.IsNullOrEmpty(TestConfigs.WechatMerchantRSACertificatePrivateKey)) @@ -1056,7 +1056,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests Assert.NotEqual(MOCK_PLAIN_STR, request.IdCardNumber!); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.UserName!)); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.IdCardNumber!)); - Assert.Equal(MOCK_CERT_SN, request.WechatpayCertificateSerialNumber!, ignoreCase: true); + Assert.Equal(MOCK_CERT_SN, request.WechatpaySerialNumber!, ignoreCase: true); } if (!string.IsNullOrEmpty(TestConfigs.WechatMerchantRSACertificatePrivateKey)) @@ -1115,7 +1115,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests Assert.NotEqual(MOCK_PLAIN_STR, request.Buyer!.UserEmail!); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.Buyer!.UserMobileNumber!)); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.Buyer!.UserEmail!)); - Assert.Equal(MOCK_CERT_SN, request.WechatpayCertificateSerialNumber!, ignoreCase: true); + Assert.Equal(MOCK_CERT_SN, request.WechatpaySerialNumber!, ignoreCase: true); } if (!string.IsNullOrEmpty(TestConfigs.WechatMerchantRSACertificatePrivateKey)) @@ -1174,7 +1174,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests Assert.NotEqual(MOCK_PLAIN_STR, request.Buyer!.UserEmail!); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.Buyer!.UserMobileNumber!)); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.Buyer!.UserEmail!)); - Assert.Equal(MOCK_CERT_SN, request.WechatpayCertificateSerialNumber!, ignoreCase: true); + Assert.Equal(MOCK_CERT_SN, request.WechatpaySerialNumber!, ignoreCase: true); } if (!string.IsNullOrEmpty(TestConfigs.WechatMerchantRSACertificatePrivateKey)) @@ -1233,7 +1233,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests Assert.NotEqual(MOCK_PLAIN_STR, request.RealIdentity!.IdCardNumber); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.RealIdentity!.RealName)); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.RealIdentity!.IdCardNumber)); - Assert.Equal(MOCK_CERT_SN, request.WechatpayCertificateSerialNumber!, ignoreCase: true); + Assert.Equal(MOCK_CERT_SN, request.WechatpaySerialNumber!, ignoreCase: true); } if (!string.IsNullOrEmpty(TestConfigs.WechatMerchantRSACertificatePrivateKey)) @@ -1292,7 +1292,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests Assert.NotEqual(MOCK_PLAIN_STR, request.RealIdentity!.IdCardNumber); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.RealIdentity!.RealName)); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.RealIdentity!.IdCardNumber)); - Assert.Equal(MOCK_CERT_SN, request.WechatpayCertificateSerialNumber!, ignoreCase: true); + Assert.Equal(MOCK_CERT_SN, request.WechatpaySerialNumber!, ignoreCase: true); } if (!string.IsNullOrEmpty(TestConfigs.WechatMerchantRSACertificatePrivateKey)) @@ -1351,7 +1351,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests Assert.NotEqual(MOCK_PLAIN_STR, request.RealIdentity!.IdCardNumber); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.RealIdentity!.RealName)); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.RealIdentity!.IdCardNumber)); - Assert.Equal(MOCK_CERT_SN, request.WechatpayCertificateSerialNumber!, ignoreCase: true); + Assert.Equal(MOCK_CERT_SN, request.WechatpaySerialNumber!, ignoreCase: true); } if (!string.IsNullOrEmpty(TestConfigs.WechatMerchantRSACertificatePrivateKey)) @@ -1407,7 +1407,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests Assert.NotEqual(MOCK_PLAIN_STR, request.IdCardNumber!); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.UserName!)); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.IdCardNumber!)); - Assert.Equal(MOCK_CERT_SN, request.WechatpayCertificateSerialNumber!, ignoreCase: true); + Assert.Equal(MOCK_CERT_SN, request.WechatpaySerialNumber!, ignoreCase: true); } if (!string.IsNullOrEmpty(TestConfigs.WechatMerchantRSACertificatePrivateKey)) @@ -1463,7 +1463,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests Assert.NotEqual(MOCK_PLAIN_STR, request.IdCardNumber!); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.UserName!)); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.IdCardNumber!)); - Assert.Equal(MOCK_CERT_SN, request.WechatpayCertificateSerialNumber!, ignoreCase: true); + Assert.Equal(MOCK_CERT_SN, request.WechatpaySerialNumber!, ignoreCase: true); } if (!string.IsNullOrEmpty(TestConfigs.WechatMerchantRSACertificatePrivateKey)) @@ -1519,7 +1519,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests Assert.NotEqual(MOCK_PLAIN_STR, request.IdCardNumber!); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.UserName!)); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.IdCardNumber!)); - Assert.Equal(MOCK_CERT_SN, request.WechatpayCertificateSerialNumber!, ignoreCase: true); + Assert.Equal(MOCK_CERT_SN, request.WechatpaySerialNumber!, ignoreCase: true); } if (!string.IsNullOrEmpty(TestConfigs.WechatMerchantRSACertificatePrivateKey)) @@ -1571,7 +1571,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests static void AssertMockRequestModel(Models.ApplyPlatformSolutionMerchantTransferReservationRequest request, Func decryptor) { Assert.NotEqual(MOCK_PLAIN_STR, request.UserName!); - Assert.Equal(MOCK_CERT_SN, request.WechatpayCertificateSerialNumber!, ignoreCase: true); + Assert.Equal(MOCK_CERT_SN, request.WechatpaySerialNumber!, ignoreCase: true); } if (!string.IsNullOrEmpty(TestConfigs.WechatMerchantRSACertificatePrivateKey)) @@ -1630,7 +1630,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests { Assert.NotEqual(MOCK_PLAIN_STR, request.ReceiverList![0].Name!); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.ReceiverList![0].Name!)); - Assert.Equal(MOCK_CERT_SN, request.WechatpayCertificateSerialNumber!, ignoreCase: true); + Assert.Equal(MOCK_CERT_SN, request.WechatpaySerialNumber!, ignoreCase: true); } if (!string.IsNullOrEmpty(TestConfigs.WechatMerchantRSACertificatePrivateKey)) @@ -1683,7 +1683,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests { Assert.NotEqual(MOCK_PLAIN_STR, request.Name!); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.Name!)); - Assert.Equal(MOCK_CERT_SN, request.WechatpayCertificateSerialNumber!, ignoreCase: true); + Assert.Equal(MOCK_CERT_SN, request.WechatpaySerialNumber!, ignoreCase: true); } if (!string.IsNullOrEmpty(TestConfigs.WechatMerchantRSACertificatePrivateKey)) @@ -1739,7 +1739,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests Assert.NotEqual(MOCK_PLAIN_STR, request.RealName!); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.BankAccountNumber!)); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.RealName!)); - Assert.Equal(MOCK_CERT_SN, request.WechatpayCertificateSerialNumber!, ignoreCase: true); + Assert.Equal(MOCK_CERT_SN, request.WechatpaySerialNumber!, ignoreCase: true); } if (!string.IsNullOrEmpty(TestConfigs.WechatMerchantRSACertificatePrivateKey)) @@ -1795,7 +1795,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests Assert.NotEqual(MOCK_PLAIN_STR, request.UserMobile!); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.UserName!)); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.UserMobile!)); - Assert.Equal(MOCK_CERT_SN, request.WechatpayCertificateSerialNumber!, ignoreCase: true); + Assert.Equal(MOCK_CERT_SN, request.WechatpaySerialNumber!, ignoreCase: true); } if (!string.IsNullOrEmpty(TestConfigs.WechatMerchantRSACertificatePrivateKey)) @@ -1848,7 +1848,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests { Assert.NotEqual(MOCK_PLAIN_STR, request.UserMobile!); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.UserMobile!)); - Assert.Equal(MOCK_CERT_SN, request.WechatpayCertificateSerialNumber!, ignoreCase: true); + Assert.Equal(MOCK_CERT_SN, request.WechatpaySerialNumber!, ignoreCase: true); } if (!string.IsNullOrEmpty(TestConfigs.WechatMerchantRSACertificatePrivateKey)) @@ -1904,7 +1904,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests Assert.NotEqual(MOCK_PLAIN_STR, request.UserMobile!); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.UserName!)); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.UserMobile!)); - Assert.Equal(MOCK_CERT_SN, request.WechatpayCertificateSerialNumber!, ignoreCase: true); + Assert.Equal(MOCK_CERT_SN, request.WechatpaySerialNumber!, ignoreCase: true); } if (!string.IsNullOrEmpty(TestConfigs.WechatMerchantRSACertificatePrivateKey)) @@ -1960,7 +1960,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests Assert.NotEqual(MOCK_PLAIN_STR, request.DriverIdCardNumber!); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.DriverName!)); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.DriverIdCardNumber!)); - Assert.Equal(MOCK_CERT_SN, request.WechatpayCertificateSerialNumber!, ignoreCase: true); + Assert.Equal(MOCK_CERT_SN, request.WechatpaySerialNumber!, ignoreCase: true); } if (!string.IsNullOrEmpty(TestConfigs.WechatMerchantRSACertificatePrivateKey)) @@ -2022,7 +2022,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests Assert.NotEqual(MOCK_PLAIN_STR, request.TransferDetailList![0].UserIdCardNumber!); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.TransferDetailList![0].UserName!)); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.TransferDetailList![0].UserIdCardNumber!)); - Assert.Equal(MOCK_CERT_SN, request.WechatpayCertificateSerialNumber!, ignoreCase: true); + Assert.Equal(MOCK_CERT_SN, request.WechatpaySerialNumber!, ignoreCase: true); } if (!string.IsNullOrEmpty(TestConfigs.WechatMerchantRSACertificatePrivateKey)) @@ -2084,7 +2084,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.Identify!.RealName!)); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.Identify!.CredentialNumber!)); Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.BankCardNumber!)); - Assert.Equal(MOCK_CERT_SN, request.WechatpayCertificateSerialNumber!, ignoreCase: true); + Assert.Equal(MOCK_CERT_SN, request.WechatpaySerialNumber!, ignoreCase: true); } if (!string.IsNullOrEmpty(TestConfigs.WechatMerchantRSACertificatePrivateKey)) diff --git a/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/TestCase_ResponseVerificationTests.cs b/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/TestCase_ResponseVerificationTests.cs index f77d244a..0dd3c238 100644 --- a/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/TestCase_ResponseVerificationTests.cs +++ b/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/TestCase_ResponseVerificationTests.cs @@ -22,7 +22,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests Assert.NotNull(response.WechatpayTimestamp); Assert.NotNull(response.WechatpaySignature); Assert.NotNull(response.WechatpaySignatureType); - Assert.NotNull(response.WechatpayCertificateSerialNumber); + Assert.NotNull(response.WechatpaySerialNumber); } [Fact(DisplayName = "测试用例:验证响应签名(基于 SM2)")] @@ -41,7 +41,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests Assert.NotNull(response.WechatpayTimestamp); Assert.NotNull(response.WechatpaySignature); Assert.NotNull(response.WechatpaySignatureType); - Assert.NotNull(response.WechatpayCertificateSerialNumber); + Assert.NotNull(response.WechatpaySerialNumber); } } }