feat(tenpayv3): 升级公共组件

This commit is contained in:
Fu Diwei
2022-01-21 13:10:56 +08:00
parent 3656eb176f
commit b442a3d618
48 changed files with 304 additions and 569 deletions

View File

@@ -1,61 +0,0 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System.Linq;
namespace Newtonsoft.Json.Converters
{
internal class TextualStringIListWithCommaConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
bool ret = objectType == typeof(IList<string>) || objectType == typeof(List<string>);
if (!ret)
{
ret = objectType.IsGenericType &&
objectType.GetGenericTypeDefinition() == typeof(List<>) &&
objectType.GetElementType() == typeof(string);
}
return ret;
}
public override bool CanRead
{
get { return true; }
}
public override bool CanWrite
{
get { return true; }
}
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
{
return null;
}
else if (reader.TokenType == JsonToken.String)
{
string? value = serializer.Deserialize<string>(reader);
if (value == null)
return null;
if (string.IsNullOrEmpty(value))
return new List<string>();
return value.Split(',').ToList();
}
throw new JsonReaderException();
}
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
{
if (value != null)
writer.WriteValue(string.Join(",", value));
else
writer.WriteNull();
}
}
}

View File

@@ -1,44 +0,0 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace Newtonsoft.Json.Converters
{
internal class TextualStringIListWithJsonConverter : JsonConverter<IList<string>?>
{
private readonly JsonConverter<List<string>?> _converter = new TextualStringListWithJsonConverter();
public override bool CanRead
{
get { return true; }
}
public override bool CanWrite
{
get { return true; }
}
public override IList<string>? ReadJson(JsonReader reader, Type objectType, IList<string>? existingValue, bool hasExistingValue, JsonSerializer serializer)
{
return _converter.ReadJson(reader, objectType, ConvertIListToList(existingValue), hasExistingValue, serializer);
}
public override void WriteJson(JsonWriter writer, IList<string>? value, JsonSerializer serializer)
{
_converter.WriteJson(writer, ConvertIListToList(value), serializer);
}
private List<string>? ConvertIListToList(IList<string>? src)
{
if (src == null)
return null;
List<string>? dest = src as List<string>;
if (dest != null)
return dest;
return new List<string>(src);
}
}
}

View File

@@ -1,47 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace Newtonsoft.Json.Converters
{
internal class TextualStringListWithCommaConverter : JsonConverter<List<string>?>
{
public override bool CanRead
{
get { return true; }
}
public override bool CanWrite
{
get { return true; }
}
public override List<string>? ReadJson(JsonReader reader, Type objectType, List<string>? existingValue, bool hasExistingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
{
return null;
}
else if (reader.TokenType == JsonToken.String)
{
string? value = serializer.Deserialize<string>(reader);
if (value == null)
return existingValue;
return value.Split(',').ToList();
}
throw new JsonReaderException();
}
public override void WriteJson(JsonWriter writer, List<string>? value, JsonSerializer serializer)
{
if (value != null)
writer.WriteValue(string.Join(",", value));
else
writer.WriteNull();
}
}
}

View File

@@ -1,46 +0,0 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace Newtonsoft.Json.Converters
{
internal class TextualStringListWithJsonConverter : JsonConverter<List<string>?>
{
public override bool CanRead
{
get { return true; }
}
public override bool CanWrite
{
get { return true; }
}
public override List<string>? ReadJson(JsonReader reader, Type objectType, List<string>? existingValue, bool hasExistingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
{
return null;
}
else if (reader.TokenType == JsonToken.String)
{
string? value = serializer.Deserialize<string>(reader);
if (value == null)
return existingValue;
return JsonConvert.DeserializeObject<List<string>>(value);
}
throw new JsonReaderException();
}
public override void WriteJson(JsonWriter writer, List<string>? value, JsonSerializer serializer)
{
if (value != null)
writer.WriteValue(JsonConvert.SerializeObject(value, Formatting.None));
else
writer.WriteNull();
}
}
}

View File

@@ -1,37 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace System.Text.Json.Converters
{
internal class TextualStringIListWithCommaConverter : JsonConverter<List<string>?>
{
public override List<string>? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.Null)
{
return null;
}
else if (reader.TokenType == JsonTokenType.String)
{
string? value = reader.GetString();
if (value == null)
return null;
return value.Split(',').ToList();
}
throw new JsonException();
}
public override void Write(Utf8JsonWriter writer, List<string>? value, JsonSerializerOptions options)
{
if (value != null)
writer.WriteStringValue(string.Join(",", value));
else
writer.WriteNullValue();
}
}
}

View File

@@ -1,34 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace System.Text.Json.Converters
{
internal class TextualStringIListWithJsonConverter : JsonConverter<IList<string>?>
{
private readonly JsonConverter<List<string>?> _converter = new TextualStringListWithJsonConverter();
public override IList<string>? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return _converter.Read(ref reader, typeToConvert, options);
}
public override void Write(Utf8JsonWriter writer, IList<string>? value, JsonSerializerOptions options)
{
_converter.Write(writer, ConvertIListToList(value), options);
}
private List<string>? ConvertIListToList(IList<string>? src)
{
if (src == null)
return null;
List<string>? dest = src as List<string>;
if (dest != null)
return dest;
return new List<string>(src);
}
}
}

View File

@@ -1,34 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace System.Text.Json.Converters
{
internal class TextualStringListWithCommaConverter : JsonConverter<IList<string>?>
{
private readonly JsonConverter<List<string>?> _converter = new TextualStringIListWithCommaConverter();
public override IList<string>? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return _converter.Read(ref reader, typeToConvert, options);
}
public override void Write(Utf8JsonWriter writer, IList<string>? value, JsonSerializerOptions options)
{
_converter.Write(writer, ConvertIListToList(value), options);
}
private List<string>? ConvertIListToList(IList<string>? src)
{
if (src == null)
return null;
List<string>? dest = src as List<string>;
if (dest != null)
return dest;
return new List<string>(src);
}
}
}

View File

@@ -1,36 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace System.Text.Json.Converters
{
internal class TextualStringListWithJsonConverter : JsonConverter<List<string>?>
{
public override List<string>? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.Null)
{
return null;
}
else if (reader.TokenType == JsonTokenType.String)
{
string? value = reader.GetString();
if (value == null)
return null;
return JsonSerializer.Deserialize<List<string>>(value, options);
}
throw new JsonException();
}
public override void Write(Utf8JsonWriter writer, List<string>? value, JsonSerializerOptions options)
{
if (value != null)
writer.WriteStringValue(JsonSerializer.Serialize(value, options));
else
writer.WriteNullValue();
}
}
}

View File

@@ -692,9 +692,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// 获取或设置优惠费率活动值。 /// 获取或设置优惠费率活动值。
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("activities_rate")] [Newtonsoft.Json.JsonProperty("activities_rate")]
[Newtonsoft.Json.JsonConverter(typeof(Converters.NewtonsoftJsonActivityRateConverter))] [Newtonsoft.Json.JsonConverter(typeof(Converters.RequestPropertyActivityRateNewtonsoftJsonConverter))]
[System.Text.Json.Serialization.JsonPropertyName("activities_rate")] [System.Text.Json.Serialization.JsonPropertyName("activities_rate")]
[System.Text.Json.Serialization.JsonConverter(typeof(Converters.SystemTextJsonActivityRateConverter))] [System.Text.Json.Serialization.JsonConverter(typeof(Converters.RequestPropertyActivityRateSystemTextJsonConverter))]
public double? ActivityRate { get; set; } public double? ActivityRate { get; set; }
/// <summary> /// <summary>
@@ -793,7 +793,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
internal static class Converters internal static class Converters
{ {
internal class NewtonsoftJsonActivityRateConverter : Newtonsoft.Json.JsonConverter<double?> internal class RequestPropertyActivityRateNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter<double?>
{ {
public override bool CanRead public override bool CanRead
{ {
@@ -837,7 +837,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
} }
} }
internal class SystemTextJsonActivityRateConverter : System.Text.Json.Serialization.JsonConverter<double?> internal class RequestPropertyActivityRateSystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter<double?>
{ {
public override double? Read(ref System.Text.Json.Utf8JsonReader reader, Type typeToConvert, System.Text.Json.JsonSerializerOptions options) public override double? Read(ref System.Text.Json.Utf8JsonReader reader, Type typeToConvert, System.Text.Json.JsonSerializerOptions options)
{ {

View File

@@ -280,6 +280,17 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
} }
} }
internal static class Converters
{
public class RequestPropertyMediaIdListNewtonsoftJsonConverter : Newtonsoft.Json.Converters.TextualObjectInJsonFormatConverterBase<IList<string>>
{
}
public class RequestPropertyMediaIdListSystemTextJsonConverter : System.Text.Json.Converters.TextualObjectInJsonFormatConverterBase<IList<string>>
{
}
}
/// <summary> /// <summary>
/// 获取或设置业务申请编号。 /// 获取或设置业务申请编号。
/// </summary> /// </summary>
@@ -368,18 +379,18 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// 获取或设置特殊资质图片媒体文件标识 ID 列表。 /// 获取或设置特殊资质图片媒体文件标识 ID 列表。
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("qualifications")] [Newtonsoft.Json.JsonProperty("qualifications")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.TextualStringIListWithJsonConverter))] [Newtonsoft.Json.JsonConverter(typeof(Converters.RequestPropertyMediaIdListNewtonsoftJsonConverter))]
[System.Text.Json.Serialization.JsonPropertyName("qualifications")] [System.Text.Json.Serialization.JsonPropertyName("qualifications")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.TextualStringIListWithJsonConverter))] [System.Text.Json.Serialization.JsonConverter(typeof(Converters.RequestPropertyMediaIdListSystemTextJsonConverter))]
public IList<string>? QualificationPictureMediaIdList { get; set; } public IList<string>? QualificationPictureMediaIdList { get; set; }
/// <summary> /// <summary>
/// 获取或设置补充材料媒体文件标识 ID 列表。 /// 获取或设置补充材料媒体文件标识 ID 列表。
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("business_addition_pics")] [Newtonsoft.Json.JsonProperty("business_addition_pics")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.TextualStringIListWithJsonConverter))] [Newtonsoft.Json.JsonConverter(typeof(Converters.RequestPropertyMediaIdListNewtonsoftJsonConverter))]
[System.Text.Json.Serialization.JsonPropertyName("business_addition_pics")] [System.Text.Json.Serialization.JsonPropertyName("business_addition_pics")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.TextualStringIListWithJsonConverter))] [System.Text.Json.Serialization.JsonConverter(typeof(Converters.RequestPropertyMediaIdListSystemTextJsonConverter))]
public IList<string>? BusinessAdditionPictureMediaIdList { get; set; } public IList<string>? BusinessAdditionPictureMediaIdList { get; set; }
/// <summary> /// <summary>

View File

@@ -0,0 +1,27 @@
## SKIT.FlurlHttpClient.Wechat.TenpayV3
[![GitHub Stars](https://img.shields.io/github/stars/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat?logo=github&label=Stars)](https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat) [![GitHub Forks](https://img.shields.io/github/forks/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat?logo=github&label=Forks)](https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat) [![NuGet Download](https://img.shields.io/nuget/dt/SKIT.FlurlHttpClient.Wechat.TenpayV3.svg?sanitize=true&label=Downloads)](https://www.nuget.org/packages/SKIT.FlurlHttpClient.Wechat.TenpayV3) [![License](https://img.shields.io/github/license/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat?label=License)](https://mit-license.org/)
基于 `Flurl.Http` 的微信商户平台 API v3 版客户端。
---
### 【功能特性】
- 基于微信支付 v3 版 API 封装。
- 支持直连商户、服务商两种模式。
- 请求时自动生成签名,无需开发者手动干预。
- 提供了微信支付所需的 RSA、AES、SHA-256 等算法工具类。
- 提供了调起支付签名、解析响应敏感数据、解析回调通知事件敏感数据等扩展方法。
---
### 【开发文档】
[点此查看](https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat)。
---
### 【更新日志】
[点此查看](https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat/blob/main/CHANGELOG.md)。

View File

@@ -9,6 +9,8 @@
<PropertyGroup> <PropertyGroup>
<PackageId>SKIT.FlurlHttpClient.Wechat.TenpayV3</PackageId> <PackageId>SKIT.FlurlHttpClient.Wechat.TenpayV3</PackageId>
<PackageIcon>LOGO.png</PackageIcon>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageLicenseExpression>MIT</PackageLicenseExpression> <PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat</PackageProjectUrl> <PackageProjectUrl>https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat</PackageProjectUrl>
<PackageTags>Flurl.Http Wechat Weixin MicroMessage Tenpay WechatPay WeixinPay Wxpay 微信 微信支付 微信商户</PackageTags> <PackageTags>Flurl.Http Wechat Weixin MicroMessage Tenpay WechatPay WeixinPay Wxpay 微信 微信支付 微信商户</PackageTags>
@@ -17,11 +19,22 @@
<Authors>Fu Diwei</Authors> <Authors>Fu Diwei</Authors>
<RepositoryType>git</RepositoryType> <RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat.git</RepositoryUrl> <RepositoryUrl>https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat.git</RepositoryUrl>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
<Deterministic>true</Deterministic>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<GenerateDocumentationFile>true</GenerateDocumentationFile> <GenerateDocumentationFile>true</GenerateDocumentationFile>
<IncludeSymbols>true</IncludeSymbols> <IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat> <SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<None Include="../../LOGO.png" Pack="true" PackagePath="/" />
<None Include="README.md" Pack="true" PackagePath="/" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<Reference Include="System.Web" Condition="'$(TargetFramework)' == 'net461' Or '$(TargetFramework)' == 'net47'" /> <Reference Include="System.Web" Condition="'$(TargetFramework)' == 'net461' Or '$(TargetFramework)' == 'net47'" />
</ItemGroup> </ItemGroup>
@@ -29,7 +42,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="System.ValueTuple" Version="4.5.0" Condition="'$(TargetFramework)' == 'net461'" /> <PackageReference Include="System.ValueTuple" Version="4.5.0" Condition="'$(TargetFramework)' == 'net461'" />
<PackageReference Include="Portable.BouncyCastle" Version="1.9.0" /> <PackageReference Include="Portable.BouncyCastle" Version="1.9.0" />
<PackageReference Include="SKIT.FlurlHttpClient.Common" Version="2.1.1" /> <PackageReference Include="SKIT.FlurlHttpClient.Common" Version="2.2.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -10,7 +10,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Utilities
public static class SHA256Utility public static class SHA256Utility
{ {
/// <summary> /// <summary>
/// 获取信息摘要。 /// 获取 SHA-256 信息摘要。
/// </summary> /// </summary>
/// <param name="bytes">信息字节数组。</param> /// <param name="bytes">信息字节数组。</param>
/// <returns>信息摘要。</returns> /// <returns>信息摘要。</returns>
@@ -24,7 +24,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Utilities
} }
/// <summary> /// <summary>
/// 获取信息摘要。 /// 获取 SHA-256 信息摘要。
/// </summary> /// </summary>
/// <param name="message">文本信息。</param> /// <param name="message">文本信息。</param>
/// <returns>信息摘要。</returns> /// <returns>信息摘要。</returns>

View File

@@ -4,7 +4,7 @@ using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV2.UnitTests namespace SKIT.FlurlHttpClient.Wechat.TenpayV2.UnitTests
{ {
public class TestCase_JsonConverterTest public class TestCase_JsonConverterTests
{ {
[Fact(DisplayName = "测试用例:自定义转换器之 `FlattenNArrayObjectConverterBase`")] [Fact(DisplayName = "测试用例:自定义转换器之 `FlattenNArrayObjectConverterBase`")]
public void TestFlattenNArrayObjectConverter() public void TestFlattenNArrayObjectConverter()

View File

@@ -13,8 +13,7 @@
"transfer_amount": 200000, "transfer_amount": 200000,
"transfer_remark": "2020年4月报销", "transfer_remark": "2020年4月报销",
"openid": "o-MYE42l80oelYMDE34nYD456Xoy", "openid": "o-MYE42l80oelYMDE34nYD456Xoy",
"user_name": "757b340b45ebef5467rter35gf464344v3542sdf4t6re4tb4f54ty45t4yyry45", "user_name": "757b340b45ebef5467rter35gf464344v3542sdf4t6re4tb4f54ty45t4yyry45"
"user_id_card": "8609cb22e1774a50a930e414cc71eca06121bcd266335cda230d24a7886a8d9f"
} }
], ],
"sp_appid": "wxf636efh567hg4388", "sp_appid": "wxf636efh567hg4388",

View File

@@ -11,8 +11,7 @@
"transfer_amount": 200000, "transfer_amount": 200000,
"transfer_remark": "2020年4月报销", "transfer_remark": "2020年4月报销",
"openid": "o-MYE42l80oelYMDE34nYD456Xoy", "openid": "o-MYE42l80oelYMDE34nYD456Xoy",
"user_name": "757b340b45ebef5467rter35gf464344v3542sdf4t6re4tb4f54ty45t4yyry45", "user_name": "757b340b45ebef5467rter35gf464344v3542sdf4t6re4tb4f54ty45t4yyry45"
"user_id_card": "8609cb22e1774a50a930e414cc71eca06121bcd266335cda230d24a7886a8d9f"
} }
] ]
} }

View File

@@ -1,8 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>netcoreapp3.1; net6.0</TargetFrameworks> <TargetFrameworks>net472; netcoreapp3.1; net6.0</TargetFrameworks>
<LangVersion>9.0</LangVersion> <LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<NullableReferenceTypes>true</NullableReferenceTypes>
<IsPackable>false</IsPackable>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -0,0 +1,26 @@
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 TestCase_AesUtilityTests
{
[Fact(DisplayName = "测试用例AES-GCM 解密")]
public void TestAESGCMDecrypt()
{
string key = "f09b03a7a1902b5b4913856f1fd07ab1";
string iv = "aae8c2e79c5b";
string aad = "certificate";
string cipherText = "x9kkL5w1JuaypcjhrYIP+kVNlN8o8uN4yJyJjy5lg+PyPnQL2Zn//ORaXAyzdaK/WBMVd3u/Y9hLaTBLMyRXzowsrkJ5PT37johye48N7BAJQ0PJwW++d1RdhOOPjoqfmws6rSV5Gv2qhfdKjmpxVjr8xr71dtBt8J2wu+bAV99HHQoAynm/Pp9OQYZgpOQ+1cyFHd43TAxOoFfmixKrXr3HP8lJot0XCUSq4qkr1Hs44FV2KuzntSk8eqKr5N17UcuPF3VYnnnF/AvQ7HuLKWwrHhUbaXfkwy0Q2n36UJMfBj7344S97E8BnS89ojgOPQi+olBPyNgrtDWHgsJAKu7HA6PV/FgmXcrZirje/AH1u25es4z5xItHscm//6rDvALgf7greV5OJzMsSl/KVDtbkjDSzim0j4ZTduIfzh7l6jfOz115ITcNILT9ef2KkcMyBBc89GZlMGeHTbgsBHzGeLawX3dXFjqt5aMnHM3VWCovA2aUM4c//rqkZGf+Va86OEFoJQLiSTFpkOrKxcIxcrbKPLTgiDWRT3wzmnUDg7kSPbluzt3ROvMFq9lB8bO/pBd7TD2w87sfUdKLj69FniX6s37SBeRVhw8GSIvBf5lpLUhqL5zKYlbuAWePuz0wVV4NTtkaVKZlmm8KTODyZDFpsyKPubDDcwT1ftRf5aSVM4x04I/1B7GkNz/TOy+zpJ0h0B7VHdxyO5JYiI/1qsatX/FE2aJdQYMYOtqfDH7ZH5UUKIqo538OKvE2M4MlBR/aVE4z4QDKfE/1kYrOfvVGfDzF/FWHfUrcqB8kdQMvk8vCoM8yYZsX4KE1aoJbNM2pWv2tpr9JE8b/VQgUyHOgPYAha+UOmZki4Sfl9H62687EIWdbM57ZxmwIiBp60SrJLiBfZon9JqXKdtJOKj0CRokQiBnONNXCVerLFeBNQfeKRw8tgJXf+QPohMGYkSDdc8hTgdbmhTwB1Vv01stlYK12QMNRCovlp/fcmpB72Phlq+/3p5pqMzknw+qm5QAz7JnpZJCFHit52gHwAkKRkVPB3HF2rfLrdTYz5c9Bok1ICAY9My47eLFdduIe99V52cjMLQuUmNFBPrDdyZKVqIHJ/wtWO/wIFpAVGSJMHctyEKmeJVc1IQN74Wm00PrpPackHdO3G41bBmkp5pqUdsSgSkwdfNVqv0cMcSe04NrRGNKMcZ7TA/CMaP1YnhxvVE+z8aksJqSJ+gdplvuwl40y5C8UEHeAi1V8Q0Bf4YvYRgOVIWm2Lzjdn2z9PWLGcStUj11/1hthk2li4V3mgm2Cr2IZme2sn4rZmJ6dexGP1nk+ZYOq0xLE8F7oex9gyDN+A/6zHqnuhO/X08qye0gochMr8U89Qvj2c0L3P2mjCea2H1mEriAJPqMPMKIinh1lQJEZufnfCcPxbZLKTtl6zHtHgOztejd1gV/nUyCVKD4MCMfBDy9C/Af8pWx6akOg/QSQNIGA2AI6zprHn9zEjpFIzXJYvruVI22Yt6oF9Xnt7Ki82wRK2M96r4kj6cwSs4exMPGv8fWMrFTm0Br6p6T+HZsxyyn2ChuPIgpfisnce/ZaU/0xCZhK/K79+TK2GeeChq5oEpua/1tx4+kDHi7H9381pLJmy2oXW060c2mmwA9+EpcuwEDhr8fsnghbv41u7b1NhEmWNVUy29Dwaz61PPGUdh5DsvaKLWC+raZ/6UEKPw+tiABJ5o6u2jAWgmEYmmJCKapNgtfPc6D+O0aHH9oqh6u4+8NRAhusPZzDGWBr6AT4pexgWFeEhZhn6bXM9HhpUe0IhOTw5D+tqXrTlNon4kjYibiMUFy1h2YyYS3IEdu1J4xqvo0rFyCxF1C+P6ubc0tClRPkXg==";
string actualPlain = Utilities.AESUtility.DecryptWithGCM(key: key, iv: iv, aad: aad, cipherText: cipherText);
string expectedPlain = "-----BEGIN CERTIFICATE-----\nMIID3DCCAsSgAwIBAgIUGZNrTcamx3sFSJsQli3v9C6gZe8wDQYJKoZIhvcNAQEL\nBQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT\nFFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg\nQ0EwHhcNMjAwODAxMDczNTE4WhcNMjUwNzMxMDczNTE4WjBuMRgwFgYDVQQDDA9U\nZW5wYXkuY29tIHNpZ24xEzARBgNVBAoMClRlbnBheS5jb20xHTAbBgNVBAsMFFRl\nbnBheS5jb20gQ0EgQ2VudGVyMQswCQYDVQQGDAJDTjERMA8GA1UEBwwIU2hlblpo\nZW4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDOAYHqxCqaRzoTIvgV\nixaYJJvmvHbiczbx5MQ9XL1ITSFxkTsNsk7RKHnO7eBS5imheJgQwd22Ky+XclSe\n7B4odssu/l/+gHo2gooTYrrCpQrOkpvGMf8R8aI56BQIF+vsomDvVq1NojHV2Fql\njMwFXzhj2EmU6p6gDv9iL7q1NrfnxFx8iJe4OhIB5Ek4qn1xXxrTUhiULd2vXlbI\nXhRetZSNcJsLt5Rw7D7c8F+aX2JchfeqsZECwKW7bSjMbVWWC6M9MgkB/aId8P0y\n7qEiiXFJkfkg1I/E1ud2apopsid5tdCyRRR6+MhhX2EC8S04MN4soUT7haqNNxX2\nrKHnAgMBAAGjgYEwfzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIE8DBlBgNVHR8EXjBc\nMFqgWKBWhlRodHRwOi8vZXZjYS5pdHJ1cy5jb20uY24vcHVibGljL2l0cnVzY3Js\nP0NBPTFCRDQyMjBFNTBEQkMwNEIwNkFEMzk3NTQ5ODQ2QzAxQzNFOEVCRDIwDQYJ\nKoZIhvcNAQELBQADggEBAJyg2z4oLQmPfftLQWyzbUc9ONhRMtfA+tVlVBgtLLKn\nWuDlsmEntheM07fu84F4pcfs3yHzjD7pAOFbO4Yt1yhQ50DK35sjbRWepPdWJZLl\nni7KBctcmm0o4zq37oB7vonmBEbFqYs9DaINYOjgI3J25iSBkPVC7dBbvFj2xB0L\ncIcXipq30tDdC/oUem27MNzwZAt49WthKhw6u3HSkcE5cO4LyYTsJhSyG/7LXwvV\nMgX4Jyzo0SSiGOU1/beaZssTVI8sTPJVlHWjhNE3Lc2SaAlKGfGwvt0X3cEZEF+7\noEZIFTkkAF2JhqfnpR3gST0G8Umq1SaVtCPP/zVI8x0=\n-----END CERTIFICATE-----";
Assert.Equal(expectedPlain, actualPlain);
}
}
}

View File

@@ -7,10 +7,10 @@ using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
{ {
public class WechatTenpayExecuteBillTests public class TestCase_ApiExecuteExecuteBillTests
{ {
[Fact(DisplayName = "[GET] /bill/tradebill")] [Fact(DisplayName = "测试用例:调用 API [GET] /bill/tradebill")]
public async Task GetBillTradeBillTest() public async Task TestExecuteGetBillTradeBill()
{ {
var request = new Models.GetBillTradeBillRequest() var request = new Models.GetBillTradeBillRequest()
{ {
@@ -24,8 +24,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.NotNull(response.DownloadUrl); Assert.NotNull(response.DownloadUrl);
} }
[Fact(DisplayName = "[GET] /bill/fundflowbill")] [Fact(DisplayName = "测试用例:调用 API [GET] /bill/fundflowbill")]
public async Task GetBillFundflowBillTest() public async Task TestExecuteGetBillFundflowBill()
{ {
var request = new Models.GetBillFundflowBillRequest() var request = new Models.GetBillFundflowBillRequest()
{ {
@@ -39,8 +39,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.NotNull(response.DownloadUrl); Assert.NotNull(response.DownloadUrl);
} }
[Fact(DisplayName = "[GET] /billdownload/file")] [Fact(DisplayName = "测试用例:调用 API [GET] /billdownload/file")]
public async Task DownloadBillFileTest() public async Task TestExecuteDownloadBillFile()
{ {
var request = new Models.DownloadBillFileRequest() var request = new Models.DownloadBillFileRequest()
{ {

View File

@@ -7,10 +7,10 @@ using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
{ {
public class WechatTenpayExecuteCombineTransactionsTests public class TestCase_ApiExecuteExecuteCombineTransactionsTests
{ {
[Fact(DisplayName = "[POST] /combine-transactions/app")] [Fact(DisplayName = "测试用例:调用 API [POST] /combine-transactions/app")]
public async Task CreateCombineTransactionAppTest() public async Task TestExecuteCreateCombineTransactionApp()
{ {
var request = new Models.CreateCombineTransactionAppRequest() var request = new Models.CreateCombineTransactionAppRequest()
{ {
@@ -35,8 +35,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.NotNull(response.PrepayId); Assert.NotNull(response.PrepayId);
} }
[Fact(DisplayName = "[POST] /combine-transactions/jsapi")] [Fact(DisplayName = "测试用例:调用 API [POST] /combine-transactions/jsapi")]
public async Task CreateCombineTransactionJsapiTest() public async Task TestExecuteCreateCombineTransactionJsapi()
{ {
var request = new Models.CreateCombineTransactionJsapiRequest() var request = new Models.CreateCombineTransactionJsapiRequest()
{ {
@@ -74,8 +74,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.NotNull(response.PrepayId); Assert.NotNull(response.PrepayId);
} }
[Fact(DisplayName = "[POST] /combine-transactions/h5")] [Fact(DisplayName = "测试用例:调用 API [POST] /combine-transactions/h5")]
public async Task CreateCombineTransactionH5Test() public async Task TestExecuteCreateCombineTransactionH5()
{ {
var request = new Models.CreateCombineTransactionH5Request() var request = new Models.CreateCombineTransactionH5Request()
{ {
@@ -100,8 +100,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.NotNull(response.H5Url); Assert.NotNull(response.H5Url);
} }
[Fact(DisplayName = "[POST] /combine-transactions/native")] [Fact(DisplayName = "测试用例:调用 API [POST] /combine-transactions/native")]
public async Task CreateCombineTransactionNativeTest() public async Task TestExecuteCreateCombineTransactionNative()
{ {
var request = new Models.CreateCombineTransactionNativeRequest() var request = new Models.CreateCombineTransactionNativeRequest()
{ {
@@ -126,8 +126,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.NotNull(response.QrcodeUrl); Assert.NotNull(response.QrcodeUrl);
} }
[Fact(DisplayName = "[GET] /combine-transactions/out-trade-no/{combine_out_trade_no}")] [Fact(DisplayName = "测试用例:调用 API [GET] /combine-transactions/out-trade-no/{combine_out_trade_no}")]
public async Task GetCombineTransactionByCombineOutTradeNumberTest() public async Task TestExecuteGetCombineTransactionByCombineOutTradeNumber()
{ {
var request = new Models.GetCombineTransactionByCombineOutTradeNumberRequest() var request = new Models.GetCombineTransactionByCombineOutTradeNumberRequest()
{ {
@@ -141,8 +141,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.NotEmpty(response.SubOrderList); Assert.NotEmpty(response.SubOrderList);
} }
[Fact(DisplayName = "[POST] /combine-transactions/out-trade-no/{combine_out_trade_no}/close")] [Fact(DisplayName = "测试用例:调用 API [POST] /combine-transactions/out-trade-no/{combine_out_trade_no}/close")]
public async Task CloseCombineTransactionTest() public async Task TestExecuteCloseCombineTransaction()
{ {
var request = new Models.CloseCombineTransactionRequest() var request = new Models.CloseCombineTransactionRequest()
{ {

View File

@@ -7,10 +7,10 @@ using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
{ {
public class WechatTenpayExecuteMarketingBusifavorTests public class TestCase_ApiExecuteExecuteMarketingBusifavorTests
{ {
[Fact(DisplayName = "[POST] /marketing/busifavor/stocks")] [Fact(DisplayName = "测试用例:调用 API [POST] /marketing/busifavor/stocks")]
public async Task CreateMarketingBusifavorStockTest() public async Task TestExecuteCreateMarketingBusifavorStock()
{ {
var request = new Models.CreateMarketingBusifavorStockRequest() var request = new Models.CreateMarketingBusifavorStockRequest()
{ {
@@ -45,8 +45,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.NotNull(response.StockId); Assert.NotNull(response.StockId);
} }
[Fact(DisplayName = "[GET] /marketing/busifavor/stocks/{stock_id}")] [Fact(DisplayName = "测试用例:调用 API [GET] /marketing/busifavor/stocks/{stock_id}")]
public async Task GetMarketingBusifavorStockByStockIdTest() public async Task TestExecuteGetMarketingBusifavorStockByStockId()
{ {
var request = new Models.GetMarketingBusifavorStockByStockIdRequest() var request = new Models.GetMarketingBusifavorStockByStockIdRequest()
{ {
@@ -64,8 +64,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.NotNull(response.CouponCodeMode); Assert.NotNull(response.CouponCodeMode);
} }
[Fact(DisplayName = "[GET] /marketing/busifavor/users/{openid}/coupons")] [Fact(DisplayName = "测试用例:调用 API [GET] /marketing/busifavor/users/{openid}/coupons")]
public async Task QueryMarketingBusifavorUserCouponsTest() public async Task TestExecuteQueryMarketingBusifavorUserCoupons()
{ {
var request = new Models.QueryMarketingBusifavorUserCouponsRequest() var request = new Models.QueryMarketingBusifavorUserCouponsRequest()
{ {
@@ -78,8 +78,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.True(response.IsSuccessful()); Assert.True(response.IsSuccessful());
} }
[Fact(DisplayName = "[POST] /marketing/busifavor/callbacks")] [Fact(DisplayName = "测试用例:调用 API [POST] /marketing/busifavor/callbacks")]
public async Task UpdateMarketingBusifavorCallbackTest() public async Task TestExecuteUpdateMarketingBusifavorCallback()
{ {
var request = new Models.UpdateMarketingBusifavorCallbackRequest() var request = new Models.UpdateMarketingBusifavorCallbackRequest()
{ {
@@ -91,8 +91,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.NotNull(response.NotifyUrl); Assert.NotNull(response.NotifyUrl);
} }
[Fact(DisplayName = "[GET] /marketing/busifavor/callbacks")] [Fact(DisplayName = "测试用例:调用 API [GET] /marketing/busifavor/callbacks")]
public async Task GetMarketingBusifavorCallbackTest() public async Task TestExecuteGetMarketingBusifavorCallback()
{ {
var request = new Models.GetMarketingBusifavorCallbackRequest(); var request = new Models.GetMarketingBusifavorCallbackRequest();
var response = await TestClients.Instance.ExecuteGetMarketingBusifavorCallbackAsync(request); var response = await TestClients.Instance.ExecuteGetMarketingBusifavorCallbackAsync(request);

View File

@@ -7,10 +7,10 @@ using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
{ {
public class WechatTenpayExecuteMarketingFavorTests public class TestCase_ApiExecuteExecuteMarketingFavorTests
{ {
[Fact(DisplayName = "[POST] /marketing/favor/coupon-stocks")] [Fact(DisplayName = "测试用例:调用 API [POST] /marketing/favor/coupon-stocks")]
public async Task CreateMarketingFavorStockTest() public async Task TestExecuteCreateMarketingFavorStock()
{ {
var request = new Models.CreateMarketingFavorStockRequest() var request = new Models.CreateMarketingFavorStockRequest()
{ {
@@ -42,8 +42,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.NotNull(response.StockId); Assert.NotNull(response.StockId);
} }
[Fact(DisplayName = "[POST] /marketing/favor/stocks/{stock_id}/start")] [Fact(DisplayName = "测试用例:调用 API [POST] /marketing/favor/stocks/{stock_id}/start")]
public async Task StartMarketingFavorStockTest() public async Task TestExecuteStartMarketingFavorStock()
{ {
var request = new Models.StartMarketingFavorStockRequest() var request = new Models.StartMarketingFavorStockRequest()
{ {
@@ -55,8 +55,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.NotNull(response.StockId); Assert.NotNull(response.StockId);
} }
[Fact(DisplayName = "[POST] /marketing/favor/stocks/{stock_id}/pause")] [Fact(DisplayName = "测试用例:调用 API [POST] /marketing/favor/stocks/{stock_id}/pause")]
public async Task PauseMarketingFavorStockTest() public async Task TestExecutePauseMarketingFavorStock()
{ {
var request = new Models.PauseMarketingFavorStockRequest() var request = new Models.PauseMarketingFavorStockRequest()
{ {
@@ -68,8 +68,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.NotNull(response.StockId); Assert.NotNull(response.StockId);
} }
[Fact(DisplayName = "[POST] /marketing/favor/stocks/{stock_id}/restart")] [Fact(DisplayName = "测试用例:调用 API [POST] /marketing/favor/stocks/{stock_id}/restart")]
public async Task RestartMarketingFavorStockTest() public async Task TestExecuteRestartMarketingFavorStock()
{ {
var request = new Models.RestartMarketingFavorStockRequest() var request = new Models.RestartMarketingFavorStockRequest()
{ {
@@ -81,8 +81,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.NotNull(response.StockId); Assert.NotNull(response.StockId);
} }
[Fact(DisplayName = "[GET] /marketing/favor/stocks/{stock_id}")] [Fact(DisplayName = "测试用例:调用 API [GET] /marketing/favor/stocks/{stock_id}")]
public async Task GetMarketingFavorStockByStockIdTest() public async Task TestExecuteGetMarketingFavorStockByStockId()
{ {
var request = new Models.GetMarketingFavorStockByStockIdRequest() var request = new Models.GetMarketingFavorStockByStockIdRequest()
{ {
@@ -94,8 +94,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.NotNull(response.StockId); Assert.NotNull(response.StockId);
} }
[Fact(DisplayName = "[GET] /marketing/favor/stocks")] [Fact(DisplayName = "测试用例:调用 API [GET] /marketing/favor/stocks")]
public async Task QueryMarketingFavorStocksTest() public async Task TestExecuteQueryMarketingFavorStocks()
{ {
var request = new Models.QueryMarketingFavorStocksRequest(); var request = new Models.QueryMarketingFavorStocksRequest();
var response = await TestClients.Instance.ExecuteQueryMarketingFavorStocksAsync(request); var response = await TestClients.Instance.ExecuteQueryMarketingFavorStocksAsync(request);
@@ -113,8 +113,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
} }
} }
[Fact(DisplayName = "[GET] /marketing/favor/stocks/{stock_id}/merchants")] [Fact(DisplayName = "测试用例:调用 API [GET] /marketing/favor/stocks/{stock_id}/merchants")]
public async Task QueryMarketingFavorStockMerchantsTest() public async Task TestExecuteQueryMarketingFavorStockMerchants()
{ {
var request = new Models.QueryMarketingFavorStockMerchantsRequest() var request = new Models.QueryMarketingFavorStockMerchantsRequest()
{ {
@@ -127,8 +127,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.NotNull(response.MerchantIdList); Assert.NotNull(response.MerchantIdList);
} }
[Fact(DisplayName = "[GET] /marketing/favor/stocks/{stock_id}/items")] [Fact(DisplayName = "测试用例:调用 API [GET] /marketing/favor/stocks/{stock_id}/items")]
public async Task QueryMarketingFavorStockItemsTest() public async Task TestExecuteQueryMarketingFavorStockItems()
{ {
var request = new Models.QueryMarketingFavorStockItemsRequest() var request = new Models.QueryMarketingFavorStockItemsRequest()
{ {
@@ -141,8 +141,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.NotNull(response.Items); Assert.NotNull(response.Items);
} }
[Fact(DisplayName = "[POST] /marketing/favor/callbacks")] [Fact(DisplayName = "测试用例:调用 API [POST] /marketing/favor/callbacks")]
public async Task UpdateMarketingFavorCallbackTest() public async Task TestExecuteUpdateMarketingFavorCallback()
{ {
var request = new Models.UpdateMarketingFavorCallbackRequest() var request = new Models.UpdateMarketingFavorCallbackRequest()
{ {

View File

@@ -7,10 +7,10 @@ using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
{ {
public class WechatTenpayExecuteMarketingMediaTests public class TestCase_ApiExecuteExecuteMarketingMediaTests
{ {
[Fact(DisplayName = "[POST] /marketing/favor/media/image-upload")] [Fact(DisplayName = "测试用例:调用 API [POST] /marketing/favor/media/image-upload")]
public async Task UploadMarketingMediaImageTest() public async Task TestExecuteUploadMarketingMediaImage()
{ {
var request = new Models.UploadMarketingMediaImageRequest() var request = new Models.UploadMarketingMediaImageRequest()
{ {

View File

@@ -7,10 +7,10 @@ using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
{ {
public class WechatTenpayExecuteMarketingPartnershipsTests public class TestCase_ApiExecuteExecuteMarketingPartnershipsTests
{ {
[Fact(DisplayName = "[POST] /marketing/partnerships/build")] [Fact(DisplayName = "测试用例:调用 API [POST] /marketing/partnerships/build")]
public async Task BuildMarketingPartnershipTest() public async Task TestExecuteBuildMarketingPartnership()
{ {
var request = new Models.BuildMarketingPartnershipRequest() var request = new Models.BuildMarketingPartnershipRequest()
{ {
@@ -30,8 +30,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.NotNull(response.State); Assert.NotNull(response.State);
} }
[Fact(DisplayName = "[GET] /marketing/partnerships")] [Fact(DisplayName = "测试用例:调用 API [GET] /marketing/partnerships")]
public async Task QueryMarketingPartnershipsTest() public async Task TestExecuteQueryMarketingPartnerships()
{ {
var request = new Models.QueryMarketingPartnershipsRequest() var request = new Models.QueryMarketingPartnershipsRequest()
{ {

View File

@@ -7,10 +7,10 @@ using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
{ {
public class WechatTenpayExecuteMarketingPayGiftActivityTests public class TestCase_ApiExecuteExecuteMarketingPayGiftActivityTests
{ {
[Fact(DisplayName = "[GET] /marketing/paygiftactivity/activities")] [Fact(DisplayName = "测试用例:调用 API [GET] /marketing/paygiftactivity/activities")]
public async Task QueryMarketingPayGiftActivitiesTest() public async Task TestExecuteQueryMarketingPayGiftActivities()
{ {
var request = new Models.QueryMarketingPayGiftActivitiesRequest(); var request = new Models.QueryMarketingPayGiftActivitiesRequest();
var response = await TestClients.Instance.ExecuteQueryMarketingPayGiftActivitiesAsync(request); var response = await TestClients.Instance.ExecuteQueryMarketingPayGiftActivitiesAsync(request);

View File

@@ -7,10 +7,10 @@ using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
{ {
public class WechatTenpayExecuteMerchantMediaTests public class TestCase_ApiExecuteExecuteMerchantMediaTests
{ {
[Fact(DisplayName = "[POST] /merchant/media/upload")] [Fact(DisplayName = "测试用例:调用 API [POST] /merchant/media/upload")]
public async Task UploadMerchantServiceImageTest() public async Task TestExecuteUploadMerchantServiceImage()
{ {
var request = new Models.UploadMerchantMediaImageRequest() var request = new Models.UploadMerchantMediaImageRequest()
{ {
@@ -23,8 +23,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.NotNull(response.MediaId); Assert.NotNull(response.MediaId);
} }
[Fact(DisplayName = "[POST] /merchant/media/video_upload")] [Fact(DisplayName = "测试用例:调用 API [POST] /merchant/media/video_upload")]
public async Task UploadMerchantServiceVideoTest() public async Task TestExecuteUploadMerchantServiceVideo()
{ {
var request = new Models.UploadMerchantMediaVideoRequest() var request = new Models.UploadMerchantMediaVideoRequest()
{ {

View File

@@ -7,10 +7,10 @@ using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
{ {
public class WechatTenpayExecuteMerchantServiceTests public class TestCase_ApiExecuteExecuteMerchantServiceTests
{ {
[Fact(DisplayName = "[GET] /merchant-service/complaints-v2")] [Fact(DisplayName = "测试用例:调用 API [GET] /merchant-service/complaints-v2")]
public async Task QueryMerchantServiceComplaintsTest() public async Task TestExecuteQueryMerchantServiceComplaints()
{ {
var request = new Models.QueryMerchantServiceComplaintsRequest() var request = new Models.QueryMerchantServiceComplaintsRequest()
{ {
@@ -31,8 +31,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
} }
} }
[Fact(DisplayName = "[GET] /merchant-service/complaints-v2/{merchant_id}")] [Fact(DisplayName = "测试用例:调用 API [GET] /merchant-service/complaints-v2/{merchant_id}")]
public async Task GetMerchantServiceComplaintByComplaintIdTest() public async Task TestExecuteGetMerchantServiceComplaintByComplaintId()
{ {
var request = new Models.GetMerchantServiceComplaintByComplaintIdRequest() var request = new Models.GetMerchantServiceComplaintByComplaintIdRequest()
{ {
@@ -47,8 +47,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.True(response.UserComplaintTimes >= 1); Assert.True(response.UserComplaintTimes >= 1);
} }
[Fact(DisplayName = "[GET] /merchant-service/complaints-v2/{merchant_id}/negotiation-historys")] [Fact(DisplayName = "测试用例:调用 API [GET] /merchant-service/complaints-v2/{merchant_id}/negotiation-historys")]
public async Task QueryMerchantServiceComplaintNegotiationHistoriesTest() public async Task TestExecuteQueryMerchantServiceComplaintNegotiationHistories()
{ {
var request = new Models.QueryMerchantServiceComplaintNegotiationHistoriesRequest() var request = new Models.QueryMerchantServiceComplaintNegotiationHistoriesRequest()
{ {
@@ -68,8 +68,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
} }
} }
[Fact(DisplayName = "[POST] /merchant-service/complaint-notifications")] [Fact(DisplayName = "测试用例:调用 API [POST] /merchant-service/complaint-notifications")]
public async Task CreateMerchantServiceComplaintNotificationTest() public async Task TestExecuteCreateMerchantServiceComplaintNotification()
{ {
var request = new Models.CreateMerchantServiceComplaintNotificationRequest() var request = new Models.CreateMerchantServiceComplaintNotificationRequest()
{ {
@@ -82,8 +82,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.NotNull(response.NotifyUrl); Assert.NotNull(response.NotifyUrl);
} }
[Fact(DisplayName = "[GET] /merchant-service/complaint-notifications")] [Fact(DisplayName = "测试用例:调用 API [GET] /merchant-service/complaint-notifications")]
public async Task GetMerchantServiceComplaintNotificationTest() public async Task TestExecuteGetMerchantServiceComplaintNotification()
{ {
var request = new Models.GetMerchantServiceComplaintNotificationRequest(); var request = new Models.GetMerchantServiceComplaintNotificationRequest();
var response = await TestClients.Instance.ExecuteGetMerchantServiceComplaintNotificationAsync(request); var response = await TestClients.Instance.ExecuteGetMerchantServiceComplaintNotificationAsync(request);
@@ -93,8 +93,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.NotNull(response.NotifyUrl); Assert.NotNull(response.NotifyUrl);
} }
[Fact(DisplayName = "[PUT] /merchant-service/complaint-notifications")] [Fact(DisplayName = "测试用例:调用 API [PUT] /merchant-service/complaint-notifications")]
public async Task UpdateMerchantServiceComplaintNotificationTest() public async Task TestExecuteUpdateMerchantServiceComplaintNotification()
{ {
var request = new Models.UpdateMerchantServiceComplaintNotificationRequest() var request = new Models.UpdateMerchantServiceComplaintNotificationRequest()
{ {
@@ -107,8 +107,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.NotNull(response.NotifyUrl); Assert.NotNull(response.NotifyUrl);
} }
[Fact(DisplayName = "[DELETE] /merchant-service/complaint-notifications")] [Fact(DisplayName = "测试用例:调用 API [DELETE] /merchant-service/complaint-notifications")]
public async Task DeleteMerchantServiceComplaintNotificationTest() public async Task TestExecuteDeleteMerchantServiceComplaintNotification()
{ {
var request = new Models.DeleteMerchantServiceComplaintNotificationRequest(); var request = new Models.DeleteMerchantServiceComplaintNotificationRequest();
var response = await TestClients.Instance.ExecuteDeleteMerchantServiceComplaintNotificationAsync(request); var response = await TestClients.Instance.ExecuteDeleteMerchantServiceComplaintNotificationAsync(request);
@@ -116,8 +116,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.True(response.IsSuccessful()); Assert.True(response.IsSuccessful());
} }
[Fact(DisplayName = "[POST] /merchant-service/images/upload")] [Fact(DisplayName = "测试用例:调用 API [POST] /merchant-service/images/upload")]
public async Task UploadMerchantServiceImageTest() public async Task TestExecuteUploadMerchantServiceImage()
{ {
var request = new Models.UploadMerchantServiceImageRequest() var request = new Models.UploadMerchantServiceImageRequest()
{ {

View File

@@ -7,10 +7,10 @@ using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
{ {
public class WechatTenpayExecutePayTransactionsTests public class TestCase_ApiExecuteExecutePayTransactionsTests
{ {
[Fact(DisplayName = "[POST] /pay/transactions/app")] [Fact(DisplayName = "测试用例:调用 API [POST] /pay/transactions/app")]
public async Task CreatePayTransactionAppTest() public async Task TestExecuteCreatePayTransactionApp()
{ {
var request = new Models.CreatePayTransactionAppRequest() var request = new Models.CreatePayTransactionAppRequest()
{ {
@@ -28,8 +28,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.NotNull(response.PrepayId); Assert.NotNull(response.PrepayId);
} }
[Fact(DisplayName = "[POST] /pay/transactions/jsapi")] [Fact(DisplayName = "测试用例:调用 API [POST] /pay/transactions/jsapi")]
public async Task CreatePayTransactionJsapiTest() public async Task TestExecuteCreatePayTransactionJsapi()
{ {
var request = new Models.CreatePayTransactionJsapiRequest() var request = new Models.CreatePayTransactionJsapiRequest()
{ {
@@ -52,8 +52,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.NotNull(response.PrepayId); Assert.NotNull(response.PrepayId);
} }
[Fact(DisplayName = "[POST] /pay/transactions/h5")] [Fact(DisplayName = "测试用例:调用 API [POST] /pay/transactions/h5")]
public async Task CreatePayTransactionH5Test() public async Task TestExecuteCreatePayTransactionH5()
{ {
var request = new Models.CreatePayTransactionH5Request() var request = new Models.CreatePayTransactionH5Request()
{ {
@@ -71,8 +71,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.NotNull(response.H5Url); Assert.NotNull(response.H5Url);
} }
[Fact(DisplayName = "[POST] /pay/transactions/native")] [Fact(DisplayName = "测试用例:调用 API [POST] /pay/transactions/native")]
public async Task CreatePayTransactionNativeTest() public async Task TestExecuteCreatePayTransactionNative()
{ {
var request = new Models.CreatePayTransactionNativeRequest() var request = new Models.CreatePayTransactionNativeRequest()
{ {
@@ -90,8 +90,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.NotNull(response.QrcodeUrl); Assert.NotNull(response.QrcodeUrl);
} }
[Fact(DisplayName = "[GET] /pay/transactions/id/{transaction_id}")] [Fact(DisplayName = "测试用例:调用 API [GET] /pay/transactions/id/{transaction_id}")]
public async Task GetPayTransactionByIdTest() public async Task TestExecuteGetPayTransactionById()
{ {
var request = new Models.GetPayTransactionByIdRequest() var request = new Models.GetPayTransactionByIdRequest()
{ {
@@ -108,8 +108,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.True(response.Amount.Total > 0); Assert.True(response.Amount.Total > 0);
} }
[Fact(DisplayName = "[GET] /pay/transactions/out-trade-no/{out_trade_no}")] [Fact(DisplayName = "测试用例:调用 API [GET] /pay/transactions/out-trade-no/{out_trade_no}")]
public async Task GetPayTransactionByOutTradeNumberTest() public async Task TestExecuteGetPayTransactionByOutTradeNumber()
{ {
var request = new Models.GetPayTransactionByOutTradeNumberRequest() var request = new Models.GetPayTransactionByOutTradeNumberRequest()
{ {
@@ -125,8 +125,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.True(response.Amount.Total > 0); Assert.True(response.Amount.Total > 0);
} }
[Fact(DisplayName = "[POST] /pay/transactions/out-trade-no/{out_trade_no}/close")] [Fact(DisplayName = "测试用例:调用 API [POST] /pay/transactions/out-trade-no/{out_trade_no}/close")]
public async Task ClosePayTransactionTest() public async Task TestExecuteClosePayTransaction()
{ {
var request = new Models.ClosePayTransactionRequest() var request = new Models.ClosePayTransactionRequest()
{ {

View File

@@ -7,10 +7,10 @@ using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
{ {
public class WechatTenpayExecuteProfitSharingTests public class TestCase_ApiExecuteExecuteProfitSharingTests
{ {
[Fact(DisplayName = "[POST] /profitsharing/receivers/add")] [Fact(DisplayName = "测试用例:调用 API [POST] /profitsharing/receivers/add")]
public async Task AddProfitSharingReceiverTest() public async Task TestExecuteAddProfitSharingReceiver()
{ {
await TestClients.InitializeCertificateManagerAsync(); await TestClients.InitializeCertificateManagerAsync();

View File

@@ -7,10 +7,10 @@ using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
{ {
public class WechatTenpayExecuteRefundTests public class TestCase_ApiExecuteExecuteRefundTests
{ {
[Fact(DisplayName = "[POST] /refund/domestic/refunds")] [Fact(DisplayName = "测试用例:调用 API [POST] /refund/domestic/refunds")]
public async Task CreateRefundDomesticRefundTest() public async Task TestExecuteCreateRefundDomesticRefund()
{ {
var request = new Models.CreateRefundDomesticRefundRequest() var request = new Models.CreateRefundDomesticRefundRequest()
{ {
@@ -36,8 +36,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.True(response.Amount.PayerRefund > 0); Assert.True(response.Amount.PayerRefund > 0);
} }
[Fact(DisplayName = "[GET] /refund/domestic/refunds/{out_refund_no}")] [Fact(DisplayName = "测试用例:调用 API [GET] /refund/domestic/refunds/{out_refund_no}")]
public async Task GetRefundDomesticRefundByOutRefundNumberTest() public async Task TestExecuteGetRefundDomesticRefundByOutRefundNumber()
{ {
var request = new Models.GetRefundDomesticRefundByOutRefundNumberRequest() var request = new Models.GetRefundDomesticRefundByOutRefundNumberRequest()
{ {

View File

@@ -3,10 +3,10 @@ using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
{ {
public class WechatTenpayCertificateManagerTests public class TestCase_CertificateManagerTests
{ {
[Fact(DisplayName = "序列化与反序列化 `CertificateEntry`")] [Fact(DisplayName = "测试用例:`CertificateEntry` 序列化")]
public void CertificateEntrySerializationTest() public void TestCertificateEntrySerialization()
{ {
var entry = new Settings.CertificateEntry("SN", "-----BEGIN CERTIFICATE-----END CERTIFICATE-----", DateTimeOffset.Now, DateTimeOffset.Now); var entry = new Settings.CertificateEntry("SN", "-----BEGIN CERTIFICATE-----END CERTIFICATE-----", DateTimeOffset.Now, DateTimeOffset.Now);

View File

@@ -9,14 +9,14 @@ using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
{ {
public class WechatTenpayDeclarationTests public class TestCase_CodeReviewAnalyzer
{ {
private static readonly Assembly _assembly = Assembly.Load("SKIT.FlurlHttpClient.Wechat.TenpayV3"); private Assembly SourceAssembly { get; } = Assembly.Load("SKIT.FlurlHttpClient.Wechat.TenpayV3");
[Fact(DisplayName = "验证 API 模型命名")] [Fact(DisplayName = "代码评审:分析 API 模型命名")]
public void ApiModelsNamingTest() public void ApiModelsNamingTest()
{ {
CodeStyleUtil.VerifyApiModelsNaming(_assembly, out var ex); CodeStyleUtil.VerifyApiModelsNaming(SourceAssembly, out var ex);
if (ex != null) if (ex != null)
throw ex; throw ex;
@@ -24,11 +24,11 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.Null(ex); Assert.Null(ex);
} }
[Fact(DisplayName = "验证 API 模型定义")] [Fact(DisplayName = "代码评审:分析 API 模型定义")]
public void ApiModelsDefinitionTest() public void ApiModelsDefinitionTest()
{ {
string workdir = Path.Combine(TestConfigs.ProjectTestDirectory, "ModelSamples"); string workdir = Path.Combine(TestConfigs.ProjectTestDirectory, "ModelSamples");
CodeStyleUtil.VerifyApiModelsDefinition(_assembly, workdir, out var ex); CodeStyleUtil.VerifyApiModelsDefinition(SourceAssembly, workdir, out var ex);
if (ex != null) if (ex != null)
throw ex; throw ex;
@@ -36,11 +36,11 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.Null(ex); Assert.Null(ex);
} }
[Fact(DisplayName = "验证 API 事件定义")] [Fact(DisplayName = "代码评审:分析 API 事件定义")]
public void ApiEventsDefinitionTest() public void ApiEventsDefinitionTest()
{ {
string workdir = Path.Combine(TestConfigs.ProjectTestDirectory, "EventSamples"); string workdir = Path.Combine(TestConfigs.ProjectTestDirectory, "EventSamples");
CodeStyleUtil.VerifyApiEventsDefinition(_assembly, workdir, out var ex); CodeStyleUtil.VerifyApiEventsDefinition(SourceAssembly, workdir, out var ex);
if (ex != null) if (ex != null)
throw ex; throw ex;
@@ -48,10 +48,10 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.Null(ex); Assert.Null(ex);
} }
[Fact(DisplayName = "验证 API 接口命名")] [Fact(DisplayName = "代码评审:分析 API 接口命名")]
public void ApiExtensionsNamingTest() public void ApiExtensionsNamingTest()
{ {
CodeStyleUtil.VerifyApiExtensionsNaming(_assembly, out var ex); CodeStyleUtil.VerifyApiExtensionsNaming(SourceAssembly, out var ex);
if (ex != null) if (ex != null)
throw ex; throw ex;
@@ -59,7 +59,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.Null(ex); Assert.Null(ex);
} }
[Fact(DisplayName = "验证代码规范")] [Fact(DisplayName = "代码评审:分析代码规范")]
public void CodeStyleTest() public void CodeStyleTest()
{ {
string workdir = Path.Combine(TestConfigs.ProjectSourceDirectory); string workdir = Path.Combine(TestConfigs.ProjectSourceDirectory);

View File

@@ -0,0 +1,23 @@
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 TestCase_HashUtilityTests
{
[Fact(DisplayName = "测试用例SHA-256 信息摘要")]
public void TestSHA256Hash()
{
string rawData = "SHA256HashTest";
string actualHash = Utilities.SHA256Utility.Hash(rawData);
string expectedHash = "8446f1ce5ca8b4a87c0d0cc15be4ba173b2ff78dc33c5f6731d877dcd2d8f401";
Assert.Equal(expectedHash, actualHash, ignoreCase: true);
}
}
}

View File

@@ -7,7 +7,7 @@ using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
{ {
public class WechatTenpayRequestEncryptionTests public class TestCase_RequestEncryptionTests
{ {
private const string RSA_CERTSN = "mock_sn"; 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_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-----";
@@ -28,8 +28,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
}); });
}, isThreadSafe: false); }, isThreadSafe: false);
[Fact(DisplayName = "加密请求中的敏感数据([POST] /profitsharing/receivers/add")] [Fact(DisplayName = "测试用例:加密请求中的敏感数据([POST] /profitsharing/receivers/add")]
public void DecryptResponseSensitiveProperty_AddProfitSharingReceiverRequest() public void TestEncryptResponseSensitiveProperty_AddProfitSharingReceiverRequest()
{ {
var mock = new Models.AddProfitSharingReceiverRequest() var mock = new Models.AddProfitSharingReceiverRequest()
{ {
@@ -40,11 +40,11 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.Equal(RSA_CERTSN, data.WechatpayCertSerialNumber); Assert.Equal(RSA_CERTSN, data.WechatpayCertSerialNumber);
Assert.Equal(MockText, data.Account); Assert.Equal(MockText, data.Account);
Assert.Equal(MockText, Utilities.RSAUtility.DecryptWithECB(RSA_PRIVATE_KEY, data.Name)); Assert.Equal(MockText, Utilities.RSAUtility.DecryptWithECB(RSA_PRIVATE_KEY, data.Name!));
} }
[Fact(DisplayName = "加密请求中的敏感数据([POST] /profitsharing/orders")] [Fact(DisplayName = "测试用例:加密请求中的敏感数据([POST] /profitsharing/orders")]
public void DecryptResponseSensitiveProperty_CreateProfitSharingOrderRequest() public void TestEncryptResponseSensitiveProperty_CreateProfitSharingOrderRequest()
{ {
var mock = new Models.CreateProfitSharingOrderRequest() var mock = new Models.CreateProfitSharingOrderRequest()
{ {
@@ -61,7 +61,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.Equal(RSA_CERTSN, data.WechatpayCertSerialNumber); Assert.Equal(RSA_CERTSN, data.WechatpayCertSerialNumber);
Assert.Equal(MockText, data.ReceiverList[0].Account); Assert.Equal(MockText, data.ReceiverList[0].Account);
Assert.Equal(MockText, Utilities.RSAUtility.DecryptWithECB(RSA_PRIVATE_KEY, data.ReceiverList[0].Name)); Assert.Equal(MockText, Utilities.RSAUtility.DecryptWithECB(RSA_PRIVATE_KEY, data.ReceiverList[0].Name!));
} }
} }
} }

View File

@@ -8,7 +8,7 @@ using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
{ {
public class WechatTenpayResponseDecryptionTests 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_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 RSA_PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAndPeF9o6+sKy9aSAU0myl+YVascgiYSi6mn99SkLMNi3c31xDi+OSomK+iLIcGWkjxaJO0qvtcC6zuvw2e/xkps1cHRSFf84w2yN42kh7evWQCRgUttdgMwuHMB76Rqx5t5Ks1YnyclDcbKE71pJURkhOdKT1ml6MZnT4A+XWvCDwxzc5DzNEGEzpR5iEbA0GaVomUT2hXazd4v6hvbaAkQj1abQlTWK1iwxBV4d4qDqjnU5NXx8RXM2jX+GL0IbKl5Rv5Roqhm7j7hWHxf0b0vSn6bQDNcsnJJ07JZEnojqQNtrBWw3W/puwx7/p3PA0Dz5g+0sQ8FSA03CEu6RCQIDAQAB-----END PUBLIC KEY-----";
@@ -21,8 +21,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
}); });
}, isThreadSafe: false); }, isThreadSafe: false);
[Fact(DisplayName = "解密响应中的敏感数据([GET] /certificates")] [Fact(DisplayName = "测试用例:解密响应中的敏感数据([GET] /certificates")]
public async Task DecryptResponseSensitiveProperty_QueryCertificatesResponse() public async Task TestDecryptResponseSensitiveProperty_QueryCertificatesResponse()
{ {
var client1 = new WechatTenpayClient(new WechatTenpayClientOptions() var client1 = new WechatTenpayClient(new WechatTenpayClientOptions()
{ {
@@ -51,8 +51,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.DoesNotContain(response2.CertificateList, (e => e.EncryptCertificate.CipherText.StartsWith("-----BEGIN CERTIFICATE-----"))); Assert.DoesNotContain(response2.CertificateList, (e => e.EncryptCertificate.CipherText.StartsWith("-----BEGIN CERTIFICATE-----")));
} }
[Fact(DisplayName = "解密响应中的敏感数据([GET] /ecommerce/applyments/out-request-no/{out_request_no}")] [Fact(DisplayName = "测试用例:解密响应中的敏感数据([GET] /ecommerce/applyments/out-request-no/{out_request_no}")]
public void DecryptResponseSensitiveProperty_GetEcommerceApplymentByOutRequestNumberResponseTest() public void TestDecryptResponseSensitiveProperty_GetEcommerceApplymentByOutRequestNumberResponseTest()
{ {
var mock = new Models.GetEcommerceApplymentByOutRequestNumberResponse() var mock = new Models.GetEcommerceApplymentByOutRequestNumberResponse()
{ {
@@ -70,14 +70,14 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
var data = MockClientInstance.Value.DecryptResponseSensitiveProperty(mock); var data = MockClientInstance.Value.DecryptResponseSensitiveProperty(mock);
Assert.Equal(MockText, data.ApplymentState); Assert.Equal(MockText, data.ApplymentState);
Assert.Equal(MockText, data.AccountValidation.AccountNumber); Assert.Equal(MockText, data.AccountValidation!.AccountNumber);
Assert.Equal(MockText, data.AccountValidation.DestinationAccountName); Assert.Equal(MockText, data.AccountValidation!.DestinationAccountName);
Assert.Equal(MockText, data.AccountValidation.DestinationAccountNumber); Assert.Equal(MockText, data.AccountValidation!.DestinationAccountNumber);
Assert.Equal(MockText, data.AccountValidation.AccountName); Assert.Equal(MockText, data.AccountValidation!.AccountName);
} }
[Fact(DisplayName = "解密响应中的敏感数据([GET] /ecommerce/bill/fundflowbill")] [Fact(DisplayName = "测试用例:解密响应中的敏感数据([GET] /ecommerce/bill/fundflowbill")]
public void DecryptResponseSensitiveProperty_GetEcommerceBillFundflowBillResponse() public void TestDecryptResponseSensitiveProperty_GetEcommerceBillFundflowBillResponse()
{ {
var mock = new Models.GetEcommerceBillFundflowBillResponse() var mock = new Models.GetEcommerceBillFundflowBillResponse()
{ {
@@ -106,8 +106,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.Equal(MockText, data.DownloadBillList[1].EncryptKey); Assert.Equal(MockText, data.DownloadBillList[1].EncryptKey);
} }
[Fact(DisplayName = "解密响应中的敏感数据([GET] /merchant-service/complaints-v2/{complaint_id}")] [Fact(DisplayName = "测试用例:解密响应中的敏感数据([GET] /merchant-service/complaints-v2/{complaint_id}")]
public void DecryptResponseSensitiveProperty_GetMerchantServiceComplaintByComplaintIdResponse() public void TestDecryptResponseSensitiveProperty_GetMerchantServiceComplaintByComplaintIdResponse()
{ {
var mock = new Models.GetMerchantServiceComplaintByComplaintIdResponse() var mock = new Models.GetMerchantServiceComplaintByComplaintIdResponse()
{ {
@@ -129,8 +129,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.Equal(MockText, data.ComplaintOrderList[0].TransactionId); Assert.Equal(MockText, data.ComplaintOrderList[0].TransactionId);
} }
[Fact(DisplayName = "解密响应中的敏感数据([GET] /merchant-service/complaints-v2")] [Fact(DisplayName = "测试用例:解密响应中的敏感数据([GET] /merchant-service/complaints-v2")]
public void DecryptResponseSensitiveProperty_QueryMerchantServiceComplaintsResponse() public void TestDecryptResponseSensitiveProperty_QueryMerchantServiceComplaintsResponse()
{ {
var mock = new Models.QueryMerchantServiceComplaintsResponse() var mock = new Models.QueryMerchantServiceComplaintsResponse()
{ {
@@ -150,8 +150,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.Equal(MockText, data.ComplaintList[0].PayerOpenId); Assert.Equal(MockText, data.ComplaintList[0].PayerOpenId);
} }
[Fact(DisplayName = "解密响应中的敏感数据([GET] /smartguide/guides")] [Fact(DisplayName = "测试用例:解密响应中的敏感数据([GET] /smartguide/guides")]
public void DecryptResponseSensitiveProperty_QuerySmartGuidesResponse() public void TestDecryptResponseSensitiveProperty_QuerySmartGuidesResponse()
{ {
var mock = new Models.QuerySmartGuidesResponse() var mock = new Models.QuerySmartGuidesResponse()
{ {
@@ -173,8 +173,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.Equal(MockText, data.GuideList[0].UserMobile); 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}")] [Fact(DisplayName = "测试用例:解密响应中的敏感数据([GET] /transfer/batches/out-batch-no/{out_batch_no}/details/out-detail-no/{out_detail_no}")]
public void DecryptResponseSensitiveProperty_GetTransferBatchDetailByOutDetailNumberResponse() public void TestDecryptResponseSensitiveProperty_GetTransferBatchDetailByOutDetailNumberResponse()
{ {
var mock = new Models.GetTransferBatchDetailByOutDetailNumberResponse() var mock = new Models.GetTransferBatchDetailByOutDetailNumberResponse()
{ {
@@ -188,7 +188,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.Equal(MockText, data.OpenId); Assert.Equal(MockText, data.OpenId);
} }
[Fact(DisplayName = "解密响应中的敏感数据([GET] /transfer/batches/batch-id/{batch_id}/details/detail-id/{detail_id}")] [Fact(DisplayName = "测试用例:解密响应中的敏感数据([GET] /transfer/batches/batch-id/{batch_id}/details/detail-id/{detail_id}")]
public void DecryptResponseSensitiveProperty_GetTransferBatchDetailByDetailIdResponse() public void DecryptResponseSensitiveProperty_GetTransferBatchDetailByDetailIdResponse()
{ {
var mock = new Models.GetTransferBatchDetailByDetailIdResponse() var mock = new Models.GetTransferBatchDetailByDetailIdResponse()
@@ -203,8 +203,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.Equal(MockText, data.OpenId); Assert.Equal(MockText, data.OpenId);
} }
[Fact(DisplayName = "解密响应中的敏感数据([GET] /partner-transfer/batches/batch-id/{batch_id}/details/detail-id/{detail_id}")] [Fact(DisplayName = "测试用例:解密响应中的敏感数据([GET] /partner-transfer/batches/batch-id/{batch_id}/details/detail-id/{detail_id}")]
public void DecryptResponseSensitiveProperty_GetPartnerTransferBatchDetailByDetailIdResponse() public void TestDecryptResponseSensitiveProperty_GetPartnerTransferBatchDetailByDetailIdResponse()
{ {
var mock = new Models.GetPartnerTransferBatchDetailByDetailIdResponse() var mock = new Models.GetPartnerTransferBatchDetailByDetailIdResponse()
{ {

View File

@@ -7,10 +7,10 @@ using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
{ {
public class WechatTenpayResponseVerificationTests public class TestCase_ResponseVerificationTests
{ {
[Fact(DisplayName = "验证响应签名")] [Fact(DisplayName = "测试用例:验证响应签名")]
public async Task VerifyResponseSignatureTest() public async Task TestVerifyResponseSignature()
{ {
await TestClients.InitializeCertificateManagerAsync(); await TestClients.InitializeCertificateManagerAsync();

View File

@@ -7,7 +7,7 @@ using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
{ {
public class WechatTenpaySecurityTests public class TestCase_RsaUtilityTests
{ {
// 此处测试的 RSA 证书/公钥/私钥是自签名生成的,仅供执行 RSA 相关的单元测试,不能用于调用微信支付 API。 // 此处测试的 RSA 证书/公钥/私钥是自签名生成的,仅供执行 RSA 相关的单元测试,不能用于调用微信支付 API。
private const string RSA_CERT_SN = "3050f72e2dce03e7efe49557dd231d176649afbd"; private const string RSA_CERT_SN = "3050f72e2dce03e7efe49557dd231d176649afbd";
@@ -17,22 +17,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
private const string RSA_PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA52DszUZzPKPo1d9Hi5Hj\nlu7OINwADaeXifA4rvmJJaA+jm4DCMwrAMzyS12EiW31xCAF8LZ/xkrFHO5CZgvK\n87Y+kY9DmhvNX6FVYsn4ay7KER0zo87zqQjC+njUu1rYuKnio7MYb354PitwQ3SW\nNv2qTCbCNCXTN9pJXNhlCudWCEWrNrYc4/hKz3bqu1DjpY0oHuuKPk/iRr2TTUIA\nwahNkNQheQNB2a8hL7L2OG1Sn1vaDWe+5RJYlMRZ3NgYDTqoy8GMs+6q091MQMDl\nQ90jtW/JEoM5DUyI8zfQfDLGnU7FuY0rrZ/+6OQT/o7ISf0OR5TISS0lqnDN3vVa\nph0ftDGRdGqJk2SJAHIoxp5gt410rfWS9kpSDFJs3Pvt4rtNZBYvkGD8obSm91br\nAkoX4+u1Y4p1qZpWJ4LIKw8oyeieqlLZtF/VGKOtKxe/IKn8GwoQJLx4dUGFOqM7\nHPwR9cyjMaC1o3V1NQG+1wD9TLtGh3WXUFJRYDmePaSp39GFPupTMlPRbD0RK80B\n6xv2rYTyYyd8s2LN6P6Hh/nFIkc1rekIf9JhPy0WKzrXdmnfjSHKPxmz0WSYN8Fx\nKasqcJhncOdhLTzzVEhj9xHSI8ejP2fJ4v+ARoD3GURPD9H7KMa7xmzRSAZ8A8LM\n3uvdJNhbKBwWqvo45ncz+7cCAwEAAQ==\n-----END PUBLIC KEY-----"; private const string RSA_PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA52DszUZzPKPo1d9Hi5Hj\nlu7OINwADaeXifA4rvmJJaA+jm4DCMwrAMzyS12EiW31xCAF8LZ/xkrFHO5CZgvK\n87Y+kY9DmhvNX6FVYsn4ay7KER0zo87zqQjC+njUu1rYuKnio7MYb354PitwQ3SW\nNv2qTCbCNCXTN9pJXNhlCudWCEWrNrYc4/hKz3bqu1DjpY0oHuuKPk/iRr2TTUIA\nwahNkNQheQNB2a8hL7L2OG1Sn1vaDWe+5RJYlMRZ3NgYDTqoy8GMs+6q091MQMDl\nQ90jtW/JEoM5DUyI8zfQfDLGnU7FuY0rrZ/+6OQT/o7ISf0OR5TISS0lqnDN3vVa\nph0ftDGRdGqJk2SJAHIoxp5gt410rfWS9kpSDFJs3Pvt4rtNZBYvkGD8obSm91br\nAkoX4+u1Y4p1qZpWJ4LIKw8oyeieqlLZtF/VGKOtKxe/IKn8GwoQJLx4dUGFOqM7\nHPwR9cyjMaC1o3V1NQG+1wD9TLtGh3WXUFJRYDmePaSp39GFPupTMlPRbD0RK80B\n6xv2rYTyYyd8s2LN6P6Hh/nFIkc1rekIf9JhPy0WKzrXdmnfjSHKPxmz0WSYN8Fx\nKasqcJhncOdhLTzzVEhj9xHSI8ejP2fJ4v+ARoD3GURPD9H7KMa7xmzRSAZ8A8LM\n3uvdJNhbKBwWqvo45ncz+7cCAwEAAQ==\n-----END PUBLIC KEY-----";
private const string RSA_PRIVATE_KEY = "-----BEGIN PRIVATE KEY-----\n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\nhpUq0eKgdGHc2R4r57soRvGoGy2DtA==\n-----END PRIVATE KEY-----"; private const string RSA_PRIVATE_KEY = "-----BEGIN PRIVATE KEY-----\nMIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQDnYOzNRnM8o+jV\n30eLkeOW7s4g3AANp5eJ8Diu+YkloD6ObgMIzCsAzPJLXYSJbfXEIAXwtn/GSsUc\n7kJmC8rztj6Rj0OaG81foVViyfhrLsoRHTOjzvOpCML6eNS7Wti4qeKjsxhvfng+\nK3BDdJY2/apMJsI0JdM32klc2GUK51YIRas2thzj+ErPduq7UOOljSge64o+T+JG\nvZNNQgDBqE2Q1CF5A0HZryEvsvY4bVKfW9oNZ77lEliUxFnc2BgNOqjLwYyz7qrT\n3UxAwOVD3SO1b8kSgzkNTIjzN9B8MsadTsW5jSutn/7o5BP+jshJ/Q5HlMhJLSWq\ncM3e9VqmHR+0MZF0aomTZIkAcijGnmC3jXSt9ZL2SlIMUmzc++3iu01kFi+QYPyh\ntKb3VusCShfj67VjinWpmlYngsgrDyjJ6J6qUtm0X9UYo60rF78gqfwbChAkvHh1\nQYU6ozsc/BH1zKMxoLWjdXU1Ab7XAP1Mu0aHdZdQUlFgOZ49pKnf0YU+6lMyU9Fs\nPRErzQHrG/athPJjJ3yzYs3o/oeH+cUiRzWt6Qh/0mE/LRYrOtd2ad+NIco/GbPR\nZJg3wXEpqypwmGdw52EtPPNUSGP3EdIjx6M/Z8ni/4BGgPcZRE8P0fsoxrvGbNFI\nBnwDwsze690k2FsoHBaq+jjmdzP7twIDAQABAoICAQDTJ+hT2eRWxfs6G39uhyBd\nYOhqonvF+llYgAsq2/3mgZw1XX6Va8Ye/+prDxhiVyB/8P2a1OI884V5xpKAEGkS\nCxKEwmreXFsL1+9VrZ5xKo0sGytCZh6F98IA1X7G0LyRojB8VniJX7CahAf6944S\n92KQBpsa/h4JjcN/4NgtoDsqZ3I+BurMvY6AUTUc51ApiG3B8hECluKYzm98hSyt\nj0viTUWS638QCzxNDJSZoGNTnX6c1z4mTZzbf2nHGsqwYAUlligzGS97FC1/tspE\nKa9p6G9m3qyVT3B4DkrM3YXWj8nwcT4YQLhgj60TlfiBVVjPyJ8T8Qi7yCCJRf6H\nd8/YT9Nh/uaHh9DUmgiN6SL2v7kRnfJ9+5nXfyxjC/jiJjMwoFvSzkWYNdz0AOiw\nqVFVAzIBvNS4he6blXlpxvi8vtx4Bkg86uwUlauKtUbtRxy7PaUYJ966dgvYH6oB\nEqRPXqSc0d4GaY+RS6LzcXmwLYmsXwZV+GwY9Q8Y445vuP20Ae/dc2l9R19Dp90U\nYWKU49QgXIrGqZ0vL4StWuy10Y3tpBdW12qBpVGwUIxMhY2dAR5nWrXnqbqXZ3KK\novWPPKj0+SUN/RKglzNjezkvJqcfTHWn32+wqjTzAivYIYZhFtYRje95OzGnjp3q\nVQm/hXZGWaJdNCmu94oFcQKCAQEA/iRxbMxY3ZC2E3VD9PzTatRWxJ0ZgR2ZvXQZ\nDZe+Ut1bzuKerPQIkGNDAqRjicYSS6QbtopNbVjyNpz7lJduXXohpTSDrWlIjfto\n/dQ8AFHOEeM2ynp/s+Q8/fzXAbgmBmgFpGOf/bYzDWuweQ9G29msJ7G8py+Lo5RH\nb6ZmhvkGVez4m3mR7B3fbRMO/K/4fyRRJm40Nc3aAk+UbnhL/Nl8nMRC+bkjJv0N\nG4Pf6Fhf99sqJR7EbS2B5p9C+m6Du9zVC/zmIhOSg7Cg6/VGLdSX/el7QgL9r8Ld\n71a1Bn4hTeWnRgkyyC2c/oiCx2GcLFMNXZECIqUNhpZDsaNz/wKCAQEA6RHiywU+\niVyRW28RP3UvoKhm0RqWH8kFJ6SjATi0QDTNUAOEtTOXAmyc9FuxkBQjoIi8qVby\nYwZF9YFXb1o823J4EafEKX1D9gGHeV22FlzhMSBOzf0KTi1R9IAJoIScBIyNyamZ\nKwAfa7bLCbxNBiQG3JYmQqI3OE6VFFM7uuIWvZHF26Rt8HLKYXtRzZ/phO3mJ4Ke\nyQYfl+yF5PWueGpLJAjNYI3E2TxxudQMtYkWDV6o8OJrQ66bnUcHMxi1XPNYDlBM\nAQsGHIN7+qYx5EY7fHK1kzChYOoORsqjGwj9SSEdnNTM3uB6PLXnJsoG0NTaaoVo\nW5rfnCPjI0gYSQKCAQBlMj24BOad0zGtLdSRiNrmfwbN44B0WUUOm1wefX3boSkd\niD+GvuVqGRxlwO+hvK0sUXx3gzqxf+lyta+3y1S3BBrBndeRBYtOff2glRIPToOv\nu7nlhkGzb/6ZZER4+sqpYmJcww7CB/rsLSVoDx04DcTvSWbFa7k+uZx4aNoKhL5x\nGJslzZK9YmfFFwGwvKFGfz+Q/fDsO7vDj8ya8GvRkwh7o+rHZWEJ9Vlyy2AtNIOC\nPlLZ1RaCIszG+EPDVJ4///8Vdu5sQz7kEUECs/ft5+ldwcrCzk4V3pJg6zXKEA9S\n5U9mI+OEsiUBdXodylBVlfyMdWFUSkTIgq0R3vQhAoIBABtLb+7st00o3REDKdbv\np1s+PYRBg9FHHmZtHnXXKSzXwi+bqd/6obWz+JGZZ2sDIMT9HnMKbqpwIqNEuXOd\n8sCUYEFZD1z4gYv+09m/wsJNsEWrje8LsjhDkHR8xiPZQ9g4iaZTSU/C3OslZhPG\nzJJqh68vml11V9gtQ8I0mSsirR0YRD6bvBBLsS3HXmYhUxyxK6H25xeNswd8uJV+\nvCb388LNkRe8oo/6RytHDRH5cu6v5kMHkR5FBY5eshYmz56KFQbgGnaIzvdp4owR\nCIi+PNsvJ9qL+Go8Ht3lf0J8RAVbbndeaHu1eDtB5kcho7izJL0S0Izhz0we28vW\n9pkCggEAbxVbSvo1zwI6rJ5V5hNA3mLfyQfZbdGa3DvsJNpYkkKfcDDCY0A5c87v\naIXJs+Mv2Ec/jNlQnIgrAavrM4Q8QxsBCfQREfb2GK9xZPINAZ9BZAyMcqO5FIUG\n2b5SKxXWVaFpt52CsKXQIIJUy3VI9lyvKNQc9xKIXarYiMyC9X4/tVmqZqIJwPZZ\nZqWeptNm5dyIGHbKsxIXdYBgD8TKb22nFaKbRX7dB11zGfs3o5rOftWWew7/ha3Q\nePN9vy8x0PXfKzBbWNgOwu/uv4uQF0mrhHb+sn6N2XSj3v20nJz562ropN3tI8oe\nhpUq0eKgdGHc2R4r57soRvGoGy2DtA==\n-----END PRIVATE KEY-----";
[Fact(DisplayName = "证书和回调报文解密AES-GCM")] [Fact(DisplayName = "测试用例:从 RSA 证书中导出公钥")]
public void AESGCMDecryptTest() public void TestExportRSAPublicKeyFromCertificate()
{
string key = "f09b03a7a1902b5b4913856f1fd07ab1";
string iv = "aae8c2e79c5b";
string aad = "certificate";
string cipherText = "x9kkL5w1JuaypcjhrYIP+kVNlN8o8uN4yJyJjy5lg+PyPnQL2Zn//ORaXAyzdaK/WBMVd3u/Y9hLaTBLMyRXzowsrkJ5PT37johye48N7BAJQ0PJwW++d1RdhOOPjoqfmws6rSV5Gv2qhfdKjmpxVjr8xr71dtBt8J2wu+bAV99HHQoAynm/Pp9OQYZgpOQ+1cyFHd43TAxOoFfmixKrXr3HP8lJot0XCUSq4qkr1Hs44FV2KuzntSk8eqKr5N17UcuPF3VYnnnF/AvQ7HuLKWwrHhUbaXfkwy0Q2n36UJMfBj7344S97E8BnS89ojgOPQi+olBPyNgrtDWHgsJAKu7HA6PV/FgmXcrZirje/AH1u25es4z5xItHscm//6rDvALgf7greV5OJzMsSl/KVDtbkjDSzim0j4ZTduIfzh7l6jfOz115ITcNILT9ef2KkcMyBBc89GZlMGeHTbgsBHzGeLawX3dXFjqt5aMnHM3VWCovA2aUM4c//rqkZGf+Va86OEFoJQLiSTFpkOrKxcIxcrbKPLTgiDWRT3wzmnUDg7kSPbluzt3ROvMFq9lB8bO/pBd7TD2w87sfUdKLj69FniX6s37SBeRVhw8GSIvBf5lpLUhqL5zKYlbuAWePuz0wVV4NTtkaVKZlmm8KTODyZDFpsyKPubDDcwT1ftRf5aSVM4x04I/1B7GkNz/TOy+zpJ0h0B7VHdxyO5JYiI/1qsatX/FE2aJdQYMYOtqfDH7ZH5UUKIqo538OKvE2M4MlBR/aVE4z4QDKfE/1kYrOfvVGfDzF/FWHfUrcqB8kdQMvk8vCoM8yYZsX4KE1aoJbNM2pWv2tpr9JE8b/VQgUyHOgPYAha+UOmZki4Sfl9H62687EIWdbM57ZxmwIiBp60SrJLiBfZon9JqXKdtJOKj0CRokQiBnONNXCVerLFeBNQfeKRw8tgJXf+QPohMGYkSDdc8hTgdbmhTwB1Vv01stlYK12QMNRCovlp/fcmpB72Phlq+/3p5pqMzknw+qm5QAz7JnpZJCFHit52gHwAkKRkVPB3HF2rfLrdTYz5c9Bok1ICAY9My47eLFdduIe99V52cjMLQuUmNFBPrDdyZKVqIHJ/wtWO/wIFpAVGSJMHctyEKmeJVc1IQN74Wm00PrpPackHdO3G41bBmkp5pqUdsSgSkwdfNVqv0cMcSe04NrRGNKMcZ7TA/CMaP1YnhxvVE+z8aksJqSJ+gdplvuwl40y5C8UEHeAi1V8Q0Bf4YvYRgOVIWm2Lzjdn2z9PWLGcStUj11/1hthk2li4V3mgm2Cr2IZme2sn4rZmJ6dexGP1nk+ZYOq0xLE8F7oex9gyDN+A/6zHqnuhO/X08qye0gochMr8U89Qvj2c0L3P2mjCea2H1mEriAJPqMPMKIinh1lQJEZufnfCcPxbZLKTtl6zHtHgOztejd1gV/nUyCVKD4MCMfBDy9C/Af8pWx6akOg/QSQNIGA2AI6zprHn9zEjpFIzXJYvruVI22Yt6oF9Xnt7Ki82wRK2M96r4kj6cwSs4exMPGv8fWMrFTm0Br6p6T+HZsxyyn2ChuPIgpfisnce/ZaU/0xCZhK/K79+TK2GeeChq5oEpua/1tx4+kDHi7H9381pLJmy2oXW060c2mmwA9+EpcuwEDhr8fsnghbv41u7b1NhEmWNVUy29Dwaz61PPGUdh5DsvaKLWC+raZ/6UEKPw+tiABJ5o6u2jAWgmEYmmJCKapNgtfPc6D+O0aHH9oqh6u4+8NRAhusPZzDGWBr6AT4pexgWFeEhZhn6bXM9HhpUe0IhOTw5D+tqXrTlNon4kjYibiMUFy1h2YyYS3IEdu1J4xqvo0rFyCxF1C+P6ubc0tClRPkXg==";
string actualPlain = Utilities.AESUtility.DecryptWithGCM(key: key, iv: iv, aad: aad, cipherText: cipherText);
string expectedPlain = "-----BEGIN CERTIFICATE-----\nMIID3DCCAsSgAwIBAgIUGZNrTcamx3sFSJsQli3v9C6gZe8wDQYJKoZIhvcNAQEL\nBQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT\nFFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg\nQ0EwHhcNMjAwODAxMDczNTE4WhcNMjUwNzMxMDczNTE4WjBuMRgwFgYDVQQDDA9U\nZW5wYXkuY29tIHNpZ24xEzARBgNVBAoMClRlbnBheS5jb20xHTAbBgNVBAsMFFRl\nbnBheS5jb20gQ0EgQ2VudGVyMQswCQYDVQQGDAJDTjERMA8GA1UEBwwIU2hlblpo\nZW4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDOAYHqxCqaRzoTIvgV\nixaYJJvmvHbiczbx5MQ9XL1ITSFxkTsNsk7RKHnO7eBS5imheJgQwd22Ky+XclSe\n7B4odssu/l/+gHo2gooTYrrCpQrOkpvGMf8R8aI56BQIF+vsomDvVq1NojHV2Fql\njMwFXzhj2EmU6p6gDv9iL7q1NrfnxFx8iJe4OhIB5Ek4qn1xXxrTUhiULd2vXlbI\nXhRetZSNcJsLt5Rw7D7c8F+aX2JchfeqsZECwKW7bSjMbVWWC6M9MgkB/aId8P0y\n7qEiiXFJkfkg1I/E1ud2apopsid5tdCyRRR6+MhhX2EC8S04MN4soUT7haqNNxX2\nrKHnAgMBAAGjgYEwfzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIE8DBlBgNVHR8EXjBc\nMFqgWKBWhlRodHRwOi8vZXZjYS5pdHJ1cy5jb20uY24vcHVibGljL2l0cnVzY3Js\nP0NBPTFCRDQyMjBFNTBEQkMwNEIwNkFEMzk3NTQ5ODQ2QzAxQzNFOEVCRDIwDQYJ\nKoZIhvcNAQELBQADggEBAJyg2z4oLQmPfftLQWyzbUc9ONhRMtfA+tVlVBgtLLKn\nWuDlsmEntheM07fu84F4pcfs3yHzjD7pAOFbO4Yt1yhQ50DK35sjbRWepPdWJZLl\nni7KBctcmm0o4zq37oB7vonmBEbFqYs9DaINYOjgI3J25iSBkPVC7dBbvFj2xB0L\ncIcXipq30tDdC/oUem27MNzwZAt49WthKhw6u3HSkcE5cO4LyYTsJhSyG/7LXwvV\nMgX4Jyzo0SSiGOU1/beaZssTVI8sTPJVlHWjhNE3Lc2SaAlKGfGwvt0X3cEZEF+7\noEZIFTkkAF2JhqfnpR3gST0G8Umq1SaVtCPP/zVI8x0=\n-----END CERTIFICATE-----";
Assert.Equal(expectedPlain, actualPlain);
}
[Fact(DisplayName = "从 RSA 证书中导出公钥")]
public void ExportRSAPublicKeyFromCertificateTest()
{ {
string actualPublicKey = Utilities.RSAUtility.ExportPublicKey(RSA_CERTIFICATE).Replace("\r", "").Replace("\n", ""); string actualPublicKey = Utilities.RSAUtility.ExportPublicKey(RSA_CERTIFICATE).Replace("\r", "").Replace("\n", "");
string expectedPublicKey = RSA_PUBLIC_KEY.Replace("\r", "").Replace("\n", ""); string expectedPublicKey = RSA_PUBLIC_KEY.Replace("\r", "").Replace("\n", "");
@@ -40,8 +26,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.Equal(expectedPublicKey, actualPublicKey, ignoreLineEndingDifferences: true); Assert.Equal(expectedPublicKey, actualPublicKey, ignoreLineEndingDifferences: true);
} }
[Fact(DisplayName = "从 RSA 证书中导出证书序列号")] [Fact(DisplayName = "测试用例:从 RSA 证书中导出证书序列号")]
public void ExportRSASerialNumberFromCertificateTest() public void TestExportRSASerialNumberFromCertificate()
{ {
string actualSerialNumber = Utilities.RSAUtility.ExportSerialNumber(RSA_CERTIFICATE); string actualSerialNumber = Utilities.RSAUtility.ExportSerialNumber(RSA_CERTIFICATE);
string expectedSerialNumber = RSA_CERT_SN; string expectedSerialNumber = RSA_CERT_SN;
@@ -49,8 +35,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.Equal(expectedSerialNumber, actualSerialNumber); Assert.Equal(expectedSerialNumber, actualSerialNumber);
} }
[Fact(DisplayName = "从 RSA 证书中导出证书颁发时间")] [Fact(DisplayName = "测试用例:从 RSA 证书中导出证书颁发时间")]
public void ExportRSAEffectiveTimeFromCertificateTest() public void TestExportRSAEffectiveTimeFromCertificate()
{ {
DateTimeOffset actualEffectiveTime = Utilities.RSAUtility.ExportEffectiveTime(RSA_CERTIFICATE); DateTimeOffset actualEffectiveTime = Utilities.RSAUtility.ExportEffectiveTime(RSA_CERTIFICATE);
DateTimeOffset expectedEffectiveTime = DateTimeOffset.Parse(RSA_CERT_START_DATE); DateTimeOffset expectedEffectiveTime = DateTimeOffset.Parse(RSA_CERT_START_DATE);
@@ -58,8 +44,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.Equal(expectedEffectiveTime, actualEffectiveTime); Assert.Equal(expectedEffectiveTime, actualEffectiveTime);
} }
[Fact(DisplayName = "从 RSA 证书中导出证书过期时间")] [Fact(DisplayName = "测试用例:从 RSA 证书中导出证书过期时间")]
public void ExportRSAExpireTimeFromCertificateTest() public void TestExportRSAExpireTimeFromCertificate()
{ {
DateTimeOffset actualExpireTime = Utilities.RSAUtility.ExportExpireTime(RSA_CERTIFICATE); DateTimeOffset actualExpireTime = Utilities.RSAUtility.ExportExpireTime(RSA_CERTIFICATE);
DateTimeOffset expectedExpireTime = DateTimeOffset.Parse(RSA_CERT_END_DATE); DateTimeOffset expectedExpireTime = DateTimeOffset.Parse(RSA_CERT_END_DATE);
@@ -67,8 +53,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.Equal(expectedExpireTime, actualExpireTime); Assert.Equal(expectedExpireTime, actualExpireTime);
} }
[Fact(DisplayName = "签名生成(SHA256WithRSA")] [Fact(DisplayName = "测试用例:SHA256WithRSA 签名生成")]
public void SHA256WithRSASignTest() public void TestRSASignatureSHA256WithRSASign()
{ {
string plainText = "SHA256WithRSASignTest"; string plainText = "SHA256WithRSASignTest";
string actualSign = Utilities.RSAUtility.SignWithSHA256(RSA_PRIVATE_KEY, plainText); string actualSign = Utilities.RSAUtility.SignWithSHA256(RSA_PRIVATE_KEY, plainText);
@@ -77,8 +63,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.Equal(expectedSign, actualSign); Assert.Equal(expectedSign, actualSign);
} }
[Fact(DisplayName = "签名验证(SHA256WithRSA")] [Fact(DisplayName = "测试用例:SHA256WithRSA 签名验证")]
public void SHA256WithRSAVerifyTest() public void TestRSASignatureSHA256WithRSAVerify()
{ {
string plainText = "SHA256WithRSAVerifyTest"; string plainText = "SHA256WithRSAVerifyTest";
string signText = "aHX+MrmZHDEraMKBEPV2Vnps1B9b25lGbv/rdppx/S7+oaXtjKJprzCq5H7RCpvrKS3xYIeTEPwQGC3Vots7dCdLi8v8ew1vvtXf8qNAnd7CTMHqu3wSohXzgyASTmNbXE2ml9LbWYPPYMvPJXROQbGVjoOrsErWBPPJYXuO3lIckIfwI05OTdl4H3+BvpD/ZoljRp8Qgo9+paGvarBc++TaAh0FXnQf0TGNFUIeHHiAKBee5oCBTuZZM9J5RPw0oIq/g7Wun+e/zWiwVBPHltOgZrV46uagSAE6nBDHk+hlNxDivCxkJdBVCSIYFFmBXIcnGZ/u4ZfBui/k1jGoKibyvPK4z2+6GSlj41Yo81kuSBfzLiSsx33EPR1eIJJkwDTsvap0ymL9pfIqMiLuiteH5kGmL/dyONy9oAJywLEeITfoVyElM/CY6Dc+xDhRnjN7Hu54meYyXRZrnCtQ3YhzEr1immNBn6npgA/qi9aHsuWFOw8b8aSwOHDHTDmjmvV+axI8CVMrR0MjB9QNCWrKLq2B9iQX9MtLgcUyDsQvzAsxUJm/OEfzUjs9SHvmgmyAvzNAuTdO7wLQ+ZmKg0yZne6nvcrJVvfh3lD5ZPt7NY57Y6OIJluqKUT5H+a3H6W9Q1Z+cBMnHGYaaK7Tv8IcDdEYqTIG8hc5BqjFOzE="; string signText = "aHX+MrmZHDEraMKBEPV2Vnps1B9b25lGbv/rdppx/S7+oaXtjKJprzCq5H7RCpvrKS3xYIeTEPwQGC3Vots7dCdLi8v8ew1vvtXf8qNAnd7CTMHqu3wSohXzgyASTmNbXE2ml9LbWYPPYMvPJXROQbGVjoOrsErWBPPJYXuO3lIckIfwI05OTdl4H3+BvpD/ZoljRp8Qgo9+paGvarBc++TaAh0FXnQf0TGNFUIeHHiAKBee5oCBTuZZM9J5RPw0oIq/g7Wun+e/zWiwVBPHltOgZrV46uagSAE6nBDHk+hlNxDivCxkJdBVCSIYFFmBXIcnGZ/u4ZfBui/k1jGoKibyvPK4z2+6GSlj41Yo81kuSBfzLiSsx33EPR1eIJJkwDTsvap0ymL9pfIqMiLuiteH5kGmL/dyONy9oAJywLEeITfoVyElM/CY6Dc+xDhRnjN7Hu54meYyXRZrnCtQ3YhzEr1immNBn6npgA/qi9aHsuWFOw8b8aSwOHDHTDmjmvV+axI8CVMrR0MjB9QNCWrKLq2B9iQX9MtLgcUyDsQvzAsxUJm/OEfzUjs9SHvmgmyAvzNAuTdO7wLQ+ZmKg0yZne6nvcrJVvfh3lD5ZPt7NY57Y6OIJluqKUT5H+a3H6W9Q1Z+cBMnHGYaaK7Tv8IcDdEYqTIG8hc5BqjFOzE=";
@@ -87,8 +73,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.True(Utilities.RSAUtility.VerifyWithSHA256ByCertificate(RSA_CERTIFICATE, plainText, signText)); Assert.True(Utilities.RSAUtility.VerifyWithSHA256ByCertificate(RSA_CERTIFICATE, plainText, signText));
} }
[Fact(DisplayName = "使用 RSA 公钥加密")] [Fact(DisplayName = "测试用例:使用 RSA 公钥加密")]
public void RSAEncryptTest() public void TestRSAEncrypt()
{ {
string plainText = "RsaEncryptTest"; string plainText = "RsaEncryptTest";
string actualCipherByPublicKey = Utilities.RSAUtility.EncryptWithECB(RSA_PUBLIC_KEY, plainText); string actualCipherByPublicKey = Utilities.RSAUtility.EncryptWithECB(RSA_PUBLIC_KEY, plainText);
@@ -99,8 +85,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.NotEqual(actualCipherByPublicKey, actualCipherByCertificate); Assert.NotEqual(actualCipherByPublicKey, actualCipherByCertificate);
} }
[Fact(DisplayName = "使用 RSA 私钥解密")] [Fact(DisplayName = "测试用例:使用 RSA 私钥解密")]
public void RSADecryptTest() public void TestRSADecrypt()
{ {
string cipherText = "LXwSqg4jqIv1X8Jx7RAbKw+mc/2SqAfdO4Ytqu09kytzCiDFdIZuJkdo2BQQOoyn/FtCyvn9Loip3VocOuATtsUDo6BmeMJcapl0HfXkyxsYnVRawsq01SPIRz8c83u+K38ZDVjNxEwcwcxH86wMm3PMzLZqISIVrD9sD3an5TfGuS+y/RN8y6W/P7BD/Rpxh0qLJl5B2oPYHOeKK0tdv6GlouUClzxB5tmdK5EKKw0j4WD5qIEwRm8Xzh/V27bt2autzRBbJT47eNypMR5wT7wWm/YwjyDoLLUmuCBaXbWZuqkB0pGS53y3Rdk64LVZ52567hBuQ/JdqMJdCecfy85x+ygnOtCM7bRl/fspU8U5SmwAKohYMc8VH4kRKhxoh8wX9wXCwbngLQ+S50TB3UziY1FmAmWFAI2/fpiyzGJZAVA+mYRCoQAFOksVEuud3ngGkfx2SafJ589IX9z0dnaz1AElaH84LhrOjJyU7dV6E9Su45IegNNai2O8bwN8dliVMPlXZuUAGaZpPLPOxq+hE7GpgNHaVFNye52b7dG3n3mt3hhSwb9AxAyAbSXktBSS/PMOAAS1TxwQ9C/0bKhApUDpjTG8oZBRBVTUHmsX+6/k5+6KSqfOrD88cBDPIhumY6V1h78GtXkFX2lQu9lT2J/fHCrDx39CiRnFAfI="; string cipherText = "LXwSqg4jqIv1X8Jx7RAbKw+mc/2SqAfdO4Ytqu09kytzCiDFdIZuJkdo2BQQOoyn/FtCyvn9Loip3VocOuATtsUDo6BmeMJcapl0HfXkyxsYnVRawsq01SPIRz8c83u+K38ZDVjNxEwcwcxH86wMm3PMzLZqISIVrD9sD3an5TfGuS+y/RN8y6W/P7BD/Rpxh0qLJl5B2oPYHOeKK0tdv6GlouUClzxB5tmdK5EKKw0j4WD5qIEwRm8Xzh/V27bt2autzRBbJT47eNypMR5wT7wWm/YwjyDoLLUmuCBaXbWZuqkB0pGS53y3Rdk64LVZ52567hBuQ/JdqMJdCecfy85x+ygnOtCM7bRl/fspU8U5SmwAKohYMc8VH4kRKhxoh8wX9wXCwbngLQ+S50TB3UziY1FmAmWFAI2/fpiyzGJZAVA+mYRCoQAFOksVEuud3ngGkfx2SafJ589IX9z0dnaz1AElaH84LhrOjJyU7dV6E9Su45IegNNai2O8bwN8dliVMPlXZuUAGaZpPLPOxq+hE7GpgNHaVFNye52b7dG3n3mt3hhSwb9AxAyAbSXktBSS/PMOAAS1TxwQ9C/0bKhApUDpjTG8oZBRBVTUHmsX+6/k5+6KSqfOrD88cBDPIhumY6V1h78GtXkFX2lQu9lT2J/fHCrDx39CiRnFAfI=";
string actualPlain = Utilities.RSAUtility.DecryptWithECB(RSA_PRIVATE_KEY, cipherText); string actualPlain = Utilities.RSAUtility.DecryptWithECB(RSA_PRIVATE_KEY, cipherText);
@@ -108,16 +94,5 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
Assert.Equal(expectedPlain, actualPlain); Assert.Equal(expectedPlain, actualPlain);
} }
[Fact(DisplayName = "信息摘要SHA-256")]
public void SHA256HashTest()
{
string rawData = "SHA256HashTest";
string actualHash = Utilities.SHA256Utility.Hash(rawData);
string expectedHash = "8446f1ce5ca8b4a87c0d0cc15be4ba173b2ff78dc33c5f6731d877dcd2d8f401";
Assert.Equal(expectedHash, actualHash, ignoreCase: true);
}
} }
} }

View File

@@ -7,14 +7,14 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
{ {
static TestClients() static TestClients()
{ {
GlobalCertificateManager = new Settings.InMemoryCertificateManager(); var certificateManager = new Settings.InMemoryCertificateManager();
Instance = new WechatTenpayClient(new WechatTenpayClientOptions() Instance = new WechatTenpayClient(new WechatTenpayClientOptions()
{ {
MerchantId = TestConfigs.WechatMerchantId, MerchantId = TestConfigs.WechatMerchantId,
MerchantV3Secret = TestConfigs.WechatMerchantSecret, MerchantV3Secret = TestConfigs.WechatMerchantSecret,
MerchantCertSerialNumber = TestConfigs.WechatMerchantCertSerialNumber, MerchantCertSerialNumber = TestConfigs.WechatMerchantCertSerialNumber,
MerchantCertPrivateKey = TestConfigs.WechatMerchantCertPrivateKey, MerchantCertPrivateKey = TestConfigs.WechatMerchantCertPrivateKey,
CertificateManager = GlobalCertificateManager CertificateManager = certificateManager
}); });
} }
@@ -26,12 +26,10 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
response = Instance.DecryptResponseSensitiveProperty(response); response = Instance.DecryptResponseSensitiveProperty(response);
foreach (var certificateModel in response.CertificateList) foreach (var certificateModel in response.CertificateList)
{ {
GlobalCertificateManager.AddEntry(new Settings.CertificateEntry(certificateModel)); Instance.CertificateManager.AddEntry(new Settings.CertificateEntry(certificateModel));
} }
} }
public static readonly Settings.CertificateManager GlobalCertificateManager;
public static readonly WechatTenpayClient Instance; public static readonly WechatTenpayClient Instance;
} }
} }

View File

@@ -17,15 +17,15 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
using var jdoc = JsonDocument.Parse(stream); using var jdoc = JsonDocument.Parse(stream);
var config = jdoc.RootElement.GetProperty("TestConfig"); var config = jdoc.RootElement.GetProperty("TestConfig");
WechatAppId = config.GetProperty("AppId").GetString(); WechatMerchantId = config.GetProperty("MerchantId").GetString()!;
WechatMerchantId = config.GetProperty("MerchantId").GetString(); WechatMerchantSecret = config.GetProperty("MerchantSecret").GetString()!;
WechatMerchantSecret = config.GetProperty("MerchantSecret").GetString(); WechatMerchantCertSerialNumber = config.GetProperty("MerchantCertSerialNumber").GetString()!;
WechatMerchantCertSerialNumber = config.GetProperty("MerchantCertSerialNumber").GetString(); WechatMerchantCertPrivateKey = config.GetProperty("MerchantCertPrivateKey").GetString()!;
WechatMerchantCertPrivateKey = config.GetProperty("MerchantCertPrivateKey").GetString(); WechatAppId = config.GetProperty("AppId").GetString()!;
WechatOpenId = config.GetProperty("OpenId").GetString(); WechatOpenId = config.GetProperty("OpenId").GetString()!;
ProjectSourceDirectory = jdoc.RootElement.GetProperty("ProjectSourceDirectory").GetString(); ProjectSourceDirectory = jdoc.RootElement.GetProperty("ProjectSourceDirectory").GetString()!;
ProjectTestDirectory = jdoc.RootElement.GetProperty("ProjectTestDirectory").GetString(); ProjectTestDirectory = jdoc.RootElement.GetProperty("ProjectTestDirectory").GetString()!;
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -33,11 +33,11 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
} }
} }
public static readonly string WechatAppId;
public static readonly string WechatMerchantId; public static readonly string WechatMerchantId;
public static readonly string WechatMerchantSecret; public static readonly string WechatMerchantSecret;
public static readonly string WechatMerchantCertSerialNumber; public static readonly string WechatMerchantCertSerialNumber;
public static readonly string WechatMerchantCertPrivateKey; public static readonly string WechatMerchantCertPrivateKey;
public static readonly string WechatAppId;
public static readonly string WechatOpenId; public static readonly string WechatOpenId;
public static readonly string ProjectSourceDirectory; public static readonly string ProjectSourceDirectory;

View File

@@ -1,10 +1,10 @@
{ {
"TestConfig": { "TestConfig": {
"AppId": "请在此填写用于测试的微信 AppId",
"MerchantId": "请在此填写用于测试的微信商户号", "MerchantId": "请在此填写用于测试的微信商户号",
"MerchantSecret": "请在此填写用于测试的微信商户 API v3 密钥", "MerchantSecret": "请在此填写用于测试的微信商户 API v3 密钥",
"MerchantCertSerialNumber": "请在此填写用于测试的微信商户 API 证书序列号", "MerchantCertSerialNumber": "请在此填写用于测试的微信商户 API 证书序列号",
"MerchantCertPrivateKey": "请在此填写用于测试的微信商户 API 证书私钥(字符串格式)", "MerchantCertPrivateKey": "请在此填写用于测试的微信商户 API 证书私钥(字符串格式)",
"AppId": "请在此填写用于测试的微信 AppId",
"OpenId": "请在此填写用于测试的微信用户唯一标识" "OpenId": "请在此填写用于测试的微信用户唯一标识"
}, },
"ProjectSourceDirectory": "请输入当前 SDK 项目所在的目录完整路径,如 C:\\Project\\src\\SKIT.FlurlHttpClient.Wechat.TenpayV3\\", "ProjectSourceDirectory": "请输入当前 SDK 项目所在的目录完整路径,如 C:\\Project\\src\\SKIT.FlurlHttpClient.Wechat.TenpayV3\\",