mirror of
https://gitee.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat.git
synced 2025-09-19 01:58:14 +08:00
feat(tenpayv3): 升级公共组件
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using SKIT.FlurlHttpClient.Tools.CodeAnalyzer;
|
||||
using Xunit;
|
||||
|
||||
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
|
||||
{
|
||||
public class CodeAnalyzeTests
|
||||
{
|
||||
[Fact(DisplayName = "代码质量分析")]
|
||||
public void CodeAnalyze()
|
||||
{
|
||||
Assert.Null(Record.Exception(() =>
|
||||
{
|
||||
var options = new TypeDeclarationAnalyzerOptions()
|
||||
{
|
||||
SdkAssembly = Assembly.GetAssembly(typeof(WechatTenpayClient))!,
|
||||
SdkRequestModelDeclarationNamespace = "SKIT.FlurlHttpClient.Wechat.TenpayV3.Models",
|
||||
SdkResponseModelDeclarationNamespace = "SKIT.FlurlHttpClient.Wechat.TenpayV3.Models",
|
||||
SdkExecutingExtensionDeclarationNamespace = "SKIT.FlurlHttpClient.Wechat.TenpayV3",
|
||||
SdkWebhookEventDeclarationNamespace = "SKIT.FlurlHttpClient.Wechat.TenpayV3.Events",
|
||||
ThrowOnNotFoundRequestModelTypes = true,
|
||||
ThrowOnNotFoundResponseModelTypes = true,
|
||||
ThrowOnNotFoundExecutingExtensionTypes = true,
|
||||
ThrowOnNotFoundWebhookEventTypes = true
|
||||
};
|
||||
new TypeDeclarationAnalyzer(options).AssertNoIssues();
|
||||
}));
|
||||
|
||||
Assert.Null(Record.Exception(() =>
|
||||
{
|
||||
string workdir = Environment.CurrentDirectory;
|
||||
string projdir = Path.Combine(workdir, "../../../../../");
|
||||
|
||||
var options = new SourceFileAnalyzerOptions()
|
||||
{
|
||||
SdkAssembly = Assembly.GetAssembly(typeof(WechatTenpayClient))!,
|
||||
SdkRequestModelDeclarationNamespace = "SKIT.FlurlHttpClient.Wechat.TenpayV3.Models",
|
||||
SdkResponseModelDeclarationNamespace = "SKIT.FlurlHttpClient.Wechat.TenpayV3.Models",
|
||||
SdkWebhookEventDeclarationNamespace = "SKIT.FlurlHttpClient.Wechat.TenpayV3.Events",
|
||||
ProjectSourceRootDirectory = Path.Combine(projdir, "./src/SKIT.FlurlHttpClient.Wechat.TenpayV3/"),
|
||||
ProjectTestRootDirectory = Path.Combine(projdir, "./test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/"),
|
||||
ThrowOnNotFoundRequestModelClassCodeFiles = true,
|
||||
ThrowOnNotFoundResponseModelClassCodeFiles = true,
|
||||
ThrowOnNotFoundExecutingExtensionClassCodeFiles = true,
|
||||
ThrowOnNotFoundWebhookEventClassCodeFiles = true,
|
||||
ThrowOnNotFoundRequestModelSerializationSampleFiles = true,
|
||||
ThrowOnNotFoundResponseModelSerializationSampleFiles = true,
|
||||
ThrowOnNotFoundWebhookEventSerializationSampleFiles = true
|
||||
};
|
||||
new SourceFileAnalyzer(options)
|
||||
.SetFileScanner(SourceFileContentKinds.WebhookEventClassCode, (directory) => directory.GetAllFiles("*.cs"))
|
||||
.SetFileScanner(SourceFileContentKinds.WebhookEventSerializationSample, (directory) => directory.GetAllFiles("*.json"))
|
||||
.AssertNoIssues();
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
@@ -11,22 +11,22 @@
|
||||
<ItemGroup>
|
||||
<None Remove=".gitignore" />
|
||||
<Content Include="appsettings.json">
|
||||
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
|
||||
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="appsettings.*.json" Condition="'$(Configuration)' == 'Debug'">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<CopyToPublishDirectory>Always</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="ModelSamples/**/*.json" />
|
||||
<Content Include="EventSamples/**/*.json" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.0" />
|
||||
<PackageReference Include="SKIT.FlurlHttpClient.Tools.CodeAnalyzer" Version="0.1.0-alpha.1" />
|
||||
<PackageReference Include="xunit" Version="2.4.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
|
||||
<PackageReference Include="SKIT.FlurlHttpClient.Tools.CodeAnalyzer" Version="0.3.0-preview.1" />
|
||||
<PackageReference Include="xunit" Version="2.6.6" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.6">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
|
||||
var response = await TestClients.InstanceUseRSA.ExecuteDownloadBillFileAsync(request);
|
||||
|
||||
Assert.True(response.IsSuccessful());
|
||||
Assert.NotEmpty(response.RawBytes);
|
||||
Assert.NotEmpty(response.GetRawBytes());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
@@ -135,7 +135,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
|
||||
Assert.NotNull(response.CombineAppId);
|
||||
Assert.NotNull(response.CombineMerchantId);
|
||||
Assert.NotNull(response.CombineOutTradeNumber);
|
||||
Assert.NotEmpty(response.SubOrderList);
|
||||
Assert.NotEmpty(response.SubOrderList!);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "测试用例:调用 API [POST] /combine-transactions/out-trade-no/{combine_out_trade_no}/close")]
|
||||
|
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
|
@@ -41,7 +41,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
|
||||
[Fact(DisplayName = "测试用例:`CertificateEntry` 构造器")]
|
||||
public void TestCertificateEntryConstructor()
|
||||
{
|
||||
var certRSA = new Settings.CertificateEntry(
|
||||
var certRSA = Settings.CertificateEntry.Parse(
|
||||
new Models.QueryCertificatesResponse.Types.Certificate()
|
||||
{
|
||||
SerialNumber = CERT_RSA_SN,
|
||||
@@ -55,7 +55,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
|
||||
);
|
||||
Assert.Equal(Settings.CertificateEntry.ALGORITHM_TYPE_RSA, certRSA.AlgorithmType);
|
||||
|
||||
var certSM2 = new Settings.CertificateEntry(
|
||||
var certSM2 = Settings.CertificateEntry.Parse(
|
||||
new Models.QueryCertificatesResponse.Types.Certificate()
|
||||
{
|
||||
SerialNumber = CERT_SM2_SN,
|
||||
|
@@ -1,28 +0,0 @@
|
||||
using SKIT.FlurlHttpClient.Tools.CodeAnalyzer;
|
||||
using Xunit;
|
||||
|
||||
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
|
||||
{
|
||||
public class TestCase_CodeReview
|
||||
{
|
||||
[Fact(DisplayName = "测试用例:代码质量分析")]
|
||||
public void TestCodeAnalyzer()
|
||||
{
|
||||
Assert.Null(Record.Exception(() =>
|
||||
{
|
||||
CodeAnalyzerOptions options = new CodeAnalyzerOptions()
|
||||
{
|
||||
AssemblyName = "SKIT.FlurlHttpClient.Wechat.TenpayV3",
|
||||
WorkDirectoryForSourceCode = TestConfigs.WorkDirectoryForSdk,
|
||||
WorkDirectoryForTestSample = TestConfigs.WorkDirectoryForTest,
|
||||
AllowNotFoundEventTypes = true,
|
||||
AllowNotFoundEventSamples = true
|
||||
};
|
||||
CodeAnalyzer analyzer = new CodeAnalyzer(options);
|
||||
analyzer.Start();
|
||||
analyzer.Assert();
|
||||
analyzer.Flush();
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,92 @@
|
||||
using Xunit;
|
||||
|
||||
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
|
||||
{
|
||||
public class TestCase_JsonConverterOfYesOrNoBooleanBooleanTest
|
||||
{
|
||||
private sealed class MockObject
|
||||
{
|
||||
[Newtonsoft.Json.JsonProperty(Order = 1)]
|
||||
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.Internal.YesOrNoBooleanConverter))]
|
||||
[System.Text.Json.Serialization.JsonPropertyOrder(1)]
|
||||
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.Internal.YesOrNoBooleanConverter))]
|
||||
public bool Property { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty(Order = 2)]
|
||||
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.Internal.YesOrNoBooleanConverter))]
|
||||
[System.Text.Json.Serialization.JsonPropertyOrder(2)]
|
||||
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.Internal.YesOrNoBooleanConverter))]
|
||||
public bool? NullableProperty { get; set; }
|
||||
}
|
||||
|
||||
private static void TestCustomJsonConverter(IJsonSerializer jsonSerializer)
|
||||
{
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
var expectObj = new MockObject() { NullableProperty = null };
|
||||
var actualJson = jsonSerializer.Serialize(expectObj);
|
||||
var actualObj = jsonSerializer.Deserialize<MockObject>(actualJson);
|
||||
|
||||
Assert.Equal("{\"Property\":\"N\"}", actualJson);
|
||||
|
||||
Assert.Equal(expectObj.Property, actualObj.Property);
|
||||
Assert.Equal(expectObj.Property, jsonSerializer.Deserialize<MockObject>("{\"Property\":\"N\"}").Property);
|
||||
Assert.Equal(expectObj.Property, jsonSerializer.Deserialize<MockObject>("{}").Property);
|
||||
|
||||
Assert.Equal(expectObj.NullableProperty, actualObj.NullableProperty);
|
||||
Assert.Equal(expectObj.NullableProperty, jsonSerializer.Deserialize<MockObject>("{\"NullableProperty\":null}").NullableProperty);
|
||||
Assert.Equal(expectObj.NullableProperty, jsonSerializer.Deserialize<MockObject>("{}").NullableProperty);
|
||||
});
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
var expectObj = new MockObject() { Property = false, NullableProperty = false };
|
||||
var actualJson = jsonSerializer.Serialize(expectObj);
|
||||
var actualObj = jsonSerializer.Deserialize<MockObject>(actualJson);
|
||||
|
||||
Assert.Equal("{\"Property\":\"N\",\"NullableProperty\":\"N\"}", actualJson);
|
||||
|
||||
Assert.Equal(expectObj.Property, actualObj.Property);
|
||||
Assert.Equal(expectObj.Property, jsonSerializer.Deserialize<MockObject>("{\"Property\":false}").Property);
|
||||
|
||||
Assert.Equal(expectObj.NullableProperty, actualObj.NullableProperty);
|
||||
Assert.Equal(expectObj.NullableProperty, jsonSerializer.Deserialize<MockObject>("{\"NullableProperty\":false}").NullableProperty);
|
||||
});
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
var expectObj = new MockObject() { Property = true, NullableProperty = true };
|
||||
var actualJson = jsonSerializer.Serialize(expectObj);
|
||||
var actualObj = jsonSerializer.Deserialize<MockObject>(actualJson);
|
||||
|
||||
Assert.Equal("{\"Property\":\"Y\",\"NullableProperty\":\"Y\"}", actualJson);
|
||||
|
||||
Assert.Equal(expectObj.Property, actualObj.Property);
|
||||
Assert.Equal(expectObj.Property, jsonSerializer.Deserialize<MockObject>("{\"Property\":true}").Property);
|
||||
|
||||
Assert.Equal(expectObj.NullableProperty, actualObj.NullableProperty);
|
||||
Assert.Equal(expectObj.NullableProperty, jsonSerializer.Deserialize<MockObject>("{\"NullableProperty\":true}").NullableProperty);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "测试用例:自定义 Newtosoft.Json.JsonConverter 之 YesOrNoBooleanConverter")]
|
||||
public void TestNewtosoftJsonConverter()
|
||||
{
|
||||
var jsonSettings = NewtonsoftJsonSerializer.GetDefaultSerializerSettings();
|
||||
jsonSettings.Formatting = Newtonsoft.Json.Formatting.None;
|
||||
jsonSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;
|
||||
|
||||
TestCustomJsonConverter(new NewtonsoftJsonSerializer(jsonSettings));
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "测试用例:自定义 System.Text.Json.Serialization.JsonConverter 之 YesOrNoBooleanConverter")]
|
||||
public void TestSystemTextJsonConverter()
|
||||
{
|
||||
var jsonOptions = SystemTextJsonSerializer.GetDefaultSerializerOptions();
|
||||
jsonOptions.WriteIndented = false;
|
||||
jsonOptions.DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull;
|
||||
|
||||
TestCustomJsonConverter(new SystemTextJsonSerializer(jsonOptions));
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,4 @@
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
@@ -5,36 +6,42 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
|
||||
{
|
||||
public class TestCase_ResponseVerificationTests
|
||||
{
|
||||
[Fact(DisplayName = "测试用例:验证响应签名")]
|
||||
public async Task TestVerifyResponseSignature()
|
||||
[Fact(DisplayName = "测试用例:验证响应签名(基于 RSA)")]
|
||||
public async Task TestVerifyResponseSignatureUseRSA()
|
||||
{
|
||||
await TestClients.InitializeCertificateManagerAsync();
|
||||
|
||||
var request1 = new Models.QueryCertificatesRequest() { AlgorithmType = "RSA" };
|
||||
var response1 = await TestClients.InstanceUseRSA.ExecuteQueryCertificatesAsync(request1);
|
||||
Assert.True(response1.RawStatus == 200);
|
||||
Assert.True(response1.RawHeaders.Count > 0);
|
||||
Assert.True(response1.RawBytes.Length > 0);
|
||||
Assert.True(TestClients.InstanceUseRSA.VerifyResponseSignature(response1));
|
||||
Assert.NotNull(response1.WechatpayRequestId);
|
||||
Assert.NotNull(response1.WechatpayNonce);
|
||||
Assert.NotNull(response1.WechatpayTimestamp);
|
||||
Assert.NotNull(response1.WechatpaySignature);
|
||||
Assert.NotNull(response1.WechatpaySignatureType);
|
||||
Assert.NotNull(response1.WechatpayCertificateSerialNumber);
|
||||
var request = new Models.QueryCertificatesRequest() { AlgorithmType = "RSA" };
|
||||
var response = await TestClients.InstanceUseRSA.ExecuteQueryCertificatesAsync(request);
|
||||
Assert.True(response.GetRawStatus() == 200);
|
||||
Assert.True(response.GetRawHeaders().Any());
|
||||
Assert.True(response.GetRawBytes().Any());
|
||||
Assert.True(TestClients.InstanceUseRSA.VerifyResponseSignature(response));
|
||||
Assert.NotNull(response.WechatpayRequestId);
|
||||
Assert.NotNull(response.WechatpayNonce);
|
||||
Assert.NotNull(response.WechatpayTimestamp);
|
||||
Assert.NotNull(response.WechatpaySignature);
|
||||
Assert.NotNull(response.WechatpaySignatureType);
|
||||
Assert.NotNull(response.WechatpayCertificateSerialNumber);
|
||||
}
|
||||
|
||||
var request2 = new Models.QueryCertificatesRequest() { AlgorithmType = "SM2" };
|
||||
var response2 = await TestClients.InstanceUseSM2.ExecuteQueryCertificatesAsync(request2);
|
||||
Assert.True(response2.RawStatus == 200);
|
||||
Assert.True(response2.RawHeaders.Count > 0);
|
||||
Assert.True(response2.RawBytes.Length > 0);
|
||||
Assert.True(TestClients.InstanceUseSM2.VerifyResponseSignature(response2));
|
||||
Assert.NotNull(response2.WechatpayRequestId);
|
||||
Assert.NotNull(response2.WechatpayNonce);
|
||||
Assert.NotNull(response2.WechatpayTimestamp);
|
||||
Assert.NotNull(response2.WechatpaySignature);
|
||||
Assert.NotNull(response2.WechatpaySignatureType);
|
||||
Assert.NotNull(response2.WechatpayCertificateSerialNumber);
|
||||
[Fact(DisplayName = "测试用例:验证响应签名(基于 SM2)")]
|
||||
public async Task TestVerifyResponseSignatureUseSM2()
|
||||
{
|
||||
await TestClients.InitializeCertificateManagerAsync();
|
||||
|
||||
var request = new Models.QueryCertificatesRequest() { AlgorithmType = "SM2" };
|
||||
var response = await TestClients.InstanceUseSM2.ExecuteQueryCertificatesAsync(request);
|
||||
Assert.True(response.GetRawStatus() == 200);
|
||||
Assert.True(response.GetRawHeaders().Any());
|
||||
Assert.True(response.GetRawBytes().Any());
|
||||
Assert.True(TestClients.InstanceUseSM2.VerifyResponseSignature(response));
|
||||
Assert.NotNull(response.WechatpayRequestId);
|
||||
Assert.NotNull(response.WechatpayNonce);
|
||||
Assert.NotNull(response.WechatpayTimestamp);
|
||||
Assert.NotNull(response.WechatpaySignature);
|
||||
Assert.NotNull(response.WechatpaySignatureType);
|
||||
Assert.NotNull(response.WechatpayCertificateSerialNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -37,7 +37,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
|
||||
|
||||
foreach (var certificate in InstanceUseRSA.DecryptResponseSensitiveProperty(response).CertificateList)
|
||||
{
|
||||
InstanceUseRSA.PlatformCertificateManager.AddEntry(new Settings.CertificateEntry(certificate));
|
||||
InstanceUseRSA.PlatformCertificateManager.AddEntry(Settings.CertificateEntry.Parse(certificate));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -16,7 +16,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
|
||||
using var stream = File.OpenRead("appsettings.local.json");
|
||||
using var jdoc = JsonDocument.Parse(stream);
|
||||
|
||||
var config = jdoc.RootElement.GetProperty("TestConfig");
|
||||
var config = jdoc.RootElement.GetProperty("TestConfigs");
|
||||
WechatMerchantId = config.GetProperty("MerchantId").GetString()!;
|
||||
WechatMerchantSecret = config.GetProperty("MerchantSecret").GetString()!;
|
||||
WechatMerchantRSACertificateSerialNumber = config.GetProperty("MerchantRSACertificateSerialNumber").GetString()!;
|
||||
@@ -25,9 +25,6 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
|
||||
WechatMerchantSM2CertificatePrivateKey = config.GetProperty("MerchantSM2CertificatePrivateKey").GetString();
|
||||
WechatAppId = config.GetProperty("AppId").GetString()!;
|
||||
WechatOpenId = config.GetProperty("OpenId").GetString()!;
|
||||
|
||||
WorkDirectoryForSdk = jdoc.RootElement.GetProperty("WorkDirectoryForSdk").GetString()!;
|
||||
WorkDirectoryForTest = jdoc.RootElement.GetProperty("WorkDirectoryForTest").GetString()!;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -43,8 +40,5 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
|
||||
public static readonly string? WechatMerchantSM2CertificatePrivateKey;
|
||||
public static readonly string WechatAppId;
|
||||
public static readonly string WechatOpenId;
|
||||
|
||||
public static readonly string WorkDirectoryForSdk;
|
||||
public static readonly string WorkDirectoryForTest;
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"TestConfig": {
|
||||
"TestConfigs": {
|
||||
"MerchantId": "请在此填写用于测试的微信商户号",
|
||||
"MerchantSecret": "请在此填写用于测试的微信商户 API v3 密钥",
|
||||
"MerchantRSACertificateSerialNumber": "请在此填写用于测试的微信商户基于 RSA 算法的 API 证书序列号",
|
||||
@@ -8,7 +8,5 @@
|
||||
"MerchantSM2CertificatePrivateKey": "请在此填写用于测试的微信商户基于 SM2 算法的 API 证书私钥(字符串格式)",
|
||||
"AppId": "请在此填写用于测试的微信 AppId",
|
||||
"OpenId": "请在此填写用于测试的微信用户唯一标识"
|
||||
},
|
||||
"WorkDirectoryForSdk": "请输入当前 SDK 项目所在的目录完整路径,如 C:\\Project\\src\\SKIT.FlurlHttpClient.Wechat.TenpayV3\\",
|
||||
"WorkDirectoryForTest": "请输入当前测试项目所在的目录完整路径,如 C:\\Project\\test\\SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests\\"
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user