2021-11-25 18:42:54 +08:00
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
{
2021-12-03 16:27:13 +08:00
bool requireEncrypt = request . GetType ( ) . GetCustomAttributes < WechatTenpaySensitiveAttribute > ( inherit : true ) . Any ( ) ;
if ( requireEncrypt )
2021-11-25 18:42:54 +08:00
{
2021-12-03 16:27:13 +08:00
// 遍历并加密被标记为敏感数据的字段
2021-12-03 16:53:00 +08:00
Utilities . ReflectionUtility . ReplacePropertyStringValue ( ref request , ( target , currentProp , oldValue ) = >
2021-11-25 18:42:54 +08:00
{
2021-12-03 16:53:00 +08:00
var attr = currentProp . GetCustomAttribute < WechatTenpaySensitivePropertyAttribute > ( ) ;
2021-12-03 16:27:13 +08:00
if ( attr = = null )
2021-12-03 16:53:00 +08:00
return ( false , oldValue ) ;
2021-11-25 18:42:54 +08:00
2021-12-03 16:27:13 +08:00
if ( Constants . EncryptionAlgorithms . RSA_2048_PKCS8_ECB . Equals ( attr . Algorithm ) )
2021-11-25 18:42:54 +08:00
{
2022-01-21 14:41:40 +08:00
if ( client . PlatformCertificateManager = = null )
2021-12-03 16:27:13 +08:00
throw new Exceptions . WechatTenpayRequestEncryptionException ( "Encrypt request failed, because there is no platform certificate in the manager." ) ;
string certificate ;
2022-01-21 14:41:40 +08:00
if ( ! string . IsNullOrEmpty ( request . WechatpayCertificateSerialNumber ) )
2021-11-25 18:42:54 +08:00
{
2021-12-03 16:27:13 +08:00
// 如果已在请求中指定特定的平台证书序列号,直接从管理器中取值
2022-01-21 14:41:40 +08:00
var cert = client . PlatformCertificateManager . GetEntry ( request . WechatpayCertificateSerialNumber ! ) ;
2021-12-03 16:27:13 +08:00
if ( ! cert . HasValue )
{
throw new Exceptions . WechatTenpayEventVerificationException ( "Encrypt request failed, because there is no platform certificate matched the serial number." ) ;
}
certificate = cert . Value . Certificate ;
2021-11-25 18:42:54 +08:00
}
2021-12-03 16:27:13 +08:00
else
{
// 如果未在请求中指定特定的平台证书序列号,从管理器中取过期时间最远的
2022-01-21 14:41:40 +08:00
var certs = client . PlatformCertificateManager . AllEntries ( ) . OrderByDescending ( e = > e . ExpireTime ) ;
2021-12-03 16:27:13 +08:00
if ( ! certs . Any ( ) )
{
throw new Exceptions . WechatTenpayEventVerificationException ( "Encrypt request failed, because there is no platform certificate in the manager." ) ;
}
2021-11-25 18:42:54 +08:00
2021-12-03 16:27:13 +08:00
var cert = certs . First ( ) ;
certificate = cert . Certificate ;
2022-01-21 14:41:40 +08:00
request . WechatpayCertificateSerialNumber = cert . SerialNumber ;
2021-12-03 16:27:13 +08:00
}
2021-12-03 16:53:00 +08:00
string newValue = Utilities . RSAUtility . EncryptWithECBByCertificate (
2021-12-03 16:27:13 +08:00
certificate : certificate ,
2021-12-03 16:53:00 +08:00
plainText : oldValue
2021-12-03 16:27:13 +08:00
) ;
2021-12-03 16:53:00 +08:00
return ( true , newValue ) ;
2021-11-25 18:42:54 +08:00
}
else
{
2021-12-03 16:27:13 +08:00
throw new Exceptions . WechatTenpayRequestEncryptionException ( "Unsupported encryption algorithm." ) ;
2021-11-25 18:42:54 +08:00
}
2021-12-03 16:27:13 +08:00
} ) ;
}
2021-11-25 18:42:54 +08:00
}
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 ;
}
}
}