using System; using System.Linq; using System.Reflection; namespace SKIT.FlurlHttpClient.Wechat.TenpayV3 { /// /// 为 提供请求模型敏感数据加密的扩展方法。 /// public static class WechatTenpayClientRequestEncryptionExtensions { /// /// 加密请求中传入的敏感数据。该方法会改变传入的请求模型对象。 /// /// /// /// public static TRequest EncryptRequestSensitiveProperty(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 { bool requireEncrypt = Attribute.IsDefined(request.GetType(), typeof(WechatTenpaySensitiveAttribute)); if (requireEncrypt) { // 遍历并加密被标记为敏感数据的字段 Utilities.ReflectionUtility.ReplacePropertyStringValue(ref request, (target, currentProp, oldValue) => { var attr = currentProp.GetCustomAttribute(); if (attr == null) return (false, oldValue); if (Constants.EncryptionAlgorithms.RSA_2048_ECB_PKCS8_OAEP_WITH_SHA1_AND_MGF1.Equals(attr.Algorithm) || Constants.EncryptionAlgorithms.RSA_2048_ECB_PKCS1.Equals(attr.Algorithm)) { if (client.PlatformCertificateManager == null) throw new Exceptions.WechatTenpayRequestEncryptionException("Encrypt request failed, because there is no platform certificate in the manager."); string certificate; if (!string.IsNullOrEmpty(request.WechatpayCertificateSerialNumber)) { // 如果已在请求中指定特定的平台证书序列号,直接从管理器中取值 var cert = client.PlatformCertificateManager.GetEntry(request.WechatpayCertificateSerialNumber!); 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.PlatformCertificateManager.AllEntries().OrderByDescending(e => e.ExpireTime); if (!certs.Any()) { throw new Exceptions.WechatTenpayEventVerificationException("Encrypt request failed, because there is no platform certificate in the manager."); } var cert = certs.First(); certificate = cert.Certificate; request.WechatpayCertificateSerialNumber = cert.SerialNumber; } string newValue = oldValue; if (Constants.EncryptionAlgorithms.RSA_2048_ECB_PKCS8_OAEP_WITH_SHA1_AND_MGF1.Equals(attr.Algorithm)) { newValue = Utilities.RSAUtility.EncryptWithECBByCertificate( certificate: certificate, plainText: oldValue ); } else if (Constants.EncryptionAlgorithms.RSA_2048_ECB_PKCS1.Equals(attr.Algorithm)) { newValue = Utilities.RSAUtility.EncryptWithECBByCertificate( certificate: certificate, plainText: oldValue, paddingMode: "PKCS1PADDING" ); } return (true, newValue); } 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; } } }