using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Threading.Tasks; using Xunit; namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests { public class TestCase_ResponseDecryptionTests { private const string RSA_PRIVATE_KEY = "-----BEGIN PRIVATE KEY-----MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCd094X2jr6wrL1pIBTSbKX5hVqxyCJhKLqaf31KQsw2LdzfXEOL45KiYr6IshwZaSPFok7Sq+1wLrO6/DZ7/GSmzVwdFIV/zjDbI3jaSHt69ZAJGBS212AzC4cwHvpGrHm3kqzVifJyUNxsoTvWklRGSE50pPWaXoxmdPgD5da8IPDHNzkPM0QYTOlHmIRsDQZpWiZRPaFdrN3i/qG9toCRCPVptCVNYrWLDEFXh3ioOqOdTk1fHxFczaNf4YvQhsqXlG/lGiqGbuPuFYfF/RvS9KfptAM1yycknTslkSeiOpA22sFbDdb+m7DHv+nc8DQPPmD7SxDwVIDTcIS7pEJAgMBAAECggEAM6E+czEZwDR3FLKGpDhkqxpCgVa4xyPTo7mesVeG6KjMgoRTup9F/g42n5NHXLVzereVlwbcqiltMwmuFa1PqnUJq0ryG24NZKibVfxrdAiFYyBDPneyg9LHdvJk1qG79tlbOIWDqJglbwlGQYKYn2YIH4FKiYahyZ4X2KFhEwc9mWydHSOyN8zOOJcRCy1FzUcUvITRKob+Q9epz9/4/VX0g1AnB6FwIR5pBqwMYLSv+g+JxfVKPRnSaIxq/2HOvhiyJ7fUqX1yGI+konJJHrn66JIux8xt4SxEnomZBveHlOMUTgTqovxpXisbvXQGBDV7dwW/qhGZet6h57qogQKBgQDNFLP9S6aPnwseeavxK0ygQpgJRbXbHCyqH/mVA/Pg9DaIhxl7+JCC1lS/JuZslow4t3JvjwixAzQEz9SkwUuiRO5vUWb5R+DZJ8HeqtMfoll6wxepu1TQT1pTPnSHliJQP15k5AQ1bkTZjcGA79iUmkksa4EP/GWtOooE8JhMEQKBgQDFA6oyBtbMyWlnGmdsieQuRsjCklZhPL93INX5VUfcfRqQdhqrmoaJg+OZTwVrARp6VHGEaURBTSj6bSoRbBckFNxjVsL6Utpgof+ZWmr5u8ZGHGHIPJMLt7GxI9SItpNNNY33OiUkkfSH4zHK5KZeG9sKKraQwITJCwLZUnnNeQKBgChHkLKHUUeULVLnAuZzYrF3YvUvQ/CtL/iaHyMti5D7Zlqabl7zCy8nea2xrkBVsWTSYx+WMFbUEjt/tnxFmt1cPJiQnHEJtRfxvxpE4wKrmHeMKfGkYZwoec0vzyNyUXsBd0DJqCn2Zn90YDU65ocJZqXa15aUNEQ54zHlL4SBAoGAHbve3OwBUSj4unHWuB/bi0xtkkgJt2U2tGEFSjsfvFw5PSJGBi4tLeX03Ld7ZtnkyB+kfkpw3bYqgBknpzd8CpsHZAq9JJCKmtj4PYnS6Vv4oa4458KUoskXjVeOBRAhDR8PDQf+gRVyJWwZoLh/j2Z+2Xr20MPthnYd+PSko2kCgYBra4rMhYx2Hg0rRe2O7ju+MPm+JK01VpbvwDTnEPnYgMImDmLAXF6GljCt3iy/8X1WcjMPxGjTJ/xfTMne/aqKwvPhZCBL4DdNLNRzppCovsaaMHzrQzy4cvg0IEhIprFeR7ED4eMs8zLUhl3vgNhHOkeQ7cyuEnTl5wB9xOkbSw==-----END PRIVATE KEY-----"; private const string RSA_PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAndPeF9o6+sKy9aSAU0myl+YVascgiYSi6mn99SkLMNi3c31xDi+OSomK+iLIcGWkjxaJO0qvtcC6zuvw2e/xkps1cHRSFf84w2yN42kh7evWQCRgUttdgMwuHMB76Rqx5t5Ks1YnyclDcbKE71pJURkhOdKT1ml6MZnT4A+XWvCDwxzc5DzNEGEzpR5iEbA0GaVomUT2hXazd4v6hvbaAkQj1abQlTWK1iwxBV4d4qDqjnU5NXx8RXM2jX+GL0IbKl5Rv5Roqhm7j7hWHxf0b0vSn6bQDNcsnJJ07JZEnojqQNtrBWw3W/puwx7/p3PA0Dz5g+0sQ8FSA03CEu6RCQIDAQAB-----END PUBLIC KEY-----"; private const string MockText = "mock_text"; private readonly Lazy MockClientInstance = new Lazy(() => { return new WechatTenpayClient(new WechatTenpayClientOptions() { MerchantCertificatePrivateKey = RSA_PRIVATE_KEY }); }, isThreadSafe: false); [Fact(DisplayName = "测试用例:解密响应中的敏感数据([GET] /certificates)")] public async Task TestDecryptResponseSensitiveProperty_QueryCertificatesResponse() { var client1 = new WechatTenpayClient(new WechatTenpayClientOptions() { MerchantId = TestConfigs.WechatMerchantId, MerchantV3Secret = TestConfigs.WechatMerchantSecret, MerchantCertificateSerialNumber = TestConfigs.WechatMerchantCertificateSerialNumber, MerchantCertificatePrivateKey = TestConfigs.WechatMerchantCertificatePrivateKey, AutoEncryptRequestSensitiveProperty = true, AutoDecryptResponseSensitiveProperty = true }); var request1 = new Models.QueryCertificatesRequest(); var response1 = await client1.ExecuteQueryCertificatesAsync(request1); Assert.DoesNotContain(response1.CertificateList, (e => !e.EncryptCertificate.CipherText.StartsWith("-----BEGIN CERTIFICATE-----"))); var client2 = new WechatTenpayClient(new WechatTenpayClientOptions() { MerchantId = TestConfigs.WechatMerchantId, MerchantV3Secret = TestConfigs.WechatMerchantSecret, MerchantCertificateSerialNumber = TestConfigs.WechatMerchantCertificateSerialNumber, MerchantCertificatePrivateKey = TestConfigs.WechatMerchantCertificatePrivateKey, AutoEncryptRequestSensitiveProperty = false, AutoDecryptResponseSensitiveProperty = false }); var request2 = new Models.QueryCertificatesRequest(); var response2 = await client2.ExecuteQueryCertificatesAsync(request2); Assert.DoesNotContain(response2.CertificateList, (e => e.EncryptCertificate.CipherText.StartsWith("-----BEGIN CERTIFICATE-----"))); } [Fact(DisplayName = "测试用例:解密响应中的敏感数据([GET] /ecommerce/applyments/out-request-no/{out_request_no})")] public void TestDecryptResponseSensitiveProperty_GetEcommerceApplymentByOutRequestNumberResponseTest() { var mock = new Models.GetEcommerceApplymentByOutRequestNumberResponse() { RawStatus = 200, RawHeaders = new ReadOnlyDictionary(new Dictionary() { { "K", "V" } }), ApplymentState = MockText, AccountValidation = new Models.GetEcommerceApplymentByOutRequestNumberResponse.Types.AccountValidation() { AccountName = Utilities.RSAUtility.EncryptWithECB(RSA_PUBLIC_KEY, MockText), AccountNumber = Utilities.RSAUtility.EncryptWithECB(RSA_PUBLIC_KEY, MockText), DestinationAccountName = MockText, DestinationAccountNumber = MockText } }; var data = MockClientInstance.Value.DecryptResponseSensitiveProperty(mock); Assert.Equal(MockText, data.ApplymentState); Assert.Equal(MockText, data.AccountValidation!.AccountNumber); Assert.Equal(MockText, data.AccountValidation!.DestinationAccountName); Assert.Equal(MockText, data.AccountValidation!.DestinationAccountNumber); Assert.Equal(MockText, data.AccountValidation!.AccountName); } [Fact(DisplayName = "测试用例:解密响应中的敏感数据([GET] /ecommerce/bill/fundflowbill)")] public void TestDecryptResponseSensitiveProperty_GetEcommerceBillFundflowBillResponse() { var mock = new Models.GetEcommerceBillFundflowBillResponse() { RawStatus = 200, DownloadBillCount = 1, DownloadBillList = new Models.GetEcommerceBillFundflowBillResponse.Types.DownloadBill[] { new Models.GetEcommerceBillFundflowBillResponse.Types.DownloadBill() { DownloadUrl = MockText, EncryptKey = Utilities.RSAUtility.EncryptWithECB(RSA_PUBLIC_KEY, MockText) }, new Models.GetEcommerceBillFundflowBillResponse.Types.DownloadBill() { DownloadUrl = MockText, EncryptKey = Utilities.RSAUtility.EncryptWithECB(RSA_PUBLIC_KEY, MockText) } } }; var data = MockClientInstance.Value.DecryptResponseSensitiveProperty(mock); Assert.Equal(1, data.DownloadBillCount); Assert.Equal(MockText, data.DownloadBillList[0].DownloadUrl); Assert.Equal(MockText, data.DownloadBillList[0].EncryptKey); Assert.Equal(MockText, data.DownloadBillList[1].DownloadUrl); Assert.Equal(MockText, data.DownloadBillList[1].EncryptKey); } [Fact(DisplayName = "测试用例:解密响应中的敏感数据([GET] /merchant-service/complaints-v2/{complaint_id})")] public void TestDecryptResponseSensitiveProperty_GetMerchantServiceComplaintByComplaintIdResponse() { var mock = new Models.GetMerchantServiceComplaintByComplaintIdResponse() { RawStatus = 200, ComplaintOrderList = new Models.GetMerchantServiceComplaintByComplaintIdResponse.Types.ComplaintOrder[] { new Models.GetMerchantServiceComplaintByComplaintIdResponse.Types.ComplaintOrder() { TransactionId = MockText } }, ComplaintDetail = MockText, PayerPhone = Utilities.RSAUtility.EncryptWithECB(RSA_PUBLIC_KEY, MockText) }; var data = MockClientInstance.Value.DecryptResponseSensitiveProperty(mock); Assert.Equal(MockText, data.ComplaintDetail); Assert.Equal(MockText, data.PayerPhone); Assert.Equal(MockText, data.ComplaintOrderList[0].TransactionId); } [Fact(DisplayName = "测试用例:解密响应中的敏感数据([GET] /merchant-service/complaints-v2)")] public void TestDecryptResponseSensitiveProperty_QueryMerchantServiceComplaintsResponse() { var mock = new Models.QueryMerchantServiceComplaintsResponse() { RawStatus = 200, ComplaintList = new Models.QueryMerchantServiceComplaintsResponse.Types.Complaint[] { new Models.QueryMerchantServiceComplaintsResponse.Types.Complaint() { PayerPhone = Utilities.RSAUtility.EncryptWithECB(RSA_PUBLIC_KEY, MockText), PayerOpenId = MockText } } }; var data = MockClientInstance.Value.DecryptResponseSensitiveProperty(mock); Assert.Equal(MockText, data.ComplaintList[0].PayerPhone); Assert.Equal(MockText, data.ComplaintList[0].PayerOpenId); } [Fact(DisplayName = "测试用例:解密响应中的敏感数据([GET] /smartguide/guides)")] public void TestDecryptResponseSensitiveProperty_QuerySmartGuidesResponse() { var mock = new Models.QuerySmartGuidesResponse() { RawStatus = 200, GuideList = new Models.QuerySmartGuidesResponse.Types.Guide[] { new Models.QuerySmartGuidesResponse.Types.Guide() { GuideId = MockText, UserName = Utilities.RSAUtility.EncryptWithECB(RSA_PUBLIC_KEY, MockText), UserMobile = Utilities.RSAUtility.EncryptWithECB(RSA_PUBLIC_KEY, MockText) } } }; var data = MockClientInstance.Value.DecryptResponseSensitiveProperty(mock); Assert.Equal(MockText, data.GuideList[0].GuideId); Assert.Equal(MockText, data.GuideList[0].UserName); Assert.Equal(MockText, data.GuideList[0].UserMobile); } [Fact(DisplayName = "测试用例:解密响应中的敏感数据([GET] /transfer/batches/out-batch-no/{out_batch_no}/details/out-detail-no/{out_detail_no})")] public void TestDecryptResponseSensitiveProperty_GetTransferBatchDetailByOutDetailNumberResponse() { var mock = new Models.GetTransferBatchDetailByOutDetailNumberResponse() { RawStatus = 200, UserName = Utilities.RSAUtility.EncryptWithECB(RSA_PUBLIC_KEY, MockText), OpenId = MockText }; var data = MockClientInstance.Value.DecryptResponseSensitiveProperty(mock); Assert.Equal(MockText, data.UserName); Assert.Equal(MockText, data.OpenId); } [Fact(DisplayName = "测试用例:解密响应中的敏感数据([GET] /transfer/batches/batch-id/{batch_id}/details/detail-id/{detail_id})")] public void DecryptResponseSensitiveProperty_GetTransferBatchDetailByDetailIdResponse() { var mock = new Models.GetTransferBatchDetailByDetailIdResponse() { RawStatus = 200, UserName = Utilities.RSAUtility.EncryptWithECB(RSA_PUBLIC_KEY, MockText), OpenId = MockText }; var data = MockClientInstance.Value.DecryptResponseSensitiveProperty(mock); Assert.Equal(MockText, data.UserName); Assert.Equal(MockText, data.OpenId); } [Fact(DisplayName = "测试用例:解密响应中的敏感数据([GET] /partner-transfer/batches/batch-id/{batch_id}/details/detail-id/{detail_id})")] public void TestDecryptResponseSensitiveProperty_GetPartnerTransferBatchDetailByDetailIdResponse() { var mock = new Models.GetPartnerTransferBatchDetailByDetailIdResponse() { RawStatus = 200, UserName = Utilities.RSAUtility.EncryptWithECB(RSA_PUBLIC_KEY, MockText), OpenId = MockText }; var data = MockClientInstance.Value.DecryptResponseSensitiveProperty(mock); Assert.Equal(MockText, data.UserName); Assert.Equal(MockText, data.OpenId); } } }