2021-05-10 15:30:00 +08:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
|
|
|
|
|
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 为 <see cref="WechatTenpayClient"/> 提供响应敏感数据解密的扩展方法。
|
|
|
|
|
/// </summary>
|
|
|
|
|
public static class WechatTenpayClientResponseDecryptionExtensions
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// <para>解密响应中返回的敏感数据。该方法会改变传入的响应信息。</para>
|
|
|
|
|
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_3.shtml </para>
|
|
|
|
|
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/wechatpay/wechatpay4_3.shtml </para>
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="client"></param>
|
|
|
|
|
/// <param name="response"></param>
|
|
|
|
|
/// <returns></returns>
|
2021-05-28 19:08:11 +08:00
|
|
|
|
public static Models.GetEcommerceApplymentByOutRequestNumberResponse DecryptResponseEncryptedData(this WechatTenpayClient client, Models.GetEcommerceApplymentByOutRequestNumberResponse response)
|
2021-05-10 15:30:00 +08:00
|
|
|
|
{
|
|
|
|
|
if (client == null) throw new ArgumentNullException(nameof(client));
|
|
|
|
|
if (response == null) throw new ArgumentNullException(nameof(response));
|
|
|
|
|
|
2021-06-17 19:46:16 +08:00
|
|
|
|
if (string.IsNullOrEmpty(client.WechatMerchantCertPrivateKey))
|
2021-05-10 15:30:00 +08:00
|
|
|
|
throw new Exceptions.WechatTenpayResponseDecryptionException("Decrypt response failed, because of there is no merchant private key.");
|
|
|
|
|
|
|
|
|
|
if (!response.IsSuccessful())
|
|
|
|
|
throw new Exceptions.WechatTenpayResponseDecryptionException("Decrypt response failed, because of the response is not successful.");
|
|
|
|
|
|
|
|
|
|
if (response.AccountValidation != null)
|
|
|
|
|
{
|
|
|
|
|
IList<Exception> exceptions = new List<Exception>();
|
|
|
|
|
|
|
|
|
|
var accountValidationModel = response.AccountValidation;
|
|
|
|
|
|
2021-07-08 17:10:21 +08:00
|
|
|
|
if (!string.IsNullOrEmpty(accountValidationModel.AccountName))
|
2021-05-10 15:30:00 +08:00
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
2021-07-08 17:10:21 +08:00
|
|
|
|
accountValidationModel.AccountName = Utilities.RSAUtility.DecryptWithECB(
|
2021-06-17 19:46:16 +08:00
|
|
|
|
client.WechatMerchantCertPrivateKey,
|
2021-07-08 17:10:21 +08:00
|
|
|
|
accountValidationModel.AccountName
|
2021-05-10 15:30:00 +08:00
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
exceptions.Add(ex);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-08 17:10:21 +08:00
|
|
|
|
if (!string.IsNullOrEmpty(accountValidationModel.AccountNumber))
|
2021-05-10 15:30:00 +08:00
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
2021-07-08 17:10:21 +08:00
|
|
|
|
accountValidationModel.AccountNumber = Utilities.RSAUtility.DecryptWithECB(
|
2021-06-17 19:46:16 +08:00
|
|
|
|
client.WechatMerchantCertPrivateKey,
|
2021-07-08 17:10:21 +08:00
|
|
|
|
accountValidationModel.AccountNumber!
|
2021-05-10 15:30:00 +08:00
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
exceptions.Add(ex);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (exceptions.Any())
|
|
|
|
|
throw new Exceptions.WechatTenpayResponseDecryptionException("Decrypt response failed.", new AggregateException(exceptions));
|
|
|
|
|
}
|
2021-05-28 19:08:11 +08:00
|
|
|
|
|
|
|
|
|
return response;
|
2021-05-10 15:30:00 +08:00
|
|
|
|
}
|
|
|
|
|
|
2021-05-28 19:08:11 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// <para>解密响应中返回的敏感数据。该方法会改变传入的响应信息。</para>
|
|
|
|
|
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_3.shtml </para>
|
|
|
|
|
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/wechatpay/wechatpay4_3.shtml </para>
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="client"></param>
|
|
|
|
|
/// <param name="response"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public static Models.GetEcommerceBillFundflowBillResponse DecryptResponseEncryptedData(this WechatTenpayClient client, Models.GetEcommerceBillFundflowBillResponse response)
|
2021-05-10 15:30:00 +08:00
|
|
|
|
{
|
2021-05-28 19:08:11 +08:00
|
|
|
|
if (client == null) throw new ArgumentNullException(nameof(client));
|
|
|
|
|
if (response == null) throw new ArgumentNullException(nameof(response));
|
|
|
|
|
|
2021-06-17 19:46:16 +08:00
|
|
|
|
if (string.IsNullOrEmpty(client.WechatMerchantCertPrivateKey))
|
2021-05-28 19:08:11 +08:00
|
|
|
|
throw new Exceptions.WechatTenpayResponseDecryptionException("Decrypt response failed, because of there is no merchant private key.");
|
|
|
|
|
|
|
|
|
|
if (!response.IsSuccessful())
|
|
|
|
|
throw new Exceptions.WechatTenpayResponseDecryptionException("Decrypt response failed, because of the response is not successful.");
|
|
|
|
|
|
2021-05-10 15:30:00 +08:00
|
|
|
|
if (response.DownloadBillList != null)
|
|
|
|
|
{
|
|
|
|
|
IList<Exception> exceptions = new List<Exception>();
|
|
|
|
|
|
|
|
|
|
foreach (var downloadBillModel in response.DownloadBillList)
|
|
|
|
|
{
|
2021-07-08 17:10:21 +08:00
|
|
|
|
if (!string.IsNullOrEmpty(downloadBillModel.EncryptKey))
|
2021-05-10 15:30:00 +08:00
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
2021-07-08 17:10:21 +08:00
|
|
|
|
downloadBillModel.EncryptKey = Utilities.RSAUtility.DecryptWithECB(
|
2021-06-17 19:46:16 +08:00
|
|
|
|
client.WechatMerchantCertPrivateKey,
|
2021-07-08 17:10:21 +08:00
|
|
|
|
downloadBillModel.EncryptKey
|
2021-05-10 15:30:00 +08:00
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
exceptions.Add(ex);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (exceptions.Any())
|
|
|
|
|
throw new Exceptions.WechatTenpayResponseDecryptionException("Decrypt response failed.", new AggregateException(exceptions));
|
|
|
|
|
}
|
2021-05-28 19:08:11 +08:00
|
|
|
|
|
|
|
|
|
return response;
|
2021-05-10 15:30:00 +08:00
|
|
|
|
}
|
|
|
|
|
|
2021-05-28 19:08:11 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// <para>解密响应中返回的敏感数据。该方法会改变传入的响应信息。</para>
|
|
|
|
|
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_3.shtml </para>
|
|
|
|
|
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/wechatpay/wechatpay4_3.shtml </para>
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="client"></param>
|
|
|
|
|
/// <param name="response"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public static Models.GetMerchantServiceComplaintByComplaintIdResponse DecryptResponseEncryptedData(this WechatTenpayClient client, Models.GetMerchantServiceComplaintByComplaintIdResponse response)
|
2021-05-10 15:30:00 +08:00
|
|
|
|
{
|
2021-05-28 19:08:11 +08:00
|
|
|
|
if (client == null) throw new ArgumentNullException(nameof(client));
|
|
|
|
|
if (response == null) throw new ArgumentNullException(nameof(response));
|
|
|
|
|
|
2021-06-17 19:46:16 +08:00
|
|
|
|
if (string.IsNullOrEmpty(client.WechatMerchantCertPrivateKey))
|
2021-05-28 19:08:11 +08:00
|
|
|
|
throw new Exceptions.WechatTenpayResponseDecryptionException("Decrypt response failed, because of there is no merchant private key.");
|
|
|
|
|
|
|
|
|
|
if (!response.IsSuccessful())
|
|
|
|
|
throw new Exceptions.WechatTenpayResponseDecryptionException("Decrypt response failed, because of the response is not successful.");
|
|
|
|
|
|
2021-05-10 15:30:00 +08:00
|
|
|
|
if (response.ComplaintDetail != null)
|
|
|
|
|
{
|
2021-07-08 17:10:21 +08:00
|
|
|
|
if (!string.IsNullOrEmpty(response.PayerPhone))
|
2021-05-10 15:30:00 +08:00
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
2021-07-08 17:10:21 +08:00
|
|
|
|
response.PayerPhone = Utilities.RSAUtility.DecryptWithECB(
|
2021-06-17 19:46:16 +08:00
|
|
|
|
client.WechatMerchantCertPrivateKey,
|
2021-07-08 17:10:21 +08:00
|
|
|
|
response.PayerPhone!
|
2021-05-10 15:30:00 +08:00
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
throw new Exceptions.WechatTenpayResponseDecryptionException("Decrypt response failed.", ex);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-05-28 19:08:11 +08:00
|
|
|
|
|
|
|
|
|
return response;
|
2021-05-10 15:30:00 +08:00
|
|
|
|
}
|
|
|
|
|
|
2021-05-28 19:08:11 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// <para>解密响应中返回的敏感数据。该方法会改变传入的响应信息。</para>
|
|
|
|
|
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_3.shtml </para>
|
|
|
|
|
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/wechatpay/wechatpay4_3.shtml </para>
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="client"></param>
|
|
|
|
|
/// <param name="response"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public static Models.QueryCertificatesResponse DecryptResponseEncryptedData(this WechatTenpayClient client, Models.QueryCertificatesResponse response)
|
2021-05-10 15:30:00 +08:00
|
|
|
|
{
|
2021-05-28 19:08:11 +08:00
|
|
|
|
if (client == null) throw new ArgumentNullException(nameof(client));
|
|
|
|
|
if (response == null) throw new ArgumentNullException(nameof(response));
|
|
|
|
|
|
2021-06-17 19:46:16 +08:00
|
|
|
|
if (string.IsNullOrEmpty(client.WechatMerchantV3Secret))
|
2021-05-28 19:08:11 +08:00
|
|
|
|
throw new Exceptions.WechatTenpayResponseDecryptionException("Decrypt response failed, because of there is no merchant secret.");
|
|
|
|
|
|
|
|
|
|
if (!response.IsSuccessful())
|
|
|
|
|
throw new Exceptions.WechatTenpayResponseDecryptionException("Decrypt response failed, because of the response is not successful.");
|
|
|
|
|
|
2021-05-10 15:30:00 +08:00
|
|
|
|
if (response.CertificateList != null)
|
|
|
|
|
{
|
|
|
|
|
IList<Exception> exceptions = new List<Exception>();
|
|
|
|
|
|
|
|
|
|
foreach (var certificateModel in response.CertificateList)
|
|
|
|
|
{
|
|
|
|
|
if (Constants.EncryptionAlgorithms.AEAD_AES_256_GCM.Equals(certificateModel.EncryptCertificate?.Algorithm))
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
2021-06-07 00:28:00 +08:00
|
|
|
|
certificateModel.EncryptCertificate.CipherText = Utilities.AESUtility.DecryptWithGCM(
|
2021-06-17 19:46:16 +08:00
|
|
|
|
key: client.WechatMerchantV3Secret,
|
2021-06-07 00:28:00 +08:00
|
|
|
|
iv: certificateModel.EncryptCertificate.Nonce,
|
|
|
|
|
aad: certificateModel.EncryptCertificate.AssociatedData,
|
2021-05-10 15:30:00 +08:00
|
|
|
|
cipherText: certificateModel.EncryptCertificate.CipherText
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
exceptions.Add(ex);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
exceptions.Add(new Exception("Unknown encrypt algorithm of the certificate."));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (exceptions.Any())
|
|
|
|
|
throw new Exceptions.WechatTenpayResponseDecryptionException("Decrypt response failed.", new AggregateException(exceptions));
|
|
|
|
|
}
|
2021-05-28 19:08:11 +08:00
|
|
|
|
|
|
|
|
|
return response;
|
2021-05-10 15:30:00 +08:00
|
|
|
|
}
|
|
|
|
|
|
2021-05-28 19:08:11 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// <para>解密响应中返回的敏感数据。该方法会改变传入的响应信息。</para>
|
|
|
|
|
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_3.shtml </para>
|
|
|
|
|
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/wechatpay/wechatpay4_3.shtml </para>
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="client"></param>
|
|
|
|
|
/// <param name="response"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public static Models.QueryMerchantServiceComplaintsResponse DecryptResponseEncryptedData(this WechatTenpayClient client, Models.QueryMerchantServiceComplaintsResponse response)
|
2021-05-10 15:30:00 +08:00
|
|
|
|
{
|
2021-05-28 19:08:11 +08:00
|
|
|
|
if (client == null) throw new ArgumentNullException(nameof(client));
|
|
|
|
|
if (response == null) throw new ArgumentNullException(nameof(response));
|
|
|
|
|
|
2021-06-17 19:46:16 +08:00
|
|
|
|
if (string.IsNullOrEmpty(client.WechatMerchantCertPrivateKey))
|
2021-05-28 19:08:11 +08:00
|
|
|
|
throw new Exceptions.WechatTenpayResponseDecryptionException("Decrypt response failed, because of there is no merchant private key.");
|
|
|
|
|
|
|
|
|
|
if (!response.IsSuccessful())
|
|
|
|
|
throw new Exceptions.WechatTenpayResponseDecryptionException("Decrypt response failed, because of the response is not successful.");
|
|
|
|
|
|
2021-05-10 15:30:00 +08:00
|
|
|
|
if (response.ComplaintList != null)
|
|
|
|
|
{
|
|
|
|
|
IList<Exception> exceptions = new List<Exception>();
|
|
|
|
|
|
|
|
|
|
foreach (var complaintModel in response.ComplaintList)
|
|
|
|
|
{
|
2021-07-08 17:10:21 +08:00
|
|
|
|
if (!string.IsNullOrEmpty(complaintModel.PayerPhone))
|
2021-05-10 15:30:00 +08:00
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
2021-07-08 17:10:21 +08:00
|
|
|
|
complaintModel.PayerPhone = Utilities.RSAUtility.DecryptWithECB(
|
2021-06-17 19:46:16 +08:00
|
|
|
|
client.WechatMerchantCertPrivateKey,
|
2021-07-08 17:10:21 +08:00
|
|
|
|
complaintModel.PayerPhone!
|
2021-05-10 15:30:00 +08:00
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
exceptions.Add(ex);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (exceptions.Any())
|
|
|
|
|
throw new Exceptions.WechatTenpayResponseDecryptionException("Decrypt response failed.", new AggregateException(exceptions));
|
|
|
|
|
}
|
2021-05-28 19:08:11 +08:00
|
|
|
|
|
|
|
|
|
return response;
|
2021-05-10 15:30:00 +08:00
|
|
|
|
}
|
|
|
|
|
|
2021-05-28 19:08:11 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// <para>解密响应中返回的敏感数据。该方法会改变传入的响应信息。</para>
|
|
|
|
|
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_3.shtml </para>
|
|
|
|
|
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/wechatpay/wechatpay4_3.shtml </para>
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="client"></param>
|
|
|
|
|
/// <param name="response"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public static Models.QuerySmartGuidesResponse DecryptResponseEncryptedData(this WechatTenpayClient client, Models.QuerySmartGuidesResponse response)
|
2021-05-10 15:30:00 +08:00
|
|
|
|
{
|
2021-05-28 19:08:11 +08:00
|
|
|
|
if (client == null) throw new ArgumentNullException(nameof(client));
|
|
|
|
|
if (response == null) throw new ArgumentNullException(nameof(response));
|
|
|
|
|
|
2021-06-17 19:46:16 +08:00
|
|
|
|
if (string.IsNullOrEmpty(client.WechatMerchantCertPrivateKey))
|
2021-05-28 19:08:11 +08:00
|
|
|
|
throw new Exceptions.WechatTenpayResponseDecryptionException("Decrypt response failed, because of there is no merchant private key.");
|
|
|
|
|
|
|
|
|
|
if (!response.IsSuccessful())
|
|
|
|
|
throw new Exceptions.WechatTenpayResponseDecryptionException("Decrypt response failed, because of the response is not successful.");
|
|
|
|
|
|
2021-05-10 15:30:00 +08:00
|
|
|
|
if (response.GuideList != null)
|
|
|
|
|
{
|
|
|
|
|
IList<Exception> exceptions = new List<Exception>();
|
|
|
|
|
|
|
|
|
|
foreach (var guideModel in response.GuideList)
|
|
|
|
|
{
|
2021-07-08 17:10:21 +08:00
|
|
|
|
if (!string.IsNullOrEmpty(guideModel.UserName))
|
2021-05-10 15:30:00 +08:00
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
2021-07-08 17:10:21 +08:00
|
|
|
|
guideModel.UserName = Utilities.RSAUtility.DecryptWithECB(
|
2021-06-17 19:46:16 +08:00
|
|
|
|
client.WechatMerchantCertPrivateKey,
|
2021-07-08 17:10:21 +08:00
|
|
|
|
guideModel.UserName
|
2021-05-10 15:30:00 +08:00
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
exceptions.Add(ex);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-08 17:10:21 +08:00
|
|
|
|
if (!string.IsNullOrEmpty(guideModel.UserMobile))
|
2021-05-10 15:30:00 +08:00
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
2021-07-08 17:10:21 +08:00
|
|
|
|
guideModel.UserMobile = Utilities.RSAUtility.DecryptWithECB(
|
2021-06-17 19:46:16 +08:00
|
|
|
|
client.WechatMerchantCertPrivateKey,
|
2021-07-08 17:10:21 +08:00
|
|
|
|
guideModel.UserMobile
|
2021-05-10 15:30:00 +08:00
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
exceptions.Add(ex);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (exceptions.Any())
|
|
|
|
|
throw new Exceptions.WechatTenpayResponseDecryptionException("Decrypt response failed.", new AggregateException(exceptions));
|
|
|
|
|
}
|
2021-05-28 19:08:11 +08:00
|
|
|
|
|
|
|
|
|
return response;
|
2021-05-10 15:30:00 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|