feat(tenpayv3): 新增加密中请求中敏感信息字段的扩展方法

This commit is contained in:
Fu Diwei
2021-11-25 18:42:54 +08:00
parent 906c667117
commit 9ae4c09a82
20 changed files with 202 additions and 13 deletions

View File

@@ -0,0 +1,24 @@
using System;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Exceptions
{
public class WechatTenpayRequestEncryptionException : WechatTenpayException
{
/// <inheritdoc/>
internal WechatTenpayRequestEncryptionException()
{
}
/// <inheritdoc/>
internal WechatTenpayRequestEncryptionException(string message)
: base(message)
{
}
/// <inheritdoc/>
internal WechatTenpayRequestEncryptionException(string message, Exception innerException)
: base(message, innerException)
{
}
}
}

View File

@@ -65,7 +65,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
{ {
try try
{ {
var cert = client.CertificateManager.GetEntry(callbackSerialNumber)!; var cert = client.CertificateManager.GetEntry(callbackSerialNumber);
if (!cert.HasValue) if (!cert.HasValue)
{ {
error = new Exceptions.WechatTenpayEventVerificationException("Verify signature of event failed, because there is no platform certificate matched the serial number."); error = new Exceptions.WechatTenpayEventVerificationException("Verify signature of event failed, because there is no platform certificate matched the serial number.");

View File

@@ -0,0 +1,82 @@
using System;
using System.Linq;
using System.Reflection;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
{
/// <summary>
/// 为 <see cref="WechatTenpayClient"/> 提供请求模型敏感数据加密的扩展方法。
/// </summary>
public static class WechatTenpayClientRequestEncryptionExtensions
{
/// <summary>
/// <para>加密请求中传入的敏感数据。该方法会改变传入的请求模型对象。</para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <returns></returns>
public static TRequest EncryptRequestSensitiveProperty<TRequest>(this WechatTenpayClient client, TRequest request)
where TRequest : WechatTenpayRequest
{
if (client == null) throw new ArgumentNullException(nameof(client));
if (request == null) throw new ArgumentNullException(nameof(request));
try
{
// 遍历并加密被标记为敏感数据的字段
Utilities.ReflectionUtility.ReplacePropertyStringValue(ref request, (obj, prop, value) =>
{
var attr = prop.GetCustomAttribute<WechatTenpaySensitivePropertyAttribute>();
if (attr == null)
return value;
if (Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB.Equals(attr.Algorithm))
{
if (client.CertificateManager == null)
throw new Exceptions.WechatTenpayRequestEncryptionException("Encrypt request failed, because there is no platform certificate in the manager.");
string certificate;
if (!string.IsNullOrEmpty(request.WechatpayCertSerialNumber))
{
// 如果已在请求中指定特定的平台证书序列号,直接从管理器中取值
var cert = client.CertificateManager.GetEntry(request.WechatpayCertSerialNumber!);
if (!cert.HasValue)
{
throw new Exceptions.WechatTenpayEventVerificationException("Encrypt request failed, because there is no platform certificate matched the serial number.");
}
certificate = cert.Value.Certificate;
}
else
{
// 如果未在请求中指定特定的平台证书序列号,从管理器中取过期时间最远的
var certs = client.CertificateManager.AllEntries().OrderByDescending(e => e.ExpireTime);
if (!certs.Any())
{
throw new Exceptions.WechatTenpayEventVerificationException("Encrypt request failed, because there is no platform certificate in the manager.");
}
certificate = certs.First().Certificate;
}
return Utilities.RSAUtility.EncryptWithECBByCertificate(
certificate: certificate,
plainText: value
);
}
else
{
throw new Exceptions.WechatTenpayRequestEncryptionException("Unsupported encryption algorithm.");
}
});
}
catch (Exception ex) when (!(ex is Exceptions.WechatTenpayRequestEncryptionException))
{
throw new Exceptions.WechatTenpayRequestEncryptionException("Encrypt request failed. Please see the `InnerException` for more details.", ex);
}
return request;
}
}
}

View File

@@ -1,17 +1,15 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection; using System.Reflection;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3 namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
{ {
/// <summary> /// <summary>
/// 为 <see cref="WechatTenpayClient"/> 提供响应敏感数据解密的扩展方法。 /// 为 <see cref="WechatTenpayClient"/> 提供响应模型敏感数据解密的扩展方法。
/// </summary> /// </summary>
public static class WechatTenpayClientResponseDecryptionExtensions public static class WechatTenpayClientResponseDecryptionExtensions
{ {
/// <summary> /// <summary>
/// <para>解密响应中返回的敏感数据。该方法会改变传入的响应信息。</para> /// <para>解密响应中返回的敏感数据。该方法会改变传入的响应模型对象。</para>
/// </summary> /// </summary>
/// <param name="client"></param> /// <param name="client"></param>
/// <param name="response"></param> /// <param name="response"></param>
@@ -22,9 +20,6 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
if (client == null) throw new ArgumentNullException(nameof(client)); if (client == null) throw new ArgumentNullException(nameof(client));
if (response == null) throw new ArgumentNullException(nameof(response)); if (response == null) throw new ArgumentNullException(nameof(response));
if (string.IsNullOrEmpty(client.Credentials.MerchantCertPrivateKey))
throw new Exceptions.WechatTenpayResponseDecryptionException("Decrypt response failed, because there is no merchant private key.");
if (!response.IsSuccessful()) if (!response.IsSuccessful())
throw new Exceptions.WechatTenpayResponseDecryptionException("Decrypt response failed, because the response is not successful."); throw new Exceptions.WechatTenpayResponseDecryptionException("Decrypt response failed, because the response is not successful.");
@@ -40,6 +35,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
{ {
if (Constants.EncryptionAlgorithms.AEAD_AES_256_GCM.Equals(certificateModel.EncryptCertificate?.Algorithm)) if (Constants.EncryptionAlgorithms.AEAD_AES_256_GCM.Equals(certificateModel.EncryptCertificate?.Algorithm))
{ {
if (string.IsNullOrEmpty(client.Credentials.MerchantCertPrivateKey))
throw new Exceptions.WechatTenpayResponseDecryptionException("Decrypt response failed, because there is no merchant private key.");
certificateModel.EncryptCertificate.CipherText = Utilities.AESUtility.DecryptWithGCM( certificateModel.EncryptCertificate.CipherText = Utilities.AESUtility.DecryptWithGCM(
key: client.Credentials.MerchantV3Secret, key: client.Credentials.MerchantV3Secret,
iv: certificateModel.EncryptCertificate.Nonce, iv: certificateModel.EncryptCertificate.Nonce,

View File

@@ -17,6 +17,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("contact_name")] [Newtonsoft.Json.JsonProperty("contact_name")]
[System.Text.Json.Serialization.JsonPropertyName("contact_name")] [System.Text.Json.Serialization.JsonPropertyName("contact_name")]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string Name { get; set; } = string.Empty; public string Name { get; set; } = string.Empty;
/// <summary> /// <summary>
@@ -24,6 +25,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("mobile_phone")] [Newtonsoft.Json.JsonProperty("mobile_phone")]
[System.Text.Json.Serialization.JsonPropertyName("mobile_phone")] [System.Text.Json.Serialization.JsonPropertyName("mobile_phone")]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string Mobile { get; set; } = string.Empty; public string Mobile { get; set; } = string.Empty;
/// <summary> /// <summary>
@@ -31,6 +33,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("contact_id_number")] [Newtonsoft.Json.JsonProperty("contact_id_number")]
[System.Text.Json.Serialization.JsonPropertyName("contact_id_number")] [System.Text.Json.Serialization.JsonPropertyName("contact_id_number")]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string? IdCardNumber { get; set; } public string? IdCardNumber { get; set; }
/// <summary> /// <summary>
@@ -45,6 +48,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("contact_email")] [Newtonsoft.Json.JsonProperty("contact_email")]
[System.Text.Json.Serialization.JsonPropertyName("contact_email")] [System.Text.Json.Serialization.JsonPropertyName("contact_email")]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string Email { get; set; } = string.Empty; public string Email { get; set; } = string.Empty;
} }
@@ -198,6 +202,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("id_card_name")] [Newtonsoft.Json.JsonProperty("id_card_name")]
[System.Text.Json.Serialization.JsonPropertyName("id_card_name")] [System.Text.Json.Serialization.JsonPropertyName("id_card_name")]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string IdCardName { get; set; } = string.Empty; public string IdCardName { get; set; } = string.Empty;
/// <summary> /// <summary>
@@ -205,6 +210,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("id_card_number")] [Newtonsoft.Json.JsonProperty("id_card_number")]
[System.Text.Json.Serialization.JsonPropertyName("id_card_number")] [System.Text.Json.Serialization.JsonPropertyName("id_card_number")]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string IdCardNumber { get; set; } = string.Empty; public string IdCardNumber { get; set; } = string.Empty;
/// <summary> /// <summary>
@@ -236,6 +242,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("id_doc_name")] [Newtonsoft.Json.JsonProperty("id_doc_name")]
[System.Text.Json.Serialization.JsonPropertyName("id_doc_name")] [System.Text.Json.Serialization.JsonPropertyName("id_doc_name")]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string IdDocumentName { get; set; } = string.Empty; public string IdDocumentName { get; set; } = string.Empty;
/// <summary> /// <summary>
@@ -243,6 +250,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("id_doc_number")] [Newtonsoft.Json.JsonProperty("id_doc_number")]
[System.Text.Json.Serialization.JsonPropertyName("id_doc_number")] [System.Text.Json.Serialization.JsonPropertyName("id_doc_number")]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string IdDocumentNumber { get; set; } = string.Empty; public string IdDocumentNumber { get; set; } = string.Empty;
/// <summary> /// <summary>
@@ -325,6 +333,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("name")] [Newtonsoft.Json.JsonProperty("name")]
[System.Text.Json.Serialization.JsonPropertyName("name")] [System.Text.Json.Serialization.JsonPropertyName("name")]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string Name { get; set; } = string.Empty; public string Name { get; set; } = string.Empty;
/// <summary> /// <summary>
@@ -332,6 +341,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("id_number")] [Newtonsoft.Json.JsonProperty("id_number")]
[System.Text.Json.Serialization.JsonPropertyName("id_number")] [System.Text.Json.Serialization.JsonPropertyName("id_number")]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string IdNumber { get; set; } = string.Empty; public string IdNumber { get; set; } = string.Empty;
/// <summary> /// <summary>
@@ -708,6 +718,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("account_name")] [Newtonsoft.Json.JsonProperty("account_name")]
[System.Text.Json.Serialization.JsonPropertyName("account_name")] [System.Text.Json.Serialization.JsonPropertyName("account_name")]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string AccountName { get; set; } = string.Empty; public string AccountName { get; set; } = string.Empty;
/// <summary> /// <summary>
@@ -715,6 +726,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("account_number")] [Newtonsoft.Json.JsonProperty("account_number")]
[System.Text.Json.Serialization.JsonPropertyName("account_number")] [System.Text.Json.Serialization.JsonPropertyName("account_number")]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string AccountNumber { get; set; } = string.Empty; public string AccountNumber { get; set; } = string.Empty;
/// <summary> /// <summary>

View File

@@ -27,6 +27,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("account_number")] [Newtonsoft.Json.JsonProperty("account_number")]
[System.Text.Json.Serialization.JsonPropertyName("account_number")] [System.Text.Json.Serialization.JsonPropertyName("account_number")]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string AccountNumber { get; set; } = string.Empty; public string AccountNumber { get; set; } = string.Empty;
/// <summary> /// <summary>

View File

@@ -17,6 +17,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("name")] [Newtonsoft.Json.JsonProperty("name")]
[System.Text.Json.Serialization.JsonPropertyName("name")] [System.Text.Json.Serialization.JsonPropertyName("name")]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string Name { get; set; } = string.Empty; public string Name { get; set; } = string.Empty;
/// <summary> /// <summary>
@@ -24,6 +25,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("mobile")] [Newtonsoft.Json.JsonProperty("mobile")]
[System.Text.Json.Serialization.JsonPropertyName("mobile")] [System.Text.Json.Serialization.JsonPropertyName("mobile")]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string Mobile { get; set; } = string.Empty; public string Mobile { get; set; } = string.Empty;
/// <summary> /// <summary>
@@ -31,6 +33,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("id_card_number")] [Newtonsoft.Json.JsonProperty("id_card_number")]
[System.Text.Json.Serialization.JsonPropertyName("id_card_number")] [System.Text.Json.Serialization.JsonPropertyName("id_card_number")]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string IdCardNumber { get; set; } = string.Empty; public string IdCardNumber { get; set; } = string.Empty;
} }
@@ -255,6 +258,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("identification_name")] [Newtonsoft.Json.JsonProperty("identification_name")]
[System.Text.Json.Serialization.JsonPropertyName("identification_name")] [System.Text.Json.Serialization.JsonPropertyName("identification_name")]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string IdentificationName { get; set; } = string.Empty; public string IdentificationName { get; set; } = string.Empty;
/// <summary> /// <summary>
@@ -262,6 +266,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("identification_number")] [Newtonsoft.Json.JsonProperty("identification_number")]
[System.Text.Json.Serialization.JsonPropertyName("identification_number")] [System.Text.Json.Serialization.JsonPropertyName("identification_number")]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string IdentificationNumber { get; set; } = string.Empty; public string IdentificationNumber { get; set; } = string.Empty;
/// <summary> /// <summary>

View File

@@ -31,6 +31,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("name")] [Newtonsoft.Json.JsonProperty("name")]
[System.Text.Json.Serialization.JsonPropertyName("name")] [System.Text.Json.Serialization.JsonPropertyName("name")]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string? Name { get; set; } public string? Name { get; set; }
/// <summary> /// <summary>

View File

@@ -99,6 +99,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("id_card_name")] [Newtonsoft.Json.JsonProperty("id_card_name")]
[System.Text.Json.Serialization.JsonPropertyName("id_card_name")] [System.Text.Json.Serialization.JsonPropertyName("id_card_name")]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string IdCardName { get; set; } = string.Empty; public string IdCardName { get; set; } = string.Empty;
/// <summary> /// <summary>
@@ -106,6 +107,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("id_card_number")] [Newtonsoft.Json.JsonProperty("id_card_number")]
[System.Text.Json.Serialization.JsonPropertyName("id_card_number")] [System.Text.Json.Serialization.JsonPropertyName("id_card_number")]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string IdCardNumber { get; set; } = string.Empty; public string IdCardNumber { get; set; } = string.Empty;
/// <summary> /// <summary>
@@ -130,6 +132,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("id_doc_name")] [Newtonsoft.Json.JsonProperty("id_doc_name")]
[System.Text.Json.Serialization.JsonPropertyName("id_doc_name")] [System.Text.Json.Serialization.JsonPropertyName("id_doc_name")]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string IdDocumentName { get; set; } = string.Empty; public string IdDocumentName { get; set; } = string.Empty;
/// <summary> /// <summary>
@@ -137,6 +140,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("id_doc_number")] [Newtonsoft.Json.JsonProperty("id_doc_number")]
[System.Text.Json.Serialization.JsonPropertyName("id_doc_number")] [System.Text.Json.Serialization.JsonPropertyName("id_doc_number")]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string IdDocumentNumber { get; set; } = string.Empty; public string IdDocumentNumber { get; set; } = string.Empty;
/// <summary> /// <summary>
@@ -161,6 +165,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("contact_name")] [Newtonsoft.Json.JsonProperty("contact_name")]
[System.Text.Json.Serialization.JsonPropertyName("contact_name")] [System.Text.Json.Serialization.JsonPropertyName("contact_name")]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string ContactName { get; set; } = string.Empty; public string ContactName { get; set; } = string.Empty;
/// <summary> /// <summary>
@@ -168,6 +173,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("mobile_phone")] [Newtonsoft.Json.JsonProperty("mobile_phone")]
[System.Text.Json.Serialization.JsonPropertyName("mobile_phone")] [System.Text.Json.Serialization.JsonPropertyName("mobile_phone")]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string ContactMobile { get; set; } = string.Empty; public string ContactMobile { get; set; } = string.Empty;
/// <summary> /// <summary>
@@ -175,6 +181,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("contact_id_card_number")] [Newtonsoft.Json.JsonProperty("contact_id_card_number")]
[System.Text.Json.Serialization.JsonPropertyName("contact_id_card_number")] [System.Text.Json.Serialization.JsonPropertyName("contact_id_card_number")]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string ContactIdCardNumber { get; set; } = string.Empty; public string ContactIdCardNumber { get; set; } = string.Empty;
/// <summary> /// <summary>
@@ -182,6 +189,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("contact_email")] [Newtonsoft.Json.JsonProperty("contact_email")]
[System.Text.Json.Serialization.JsonPropertyName("contact_email")] [System.Text.Json.Serialization.JsonPropertyName("contact_email")]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string ContactEmail { get; set; } = string.Empty; public string ContactEmail { get; set; } = string.Empty;
} }
@@ -199,6 +207,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("account_name")] [Newtonsoft.Json.JsonProperty("account_name")]
[System.Text.Json.Serialization.JsonPropertyName("account_name")] [System.Text.Json.Serialization.JsonPropertyName("account_name")]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string AccountName { get; set; } = string.Empty; public string AccountName { get; set; } = string.Empty;
/// <summary> /// <summary>
@@ -206,6 +215,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("account_number")] [Newtonsoft.Json.JsonProperty("account_number")]
[System.Text.Json.Serialization.JsonPropertyName("account_number")] [System.Text.Json.Serialization.JsonPropertyName("account_number")]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string AccountNumber { get; set; } = string.Empty; public string AccountNumber { get; set; } = string.Empty;
/// <summary> /// <summary>

View File

@@ -31,6 +31,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("receiver_name")] [Newtonsoft.Json.JsonProperty("receiver_name")]
[System.Text.Json.Serialization.JsonPropertyName("receiver_name")] [System.Text.Json.Serialization.JsonPropertyName("receiver_name")]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string? Name { get; set; } public string? Name { get; set; }
/// <summary> /// <summary>

View File

@@ -41,6 +41,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("encrypted_name")] [Newtonsoft.Json.JsonProperty("encrypted_name")]
[System.Text.Json.Serialization.JsonPropertyName("encrypted_name")] [System.Text.Json.Serialization.JsonPropertyName("encrypted_name")]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string? EncryptedName { get; set; } public string? EncryptedName { get; set; }
/// <summary> /// <summary>

View File

@@ -31,6 +31,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("name")] [Newtonsoft.Json.JsonProperty("name")]
[System.Text.Json.Serialization.JsonPropertyName("name")] [System.Text.Json.Serialization.JsonPropertyName("name")]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string? Name { get; set; } public string? Name { get; set; }
/// <summary> /// <summary>

View File

@@ -41,10 +41,11 @@
public string Account { get; set; } = string.Empty; public string Account { get; set; } = string.Empty;
/// <summary> /// <summary>
/// 获取或设置接收方名称。 /// 获取或设置接收方名称(需使用微信支付平台公钥加密)
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("name")] [Newtonsoft.Json.JsonProperty("name")]
[System.Text.Json.Serialization.JsonPropertyName("name")] [System.Text.Json.Serialization.JsonPropertyName("name")]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string? Name { get; set; } public string? Name { get; set; }
/// <summary> /// <summary>

View File

@@ -30,10 +30,11 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
public string Account { get; set; } = default!; public string Account { get; set; } = default!;
/// <summary> /// <summary>
/// 获取或设置接收方名称。 /// 获取或设置接收方名称(需使用商户私钥解密)
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("name")] [Newtonsoft.Json.JsonProperty("name")]
[System.Text.Json.Serialization.JsonPropertyName("name")] [System.Text.Json.Serialization.JsonPropertyName("name")]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string? Name { get; set; } public string? Name { get; set; }
/// <summary> /// <summary>

View File

@@ -41,6 +41,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("name")] [Newtonsoft.Json.JsonProperty("name")]
[System.Text.Json.Serialization.JsonPropertyName("name")] [System.Text.Json.Serialization.JsonPropertyName("name")]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string UserName { get; set; } = string.Empty; public string UserName { get; set; } = string.Empty;
/// <summary> /// <summary>
@@ -48,6 +49,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("mobile")] [Newtonsoft.Json.JsonProperty("mobile")]
[System.Text.Json.Serialization.JsonPropertyName("mobile")] [System.Text.Json.Serialization.JsonPropertyName("mobile")]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string UserMobile { get; set; } = string.Empty; public string UserMobile { get; set; } = string.Empty;
/// <summary> /// <summary>

View File

@@ -34,6 +34,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonIgnore] [Newtonsoft.Json.JsonIgnore]
[System.Text.Json.Serialization.JsonIgnore] [System.Text.Json.Serialization.JsonIgnore]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string? UserMobile { get; set; } public string? UserMobile { get; set; }
/// <summary> /// <summary>

View File

@@ -27,6 +27,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("name")] [Newtonsoft.Json.JsonProperty("name")]
[System.Text.Json.Serialization.JsonPropertyName("name")] [System.Text.Json.Serialization.JsonPropertyName("name")]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string? UserName { get; set; } public string? UserName { get; set; }
/// <summary> /// <summary>
@@ -34,6 +35,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("mobile")] [Newtonsoft.Json.JsonProperty("mobile")]
[System.Text.Json.Serialization.JsonPropertyName("mobile")] [System.Text.Json.Serialization.JsonPropertyName("mobile")]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string? UserMobile { get; set; } public string? UserMobile { get; set; }
/// <summary> /// <summary>

View File

@@ -45,6 +45,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("user_name")] [Newtonsoft.Json.JsonProperty("user_name")]
[System.Text.Json.Serialization.JsonPropertyName("user_name")] [System.Text.Json.Serialization.JsonPropertyName("user_name")]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string UserName { get; set; } = string.Empty; public string UserName { get; set; } = string.Empty;
/// <summary> /// <summary>
@@ -52,6 +53,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("user_id_card")] [Newtonsoft.Json.JsonProperty("user_id_card")]
[System.Text.Json.Serialization.JsonPropertyName("user_id_card")] [System.Text.Json.Serialization.JsonPropertyName("user_id_card")]
[WechatTenpaySensitiveProperty(algorithm: Constants.EncryptionAlgorithms.RSA_2048_PKCS8_ECB)]
public string UserIdCardNumber { get; set; } = string.Empty; public string UserIdCardNumber { get; set; } = string.Empty;
} }
} }

View File

@@ -87,10 +87,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
flurlRequest.WithHeader("Wechatpay-Serial", request.WechatpayCertSerialNumber); flurlRequest.WithHeader("Wechatpay-Serial", request.WechatpayCertSerialNumber);
} }
if (AutoDecryptResponseSensitiveProperty) if (AutoEncryptRequestSensitiveProperty)
{ {
// this.EncryptRequestSensitiveProperty(request); this.EncryptRequestSensitiveProperty(request);
throw new NotImplementedException();
} }
return flurlRequest; return flurlRequest;

View File

@@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
{
public class WechatTenpayRequestEncryptionTests
{
private const string RSA_CERTSN = "mock_sn";
private const string RSA_CERTIFICATE = "-----BEGIN CERTIFICATE-----MIID9jCCAt6gAwIBAgIUFGJAVFxIU/1hoxpZC8Tc2xKFJHowDQYJKoZIhvcNAQELBQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsTFFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3QgQ0EwHhcNMjAwODAxMDczNTE5WhcNMjUwNzMxMDczNTE5WjCBhzETMBEGA1UEAwwKMTYwMTEwMzMxNDEbMBkGA1UECgwS5b6u5L+h5ZWG5oi357O757ufMTMwMQYDVQQLDCroo5XkurrvvIjkuIrmtbfvvInmlZnogrLnp5HmioDmnInpmZDlhazlj7gxCzAJBgNVBAYMAkNOMREwDwYDVQQHDAhTaGVuWmhlbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKq4IUw5Rq6iTUahjkr+aYvmn3Hg2tHNDyIru7ZdthXw27BCwnwwDyufq6SBwXypuf3wXKpcFggZo5dwjDR6XxlGXzNDKdW7JQkTxQXqABZZVCq4yMMkVns3xbmDfAI57bW0O0F40+NOqmU9gjqRwGNvE9bE8N3y2VyxYcz53rU4FCrlCOfsFeF1Z3usbWOK5IOYXjmdzr96xVWasO0URJ60GwDZyGxRdkzd5kJy6HnVVqOUbn3t7mKbGkzQq/j+D+pyMlhjtRV475ks5uex4gVWZgEqT1b9sx1pUQvVPr6/ZXtqTJwSg/YvSCx5RBiYCskAyA/5XH9t1p/WV1zFhXUCAwEAAaOBgTB/MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgTwMGUGA1UdHwReMFwwWqBYoFaGVGh0dHA6Ly9ldmNhLml0cnVzLmNvbS5jbi9wdWJsaWMvaXRydXNjcmw/Q0E9MUJENDIyMEU1MERCQzA0QjA2QUQzOTc1NDk4NDZDMDFDM0U4RUJEMjANBgkqhkiG9w0BAQsFAAOCAQEAU44msdPGFg/r5JcWgUDEXWOqqCDiFNjWbhM/rO0A3TCV0yP5o7Se/yLsDizHGTUzZ2qg3bC02nn4RysEyMVQ+9tXsOtXQBHrmoZ5vS8ndqbE1YO33N6zxIUb0IN3yGZh3oVmQgTYYe1is4i5Sfiy7JdR6/uUrwQN13fzPaDCnNx6iVzrPSJJf1xiFdtpFFtK021prjMYG7csHiFQeelgyE8XtlQuLk0tsHBrJ2FHSdV4HISqONz0hMPL0xsZkBD/L/bvR3L0lqe8bsHOBCJOMyjxucI21mBRd7tc4AGiJlQt5jrUrbos5hul4/QUq7hFfZNDrEBMINbMyIpYWRbIqQ==-----END CERTIFICATE-----";
private const string RSA_PRIVATE_KEY = "-----BEGIN PRIVATE KEY-----MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCquCFMOUauok1GoY5K/mmL5p9x4NrRzQ8iK7u2XbYV8NuwQsJ8MA8rn6ukgcF8qbn98FyqXBYIGaOXcIw0el8ZRl8zQynVuyUJE8UF6gAWWVQquMjDJFZ7N8W5g3wCOe21tDtBeNPjTqplPYI6kcBjbxPWxPDd8tlcsWHM+d61OBQq5Qjn7BXhdWd7rG1jiuSDmF45nc6/esVVmrDtFESetBsA2chsUXZM3eZCcuh51VajlG597e5imxpM0Kv4/g/qcjJYY7UVeO+ZLObnseIFVmYBKk9W/bMdaVEL1T6+v2V7akycEoP2L0gseUQYmArJAMgP+Vx/bdaf1ldcxYV1AgMBAAECggEBAIwkgTkYX5ymIXeU0cFgXfZ5iHQsWJUXl4++hOaswPf78+wasZrOvPVbqsRtvA8BKWx7byZuV6uomHGN85p0xjJyYV4siWAps7pi3z7+m7m89OnpLO18m/2kiAzFEfyl3yxlWqtha9dSUXCwcIJx+ZPmsEuC+hPI8oQ0HQvuJtNtcDmaFBp57kxjlO4Xm0xnvq2waSmAF4cO6Dk62gksu8G7//IyIHXqmRWSpI2b/Yqf84XtwLN8Zvq/3otYuWc3pFOaKHg2sJ/JwSU+yGdeIOtEXXFIDSD6p3KvIvjrD47Da4optYReXP1k6e721z+XPBFP31i58iu1K8KOyjjJfsECgYEA41D6V1TrON31OOsM4jAtqyY/LVNdzT+I/S6lQruO9siRRJDYlAOdbM9VZnW/3rduPMBu4undbMkL5i8olnwmLeWSupClA2WmUc8DWHlBO2s0lE+ZDZgOtpZ9qOBfm7L6jbjvzbGoyJgV6SeIavH5SMQbFku5rlIi12hAb0Kv4uUCgYEAwELkPOKDH06SFOiuOzJcI4VyjK0V5LcWjceTPkaT9d1evkrNgrHiG8CjYQ3V0lqSKhckFg2PwmPk72rC4n3aFCXurimv96rG5sBFFLgPbyoKZ3Z9JoDoe/6u6YIAV/GzxJ5QJaWQQ59MxToILYyq6aA6SrNOqRUPsKuvN8jBH1ECgYEA3dJ6yNgcRj0KfIWa5+qd1iMXiZKNuamjc3WeXTWL+DSW1bMHNcElUTYuHzMOjjavw2cBjjsrEWpLS09/qwHxe95IRfi6nksGd1Ss7hw9VM9z2rqmH4bf7LuEWlTB171bFQuAL1iL3VvUHdavH7WLTr/XsvUod/y89TlNj4UjACUCgYBBR3UPZyl2O8tF5isiVlsKhIj8UtiYK8IwqY7JGlWqqVs96VAWDCflnGbc0UHEhpQSToEmK7ygGCLnV6yMEoc1SBvebrEcupOGTcom2sgCypd1wbmElUhasYLaLhXHxn1vSQGVhr2Q+EmsvaOBM73kTU79hhwzNL97ERARNMy9wQKBgHCogsDPxSh8hEJR/PBom6v/3R+Ou86K8nzulbyHGkDM7I2R//zGx4en1VxWFhsqywsGedugv1BMkgEcCFkTjIXfYh9Uwn5iGUAZCczR5ZoETYAAzK2a/uaWf92iZEU0bHJaBA4egNxk1bFe+ECFTteN8Ag+UVtx0HU6ZNlyfetH-----END PRIVATE KEY-----";
private const string MockText = "mock_text";
private readonly Lazy<WechatTenpayClient> MockClientInstance = new Lazy<WechatTenpayClient>(() =>
{
var certManager = new Settings.InMemoryCertificateManager();
certManager.AddEntry(new Settings.CertificateEntry(
serialNumber: RSA_CERTSN,
certificate: RSA_CERTIFICATE,
effectiveTime: DateTimeOffset.MinValue,
expireTime: DateTimeOffset.MaxValue
));
return new WechatTenpayClient(new WechatTenpayClientOptions()
{
CertificateManager = certManager
});
}, isThreadSafe: false);
[Fact(DisplayName = "加密请求中的敏感数据([POST] /profitsharing/receivers/add")]
public void DecryptResponseSensitiveProperty_AddProfitSharingReceiverRequest()
{
var mock = new Models.AddProfitSharingReceiverRequest()
{
Account = MockText,
Name = MockText
};
var data = MockClientInstance.Value.EncryptRequestSensitiveProperty(mock);
Assert.Equal(MockText, data.Account);
Assert.Equal(MockText, Utilities.RSAUtility.DecryptWithECB(RSA_PRIVATE_KEY, data.Name));
}
}
}