diff --git a/docs/WechatTenpayV3/Basic_ModelDefinition.md b/docs/WechatTenpayV3/Basic_ModelDefinition.md
index eeeda2c8..f301af3e 100644
--- a/docs/WechatTenpayV3/Basic_ModelDefinition.md
+++ b/docs/WechatTenpayV3/Basic_ModelDefinition.md
@@ -49,6 +49,7 @@
| √ | 行业方案:微信支付分停车服务 | 直连商户 & 服务商 | |
| √ | 行业方案:租用充电宝隔夜归还 | 直连商户 | |
| √ | 行业方案:微信点餐订单 | 服务商 | |
+| √ | 行业方案:ETC 扣费 | 服务商 | |
| √ | 营销工具:代金券 | 直连商户 & 服务商 | |
| √ | 营销工具:商家券 | 直连商户 & 服务商 | |
| √ | 营销工具:委托营销 | 直连商户 & 服务商 | |
diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Events/Vehicle/VehicleETCTransactionResource.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Events/Vehicle/VehicleETCTransactionResource.cs
new file mode 100644
index 00000000..abb00a48
--- /dev/null
+++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Events/Vehicle/VehicleETCTransactionResource.cs
@@ -0,0 +1,71 @@
+namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Events
+{
+ ///
+ /// 表示 TRANSACTION.SUCCESS(仅限 ETC 扣费)通知的数据。
+ ///
+ public class VehicleETCTransactionResource : WechatTenpayEvent.Types.IDecryptedResource
+ {
+ ///
+ /// 获取或设置微信商户号。
+ ///
+ [Newtonsoft.Json.JsonProperty("sp_mchid")]
+ [System.Text.Json.Serialization.JsonPropertyName("sp_mchid")]
+ public string MerchantId { get; set; } = default!;
+
+ ///
+ /// 获取或设置子商户号。
+ ///
+ [Newtonsoft.Json.JsonProperty("sub_mchid")]
+ [System.Text.Json.Serialization.JsonPropertyName("sub_mchid")]
+ public string? SubMerchantId { get; set; }
+
+ ///
+ /// 获取或设置微信 AppId。
+ ///
+ [Newtonsoft.Json.JsonProperty("appid")]
+ [System.Text.Json.Serialization.JsonPropertyName("appid")]
+ public string AppId { get; set; } = default!;
+
+ ///
+ /// 获取或设置子商户 AppId。
+ ///
+ [Newtonsoft.Json.JsonProperty("sub_appid")]
+ [System.Text.Json.Serialization.JsonPropertyName("sub_appid")]
+ public string? SubAppId { get; set; }
+
+ ///
+ /// 获取或设置用户唯一标识。
+ ///
+ [Newtonsoft.Json.JsonProperty("sp_openid")]
+ [System.Text.Json.Serialization.JsonPropertyName("sp_openid")]
+ public string? OpenId { get; set; }
+
+ ///
+ /// 获取或设置用户在子商户下的唯一标识。
+ ///
+ [Newtonsoft.Json.JsonProperty("sub_openid")]
+ [System.Text.Json.Serialization.JsonPropertyName("sub_openid")]
+ public string? SubOpenId { get; set; }
+
+ ///
+ /// 获取或设置 ETC 扣费授权协议号。
+ ///
+ [Newtonsoft.Json.JsonProperty("contract_id")]
+ [System.Text.Json.Serialization.JsonPropertyName("contract_id")]
+ public string ContractId { get; set; } = default!;
+
+ ///
+ /// 获取或设置车牌号。
+ ///
+ [Newtonsoft.Json.JsonProperty("plate_number")]
+ [System.Text.Json.Serialization.JsonPropertyName("plate_number")]
+ public string PlateNumber { get; set; } = default!;
+
+ ///
+ /// 获取或设置绑定状态。
+ ///
+ [Newtonsoft.Json.JsonProperty("bind_state")]
+ [System.Text.Json.Serialization.JsonPropertyName("bind_state")]
+ public string BindState { get; set; } = default!;
+ }
+}
diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Events/VehicleParking/VehicleEntranceStateChangeResource.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Events/Vehicle/VehicleEntranceStateChangeResource.cs
similarity index 100%
rename from src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Events/VehicleParking/VehicleEntranceStateChangeResource.cs
rename to src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Events/Vehicle/VehicleEntranceStateChangeResource.cs
diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Events/VehicleParking/VehicleTransactionResource.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Events/Vehicle/VehicleTransactionResource.cs
similarity index 99%
rename from src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Events/VehicleParking/VehicleTransactionResource.cs
rename to src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Events/Vehicle/VehicleTransactionResource.cs
index 7958da0d..54574152 100644
--- a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Events/VehicleParking/VehicleTransactionResource.cs
+++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Events/Vehicle/VehicleTransactionResource.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Events
{
diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Extensions/WechatTenpayClientExecuteVehicleExtensions.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Extensions/WechatTenpayClientExecuteVehicleExtensions.cs
index 100bf8d6..26e11f8f 100644
--- a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Extensions/WechatTenpayClientExecuteVehicleExtensions.cs
+++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Extensions/WechatTenpayClientExecuteVehicleExtensions.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
@@ -12,6 +12,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
///
public static class WechatTenpayClientExecuteVehicleExtensions
{
+ #region Parking
///
/// 异步调用 [GET] /vehicle/parking/services/find 接口。
/// REF: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter8_8_1.shtml
@@ -58,7 +59,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken);
}
+ #endregion
+ #region Transactions
///
/// 异步调用 [POST] /vehicle/transactions/parking 接口。
/// REF: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter8_8_3.shtml
@@ -101,5 +104,136 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken);
}
+ #endregion
+
+ #region ETC
+ ///
+ /// 异步调用 [POST] /vehicle/etc/preopen 接口。
+ /// REF: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter4_4_1.shtml
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static async Task ExecutePreopenVehicleETCAsync(this WechatTenpayClient client, Models.PreopenVehicleETCRequest request, CancellationToken cancellationToken = default)
+ {
+ if (client is null) throw new ArgumentNullException(nameof(client));
+ if (request is null) throw new ArgumentNullException(nameof(request));
+
+ IFlurlRequest flurlReq = client
+ .CreateRequest(request, HttpMethod.Post, "vehicle", "etc", "preopen");
+
+ return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken);
+ }
+
+ ///
+ /// 异步调用 [POST] /vehicle/etc/transactions/highway 接口。
+ /// REF: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter4_4_3.shtml
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static async Task ExecuteCreateVehicleETCTransactionHighwayAsync(this WechatTenpayClient client, Models.CreateVehicleETCTransactionHighwayRequest request, CancellationToken cancellationToken = default)
+ {
+ if (client is null) throw new ArgumentNullException(nameof(client));
+ if (request is null) throw new ArgumentNullException(nameof(request));
+
+ IFlurlRequest flurlReq = client
+ .CreateRequest(request, HttpMethod.Post, "vehicle", "etc", "transactions", "highway");
+
+ return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken);
+ }
+
+ ///
+ /// 异步调用 [GET] /vehicle/etc/users/{openid}/contracts 接口。
+ /// REF: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter4_4_3.shtml
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static async Task ExecuteGetVehicleETCContractByOpenIdAsync(this WechatTenpayClient client, Models.GetVehicleETCContractByOpenIdRequest request, CancellationToken cancellationToken = default)
+ {
+ if (client is null) throw new ArgumentNullException(nameof(client));
+ if (request is null) throw new ArgumentNullException(nameof(request));
+
+ IFlurlRequest flurlReq = client
+ .CreateRequest(request, HttpMethod.Get, "vehicle", "etc", "users", request.OpenId, "contracts")
+ .SetQueryParam("plan_id", request.PlanId)
+ .SetQueryParam("plate_number", request.PlateNumber);
+
+ if (request.SubMerchantId != null)
+ flurlReq.SetQueryParam("sub_mchid", request.SubMerchantId);
+
+ return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken);
+ }
+
+ ///
+ /// 异步调用 [GET] /vehicle/etc/contracts/{contract_id} 接口。
+ /// REF: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter4_4_3.shtml
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static async Task ExecuteGetVehicleETCContractByContractIdAsync(this WechatTenpayClient client, Models.GetVehicleETCContractByContractIdRequest request, CancellationToken cancellationToken = default)
+ {
+ if (client is null) throw new ArgumentNullException(nameof(client));
+ if (request is null) throw new ArgumentNullException(nameof(request));
+
+ IFlurlRequest flurlReq = client
+ .CreateRequest(request, HttpMethod.Get, "vehicle", "etc", "contracts", request.ContractId);
+
+ if (request.SubMerchantId != null)
+ flurlReq.SetQueryParam("sub_mchid", request.SubMerchantId);
+
+ return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken);
+ }
+
+ ///
+ /// 异步调用 [GET] /vehicle/etc/transactions/out-trade-no/{out_trade_no} 接口。
+ /// REF: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter4_4_8.shtml
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static async Task ExecuteGetVehicleETCTransactionByOutTradeNumberAsync(this WechatTenpayClient client, Models.GetVehicleETCTransactionByOutTradeNumberRequest request, CancellationToken cancellationToken = default)
+ {
+ if (client is null) throw new ArgumentNullException(nameof(client));
+ if (request is null) throw new ArgumentNullException(nameof(request));
+
+ IFlurlRequest flurlReq = client
+ .CreateRequest(request, HttpMethod.Get, "vehicle", "etc", "transactions", "out-trade-no", request.OutTradeNumber);
+
+ if (request.SubMerchantId != null)
+ flurlReq.SetQueryParam("sub_mchid", request.SubMerchantId);
+
+ return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken);
+ }
+
+ ///
+ /// 异步调用 [GET] /vehicle/etc/transactions/id/{transaction_id} 接口。
+ /// REF: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter4_4_8.shtml
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static async Task ExecuteGetVehicleETCTransactionByTransactionIdAsync(this WechatTenpayClient client, Models.GetVehicleETCTransactionByTransactionIdRequest request, CancellationToken cancellationToken = default)
+ {
+ if (client is null) throw new ArgumentNullException(nameof(client));
+ if (request is null) throw new ArgumentNullException(nameof(request));
+
+ IFlurlRequest flurlReq = client
+ .CreateRequest(request, HttpMethod.Get, "vehicle", "etc", "transactions", "id", request.TransactionId);
+
+ if (request.SubMerchantId != null)
+ flurlReq.SetQueryParam("sub_mchid", request.SubMerchantId);
+
+ return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken);
+ }
+ #endregion
}
}
diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/NewTaxControlFapiao/FapiaoApplications/CreateNewTaxControlFapiaoApplicationRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/NewTaxControlFapiao/FapiaoApplications/CreateNewTaxControlFapiaoApplicationRequest.cs
index 9a852c83..d7283eed 100644
--- a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/NewTaxControlFapiao/FapiaoApplications/CreateNewTaxControlFapiaoApplicationRequest.cs
+++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/NewTaxControlFapiao/FapiaoApplications/CreateNewTaxControlFapiaoApplicationRequest.cs
@@ -63,7 +63,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
public string? BankAccountNumber { get; set; }
///
- /// 获取或设置用户手机号码。
+ /// 获取或设置用户手机号码(需使用平台公钥/证书加密)。
///
[Newtonsoft.Json.JsonProperty("phone")]
[System.Text.Json.Serialization.JsonPropertyName("phone")]
@@ -72,7 +72,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
public string? UserMobileNumber { get; set; }
///
- /// 获取或设置用户邮箱地址。
+ /// 获取或设置用户邮箱地址(需使用平台公钥/证书加密)。
///
[Newtonsoft.Json.JsonProperty("email")]
[System.Text.Json.Serialization.JsonPropertyName("email")]
diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/NewTaxControlFapiao/FapiaoApplications/GetNewTaxControlFapiaoApplicationByFapiaoApplyIdResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/NewTaxControlFapiao/FapiaoApplications/GetNewTaxControlFapiaoApplicationByFapiaoApplyIdResponse.cs
index d379f8fe..70c61458 100644
--- a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/NewTaxControlFapiao/FapiaoApplications/GetNewTaxControlFapiaoApplicationByFapiaoApplyIdResponse.cs
+++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/NewTaxControlFapiao/FapiaoApplications/GetNewTaxControlFapiaoApplicationByFapiaoApplyIdResponse.cs
@@ -144,7 +144,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
public string? BankAccountNumber { get; set; }
///
- /// 获取或设置用户手机号码。
+ /// 获取或设置用户手机号码(需使用商户私钥解密)。
///
[Newtonsoft.Json.JsonProperty("phone")]
[System.Text.Json.Serialization.JsonPropertyName("phone")]
@@ -153,7 +153,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
public string? UserMobileNumber { get; set; }
///
- /// 获取或设置用户邮箱地址。
+ /// 获取或设置用户邮箱地址(需使用商户私钥解密)。
///
[Newtonsoft.Json.JsonProperty("email")]
[System.Text.Json.Serialization.JsonPropertyName("email")]
diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/NewTaxControlFapiao/UserTitle/GetNewTaxControlFapiaoUserTitleResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/NewTaxControlFapiao/UserTitle/GetNewTaxControlFapiaoUserTitleResponse.cs
index d7c74a03..aac095f8 100644
--- a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/NewTaxControlFapiao/UserTitle/GetNewTaxControlFapiaoUserTitleResponse.cs
+++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/NewTaxControlFapiao/UserTitle/GetNewTaxControlFapiaoUserTitleResponse.cs
@@ -56,7 +56,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
public string? BankAccountNumber { get; set; }
///
- /// 获取或设置用户手机号码。
+ /// 获取或设置用户手机号码(需使用平台公钥/证书加密)。
///
[Newtonsoft.Json.JsonProperty("phone")]
[System.Text.Json.Serialization.JsonPropertyName("phone")]
@@ -65,7 +65,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
public string? UserMobileNumber { get; set; }
///
- /// 获取或设置用户邮箱地址。
+ /// 获取或设置用户邮箱地址(需使用平台公钥/证书加密)。
///
[Newtonsoft.Json.JsonProperty("email")]
[System.Text.Json.Serialization.JsonPropertyName("email")]
diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Vehicle/ETC/CreateVehicleETCTransactionHighwayRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Vehicle/ETC/CreateVehicleETCTransactionHighwayRequest.cs
new file mode 100644
index 00000000..6f1dc3b2
--- /dev/null
+++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Vehicle/ETC/CreateVehicleETCTransactionHighwayRequest.cs
@@ -0,0 +1,195 @@
+using System;
+
+namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
+{
+ ///
+ /// 表示 [POST] /vehicle/etc/transactions/highway 接口的请求。
+ ///
+ public class CreateVehicleETCTransactionHighwayRequest : WechatTenpayRequest
+ {
+ public static class Types
+ {
+ public class Amount
+ {
+ ///
+ /// 获取或设置总金额(单位:分)。
+ ///
+ [Newtonsoft.Json.JsonProperty("total")]
+ [System.Text.Json.Serialization.JsonPropertyName("total")]
+ public int Total { get; set; }
+
+ ///
+ /// 获取或设置币种。
+ /// 默认值:CNY
+ ///
+ [Newtonsoft.Json.JsonProperty("currency")]
+ [System.Text.Json.Serialization.JsonPropertyName("currency")]
+ public string Currency { get; set; } = "CNY";
+ }
+
+ public class Highway
+ {
+ ///
+ /// 获取或设置车牌号。
+ ///
+ [Newtonsoft.Json.JsonProperty("plate_number")]
+ [System.Text.Json.Serialization.JsonPropertyName("plate_number")]
+ public string PlateNumber { get; set; } = string.Empty;
+
+ ///
+ /// 获取或设置入站时间。
+ ///
+ [Newtonsoft.Json.JsonProperty("start_time")]
+ [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RFC3339DateTimeOffsetConverter))]
+ [System.Text.Json.Serialization.JsonPropertyName("start_time")]
+ [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RFC3339DateTimeOffsetConverter))]
+ public DateTimeOffset StartTime { get; set; }
+
+ ///
+ /// 获取或设置出站时间。
+ ///
+ [Newtonsoft.Json.JsonProperty("end_time")]
+ [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RFC3339DateTimeOffsetConverter))]
+ [System.Text.Json.Serialization.JsonPropertyName("end_time")]
+ [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RFC3339DateTimeOffsetConverter))]
+ public DateTimeOffset EndTime { get; set; }
+
+ ///
+ /// 获取或设置通道类型。
+ ///
+ [Newtonsoft.Json.JsonProperty("channel_type")]
+ [System.Text.Json.Serialization.JsonPropertyName("channel_type")]
+ public string ChannelType { get; set; } = string.Empty;
+
+ ///
+ /// 获取或设置车辆类型。
+ ///
+ [Newtonsoft.Json.JsonProperty("car_type")]
+ [System.Text.Json.Serialization.JsonPropertyName("car_type")]
+ public string CarType { get; set; } = string.Empty;
+
+ ///
+ /// 获取或设置入口名称。
+ ///
+ [Newtonsoft.Json.JsonProperty("entrance")]
+ [System.Text.Json.Serialization.JsonPropertyName("entrance")]
+ public string? Entrance { get; set; }
+
+ ///
+ /// 获取或设置出口名称。
+ ///
+ [Newtonsoft.Json.JsonProperty("exit")]
+ [System.Text.Json.Serialization.JsonPropertyName("exit")]
+ public string? Exit { get; set; }
+
+ ///
+ /// 获取或设置承载人数。
+ ///
+ [Newtonsoft.Json.JsonProperty("carrying_capacity")]
+ [System.Text.Json.Serialization.JsonPropertyName("carrying_capacity")]
+ public int? CarryingCapacity { get; set; }
+
+ ///
+ /// 获取或设置荷载范围字符串。
+ ///
+ [Newtonsoft.Json.JsonProperty("carrying_range")]
+ [System.Text.Json.Serialization.JsonPropertyName("carrying_range")]
+ public string? CarryingRangeString { get; set; }
+ }
+
+ public class Device
+ {
+ ///
+ /// 获取或设置商户端设备号。
+ ///
+ [Newtonsoft.Json.JsonProperty("device_id")]
+ [System.Text.Json.Serialization.JsonPropertyName("device_id")]
+ public string? DeviceId { get; set; }
+
+ ///
+ /// 获取或设置商户端设备 IP。
+ ///
+ [Newtonsoft.Json.JsonProperty("device_ip")]
+ [System.Text.Json.Serialization.JsonPropertyName("device_ip")]
+ public string? DeviceIp { get; set; }
+ }
+ }
+
+ ///
+ /// 获取或设置子商户号。
+ ///
+ [Newtonsoft.Json.JsonProperty("sub_mchid")]
+ [System.Text.Json.Serialization.JsonPropertyName("sub_mchid")]
+ public string? SubMerchantId { get; set; }
+
+ ///
+ /// 获取或设置服务商 AppId。
+ ///
+ [Newtonsoft.Json.JsonProperty("appid")]
+ [System.Text.Json.Serialization.JsonPropertyName("appid")]
+ public string AppId { get; set; } = string.Empty;
+
+ ///
+ /// 获取或设置子商户 AppId。
+ ///
+ [Newtonsoft.Json.JsonProperty("sub_appid")]
+ [System.Text.Json.Serialization.JsonPropertyName("sub_appid")]
+ public string? SubAppId { get; set; }
+
+ ///
+ /// 获取或设置商户订单号。
+ ///
+ [Newtonsoft.Json.JsonProperty("out_trade_no")]
+ [System.Text.Json.Serialization.JsonPropertyName("out_trade_no")]
+ public string OutTradeNumber { get; set; } = string.Empty;
+
+ ///
+ /// 获取或设置 ETC 扣费授权协议号。
+ ///
+ [Newtonsoft.Json.JsonProperty("contract_id")]
+ [System.Text.Json.Serialization.JsonPropertyName("contract_id")]
+ public string ContractId { get; set; } = string.Empty;
+
+ ///
+ /// 获取或设置商品信息。
+ ///
+ [Newtonsoft.Json.JsonProperty("description")]
+ [System.Text.Json.Serialization.JsonPropertyName("description")]
+ public string Description { get; set; } = string.Empty;
+
+ ///
+ /// 获取或设置附加信息。
+ ///
+ [Newtonsoft.Json.JsonProperty("attach")]
+ [System.Text.Json.Serialization.JsonPropertyName("attach")]
+ public string? Attachment { get; set; }
+
+ ///
+ /// 获取或设置订单优惠标记。
+ ///
+ [Newtonsoft.Json.JsonProperty("goods_tag")]
+ [System.Text.Json.Serialization.JsonPropertyName("goods_tag")]
+ public string? GoodsTag { get; set; }
+
+ ///
+ /// 获取或设置金额信息。
+ ///
+ [Newtonsoft.Json.JsonProperty("amount")]
+ [System.Text.Json.Serialization.JsonPropertyName("amount")]
+ public Types.Amount Amount { get; set; } = new Types.Amount();
+
+ ///
+ /// 获取或设置高速信息。
+ ///
+ [Newtonsoft.Json.JsonProperty("highway_info")]
+ [System.Text.Json.Serialization.JsonPropertyName("highway_info")]
+ public Types.Highway Highway { get; set; } = new Types.Highway();
+
+ ///
+ /// 获取或设置设备信息。
+ ///
+ [Newtonsoft.Json.JsonProperty("device_info")]
+ [System.Text.Json.Serialization.JsonPropertyName("device_info")]
+ public Types.Device? Device { get; set; }
+ }
+}
diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Vehicle/ETC/CreateVehicleETCTransactionHighwayResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Vehicle/ETC/CreateVehicleETCTransactionHighwayResponse.cs
new file mode 100644
index 00000000..a56ece9f
--- /dev/null
+++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Vehicle/ETC/CreateVehicleETCTransactionHighwayResponse.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
+{
+ ///
+ /// 表示 [POST] /vehicle/etc/transactions/highway 接口的响应。
+ ///
+ public class CreateVehicleETCTransactionHighwayResponse : GetVehicleETCTransactionByOutTradeNumberResponse
+ {
+ }
+}
diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Vehicle/ETC/GetVehicleETCContractByContractIdRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Vehicle/ETC/GetVehicleETCContractByContractIdRequest.cs
new file mode 100644
index 00000000..3fcf7574
--- /dev/null
+++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Vehicle/ETC/GetVehicleETCContractByContractIdRequest.cs
@@ -0,0 +1,22 @@
+namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
+{
+ ///
+ /// 表示 [GET] /vehicle/etc/contracts/{contract_id} 接口的请求。
+ ///
+ public class GetVehicleETCContractByContractIdRequest : WechatTenpayRequest
+ {
+ ///
+ /// 获取或设置子商户号。
+ ///
+ [Newtonsoft.Json.JsonIgnore]
+ [System.Text.Json.Serialization.JsonIgnore]
+ public string? SubMerchantId { get; set; }
+
+ ///
+ /// 获取或设置 ETC 扣费授权协议号。
+ ///
+ [Newtonsoft.Json.JsonIgnore]
+ [System.Text.Json.Serialization.JsonIgnore]
+ public string ContractId { get; set; } = string.Empty;
+ }
+}
diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Vehicle/ETC/GetVehicleETCContractByContractIdResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Vehicle/ETC/GetVehicleETCContractByContractIdResponse.cs
new file mode 100644
index 00000000..3741850a
--- /dev/null
+++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Vehicle/ETC/GetVehicleETCContractByContractIdResponse.cs
@@ -0,0 +1,9 @@
+namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
+{
+ ///
+ /// 表示 [GET] /vehicle/etc/contracts/{contract_id} 接口的响应。
+ ///
+ public class GetVehicleETCContractByContractIdResponse : GetVehicleETCContractByOpenIdResponse
+ {
+ }
+}
diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Vehicle/ETC/GetVehicleETCContractByOpenIdRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Vehicle/ETC/GetVehicleETCContractByOpenIdRequest.cs
new file mode 100644
index 00000000..1bffba37
--- /dev/null
+++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Vehicle/ETC/GetVehicleETCContractByOpenIdRequest.cs
@@ -0,0 +1,36 @@
+namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
+{
+ ///
+ /// 表示 [GET] /vehicle/etc/users/{openid}/contracts 接口的请求。
+ ///
+ public class GetVehicleETCContractByOpenIdRequest : WechatTenpayRequest
+ {
+ ///
+ /// 获取或设置子商户号。
+ ///
+ [Newtonsoft.Json.JsonIgnore]
+ [System.Text.Json.Serialization.JsonIgnore]
+ public string? SubMerchantId { get; set; }
+
+ ///
+ /// 获取或设置用户唯一标识。
+ ///
+ [Newtonsoft.Json.JsonIgnore]
+ [System.Text.Json.Serialization.JsonIgnore]
+ public string OpenId { get; set; } = string.Empty;
+
+ ///
+ /// 获取或设置 ETC 授权扣费模板 ID。
+ ///
+ [Newtonsoft.Json.JsonIgnore]
+ [System.Text.Json.Serialization.JsonIgnore]
+ public string PlanId { get; set; } = string.Empty;
+
+ ///
+ /// 获取或设置车牌号。
+ ///
+ [Newtonsoft.Json.JsonIgnore]
+ [System.Text.Json.Serialization.JsonIgnore]
+ public string PlateNumber { get; set; } = string.Empty;
+ }
+}
diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Vehicle/ETC/GetVehicleETCContractByOpenIdResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Vehicle/ETC/GetVehicleETCContractByOpenIdResponse.cs
new file mode 100644
index 00000000..6a333c4f
--- /dev/null
+++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Vehicle/ETC/GetVehicleETCContractByOpenIdResponse.cs
@@ -0,0 +1,71 @@
+namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
+{
+ ///
+ /// 表示 [GET] /vehicle/etc/users/{openid}/contracts 接口的响应。
+ ///
+ public class GetVehicleETCContractByOpenIdResponse : WechatTenpayResponse
+ {
+ ///
+ /// 获取或设置微信商户号。
+ ///
+ [Newtonsoft.Json.JsonProperty("sp_mchid")]
+ [System.Text.Json.Serialization.JsonPropertyName("sp_mchid")]
+ public string MerchantId { get; set; } = default!;
+
+ ///
+ /// 获取或设置子商户号。
+ ///
+ [Newtonsoft.Json.JsonProperty("sub_mchid")]
+ [System.Text.Json.Serialization.JsonPropertyName("sub_mchid")]
+ public string? SubMerchantId { get; set; }
+
+ ///
+ /// 获取或设置微信 AppId。
+ ///
+ [Newtonsoft.Json.JsonProperty("appid")]
+ [System.Text.Json.Serialization.JsonPropertyName("appid")]
+ public string AppId { get; set; } = default!;
+
+ ///
+ /// 获取或设置子商户 AppId。
+ ///
+ [Newtonsoft.Json.JsonProperty("sub_appid")]
+ [System.Text.Json.Serialization.JsonPropertyName("sub_appid")]
+ public string? SubAppId { get; set; }
+
+ ///
+ /// 获取或设置用户唯一标识。
+ ///
+ [Newtonsoft.Json.JsonProperty("sp_openid")]
+ [System.Text.Json.Serialization.JsonPropertyName("sp_openid")]
+ public string? OpenId { get; set; }
+
+ ///
+ /// 获取或设置用户在子商户下的唯一标识。
+ ///
+ [Newtonsoft.Json.JsonProperty("sub_openid")]
+ [System.Text.Json.Serialization.JsonPropertyName("sub_openid")]
+ public string? SubOpenId { get; set; }
+
+ ///
+ /// 获取或设置 ETC 扣费授权协议号。
+ ///
+ [Newtonsoft.Json.JsonProperty("contract_id")]
+ [System.Text.Json.Serialization.JsonPropertyName("contract_id")]
+ public string ContractId { get; set; } = default!;
+
+ ///
+ /// 获取或设置车牌号。
+ ///
+ [Newtonsoft.Json.JsonProperty("plate_number")]
+ [System.Text.Json.Serialization.JsonPropertyName("plate_number")]
+ public string PlateNumber { get; set; } = default!;
+
+ ///
+ /// 获取或设置绑定状态。
+ ///
+ [Newtonsoft.Json.JsonProperty("bind_state")]
+ [System.Text.Json.Serialization.JsonPropertyName("bind_state")]
+ public string BindState { get; set; } = default!;
+ }
+}
diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Vehicle/ETC/GetVehicleETCTransactionByOutTradeNumberRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Vehicle/ETC/GetVehicleETCTransactionByOutTradeNumberRequest.cs
new file mode 100644
index 00000000..1f78c672
--- /dev/null
+++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Vehicle/ETC/GetVehicleETCTransactionByOutTradeNumberRequest.cs
@@ -0,0 +1,22 @@
+namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
+{
+ ///
+ /// 表示 [GET] /vehicle/etc/transactions/out-trade-no/{out_trade_no} 接口的请求。
+ ///
+ public class GetVehicleETCTransactionByOutTradeNumberRequest : WechatTenpayRequest
+ {
+ ///
+ /// 获取或设置商户订单号。
+ ///
+ [Newtonsoft.Json.JsonIgnore]
+ [System.Text.Json.Serialization.JsonIgnore]
+ public string OutTradeNumber { get; set; } = string.Empty;
+
+ ///
+ /// 获取或设置子商户号。
+ ///
+ [Newtonsoft.Json.JsonIgnore]
+ [System.Text.Json.Serialization.JsonIgnore]
+ public string? SubMerchantId { get; set; }
+ }
+}
diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Vehicle/ETC/GetVehicleETCTransactionByOutTradeNumberResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Vehicle/ETC/GetVehicleETCTransactionByOutTradeNumberResponse.cs
new file mode 100644
index 00000000..fb2538ec
--- /dev/null
+++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Vehicle/ETC/GetVehicleETCTransactionByOutTradeNumberResponse.cs
@@ -0,0 +1,218 @@
+using System;
+
+namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
+{
+ ///
+ /// 表示 [GET] /vehicle/etc/transactions/out-trade-no/{out_trade_no} 接口的响应。
+ ///
+ public class GetVehicleETCTransactionByOutTradeNumberResponse : WechatTenpayResponse
+ {
+ public static class Types
+ {
+ public class Payer : GetVehicleTransactionByOutTradeNumberResponse.Types.Payer
+ {
+ }
+
+ public class Amount : GetVehicleTransactionByOutTradeNumberResponse.Types.Amount
+ {
+ }
+
+ public class Device
+ {
+ ///
+ /// 获取或设置商户端设备号。
+ ///
+ [Newtonsoft.Json.JsonProperty("device_id")]
+ [System.Text.Json.Serialization.JsonPropertyName("device_id")]
+ public string? DeviceId { get; set; }
+
+ ///
+ /// 获取或设置商户端设备 IP。
+ ///
+ [Newtonsoft.Json.JsonProperty("device_ip")]
+ [System.Text.Json.Serialization.JsonPropertyName("device_ip")]
+ public string? DeviceIp { get; set; }
+ }
+
+ public class Promotion
+ {
+ ///
+ /// 获取或设置券 ID。
+ ///
+ [Newtonsoft.Json.JsonProperty("promotion_id")]
+ [System.Text.Json.Serialization.JsonPropertyName("promotion_id")]
+ public string PromotionId { get; set; } = default!;
+
+ ///
+ /// 获取或设置优惠名称。
+ ///
+ [Newtonsoft.Json.JsonProperty("name")]
+ [System.Text.Json.Serialization.JsonPropertyName("name")]
+ public string? Name { get; set; }
+
+ ///
+ /// 获取或设置优惠范围。
+ ///
+ [Newtonsoft.Json.JsonProperty("scope")]
+ [System.Text.Json.Serialization.JsonPropertyName("scope")]
+ public string? Scope { get; set; }
+
+ ///
+ /// 获取或设置优惠类型。
+ ///
+ [Newtonsoft.Json.JsonProperty("type")]
+ [System.Text.Json.Serialization.JsonPropertyName("type")]
+ public string? Type { get; set; }
+
+ ///
+ /// 获取或设置优惠券面额(单位:分)。
+ ///
+ [Newtonsoft.Json.JsonProperty("amount")]
+ [System.Text.Json.Serialization.JsonPropertyName("amount")]
+ public int Amount { get; set; }
+
+ ///
+ /// 获取或设置活动 ID。
+ ///
+ [Newtonsoft.Json.JsonProperty("activity_id")]
+ [System.Text.Json.Serialization.JsonPropertyName("activity_id")]
+ public string? ActivityId { get; set; }
+
+ ///
+ /// 获取或设置微信出资(单位:分)。
+ ///
+ [Newtonsoft.Json.JsonProperty("wxpay_contribute")]
+ [System.Text.Json.Serialization.JsonPropertyName("wxpay_contribute")]
+ public int? WechatpayContribute { get; set; }
+
+ ///
+ /// 获取或设置商户出资(单位:分)。
+ ///
+ [Newtonsoft.Json.JsonProperty("merchant_contribute")]
+ [System.Text.Json.Serialization.JsonPropertyName("merchant_contribute")]
+ public int? MerchantContribute { get; set; }
+
+ ///
+ /// 获取或设置其他出资(单位:分)。
+ ///
+ [Newtonsoft.Json.JsonProperty("other_contribute")]
+ [System.Text.Json.Serialization.JsonPropertyName("other_contribute")]
+ public int? OtherContribute { get; set; }
+ }
+ }
+
+ ///
+ /// 获取或设置微信商户号。
+ ///
+ [Newtonsoft.Json.JsonProperty("mchid")]
+ [System.Text.Json.Serialization.JsonPropertyName("mchid")]
+ public string MerchantId { get; set; } = default!;
+
+ ///
+ /// 获取或设置子商户号。
+ ///
+ [Newtonsoft.Json.JsonProperty("sub_mchid")]
+ [System.Text.Json.Serialization.JsonPropertyName("sub_mchid")]
+ public string? SubMerchantId { get; set; }
+
+ ///
+ /// 获取或设置微信 AppId。
+ ///
+ [Newtonsoft.Json.JsonProperty("appid")]
+ [System.Text.Json.Serialization.JsonPropertyName("appid")]
+ public string AppId { get; set; } = default!;
+
+ ///
+ /// 获取或设置子商户 AppId。
+ ///
+ [Newtonsoft.Json.JsonProperty("sub_appid")]
+ [System.Text.Json.Serialization.JsonPropertyName("sub_appid")]
+ public string? SubAppId { get; set; }
+
+ ///
+ /// 获取或设置商户订单号。
+ ///
+ [Newtonsoft.Json.JsonProperty("out_trade_no")]
+ [System.Text.Json.Serialization.JsonPropertyName("out_trade_no")]
+ public string OutTradeNumber { get; set; } = default!;
+
+ ///
+ /// 获取或设置微信支付订单号。
+ ///
+ [Newtonsoft.Json.JsonProperty("transaction_id")]
+ [System.Text.Json.Serialization.JsonPropertyName("transaction_id")]
+ public string? TransactionId { get; set; }
+
+ ///
+ /// 获取或设置交易类型。
+ ///
+ [Newtonsoft.Json.JsonProperty("trade_type")]
+ [System.Text.Json.Serialization.JsonPropertyName("trade_type")]
+ public string TradeType { get; set; } = default!;
+
+ ///
+ /// 获取或设置交易状态。
+ ///
+ [Newtonsoft.Json.JsonProperty("trade_state")]
+ [System.Text.Json.Serialization.JsonPropertyName("trade_state")]
+ public string TradeState { get; set; } = default!;
+
+ ///
+ /// 获取或设置交易状态描述。
+ ///
+ [Newtonsoft.Json.JsonProperty("trade_state_desc")]
+ [System.Text.Json.Serialization.JsonPropertyName("trade_state_desc")]
+ public string TradeStateDescription { get; set; } = default!;
+
+ ///
+ /// 获取或设置付款银行类型。
+ ///
+ [Newtonsoft.Json.JsonProperty("bank_type")]
+ [System.Text.Json.Serialization.JsonPropertyName("bank_type")]
+ public string? BankType { get; set; }
+
+ ///
+ /// 获取或设置附加数据。
+ ///
+ [Newtonsoft.Json.JsonProperty("attach")]
+ [System.Text.Json.Serialization.JsonPropertyName("attach")]
+ public string? Attachment { get; set; }
+
+ ///
+ /// 获取或设置支付完成时间。
+ ///
+ [Newtonsoft.Json.JsonProperty("success_time")]
+ [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RFC3339NullableDateTimeOffsetConverter))]
+ [System.Text.Json.Serialization.JsonPropertyName("success_time")]
+ [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RFC3339NullableDateTimeOffsetConverter))]
+ public DateTimeOffset? SuccessTime { get; set; }
+
+ ///
+ /// 获取或设置支付者信息。
+ ///
+ [Newtonsoft.Json.JsonProperty("payer")]
+ [System.Text.Json.Serialization.JsonPropertyName("payer")]
+ public Types.Payer? Payer { get; set; }
+
+ ///
+ /// 获取或设置金额信息。
+ ///
+ [Newtonsoft.Json.JsonProperty("amount")]
+ [System.Text.Json.Serialization.JsonPropertyName("amount")]
+ public Types.Amount Amount { get; set; } = default!;
+
+ ///
+ /// 获取或设置设备信息。
+ ///
+ [Newtonsoft.Json.JsonProperty("device_info")]
+ [System.Text.Json.Serialization.JsonPropertyName("device_info")]
+ public Types.Device? Device { get; set; }
+
+ ///
+ /// 获取或设置优惠信息。
+ ///
+ [Newtonsoft.Json.JsonProperty("promotion_detail")]
+ [System.Text.Json.Serialization.JsonPropertyName("promotion_detail")]
+ public Types.Promotion[]? PromotionList { get; set; }
+ }
+}
diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Vehicle/ETC/GetVehicleETCTransactionByTransactionIdRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Vehicle/ETC/GetVehicleETCTransactionByTransactionIdRequest.cs
new file mode 100644
index 00000000..c0c2bba6
--- /dev/null
+++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Vehicle/ETC/GetVehicleETCTransactionByTransactionIdRequest.cs
@@ -0,0 +1,22 @@
+namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
+{
+ ///
+ /// 表示 [GET] /vehicle/etc/transactions/id/{transaction_id} 接口的请求。
+ ///
+ public class GetVehicleETCTransactionByTransactionIdRequest : WechatTenpayRequest
+ {
+ ///
+ /// 获取或设置微信支付订单号。
+ ///
+ [Newtonsoft.Json.JsonIgnore]
+ [System.Text.Json.Serialization.JsonIgnore]
+ public string TransactionId { get; set; } = string.Empty;
+
+ ///
+ /// 获取或设置子商户号。
+ ///
+ [Newtonsoft.Json.JsonIgnore]
+ [System.Text.Json.Serialization.JsonIgnore]
+ public string? SubMerchantId { get; set; }
+ }
+}
diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Vehicle/ETC/GetVehicleETCTransactionByTransactionIdResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Vehicle/ETC/GetVehicleETCTransactionByTransactionIdResponse.cs
new file mode 100644
index 00000000..653cdaae
--- /dev/null
+++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Vehicle/ETC/GetVehicleETCTransactionByTransactionIdResponse.cs
@@ -0,0 +1,9 @@
+namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
+{
+ ///
+ /// 表示 [GET] /vehicle/etc/transactions/id/{transaction_id} 接口的响应。
+ ///
+ public class GetVehicleETCTransactionByTransactionIdResponse : GetVehicleETCTransactionByOutTradeNumberResponse
+ {
+ }
+}
diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Vehicle/ETC/PreopenVehicleETCRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Vehicle/ETC/PreopenVehicleETCRequest.cs
new file mode 100644
index 00000000..fc858740
--- /dev/null
+++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Vehicle/ETC/PreopenVehicleETCRequest.cs
@@ -0,0 +1,116 @@
+using System;
+
+namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
+{
+ ///
+ /// 表示 [POST] /vehicle/etc/preopen 接口的请求。
+ ///
+ [WechatTenpaySensitive]
+ public class PreopenVehicleETCRequest : WechatTenpayRequest
+ {
+ public static class Types
+ {
+ public class Identify
+ {
+ ///
+ /// 获取或设置真实姓名(需使用平台公钥/证书加密)。
+ ///
+ [Newtonsoft.Json.JsonProperty("encrypted_real_name")]
+ [System.Text.Json.Serialization.JsonPropertyName("encrypted_real_name")]
+ [WechatTenpaySensitiveProperty(scheme: Constants.SignSchemes.WECHATPAY2_RSA_2048_WITH_SHA256, algorithm: Constants.EncryptionAlgorithms.RSA_2048_ECB_PKCS8_OAEP_WITH_SHA1_AND_MGF1)]
+ [WechatTenpaySensitiveProperty(scheme: Constants.SignSchemes.WECHATPAY2_SM2_WITH_SM3, algorithm: Constants.EncryptionAlgorithms.SM2_C1C3C2_ASN1)]
+ public string EncryptedRealName { get; set; } = string.Empty;
+
+ ///
+ /// 获取或设置证件号码(需使用平台公钥/证书加密)。
+ ///
+ [Newtonsoft.Json.JsonProperty("encrypted_credential_id")]
+ [System.Text.Json.Serialization.JsonPropertyName("encrypted_credential_id")]
+ [WechatTenpaySensitiveProperty(scheme: Constants.SignSchemes.WECHATPAY2_RSA_2048_WITH_SHA256, algorithm: Constants.EncryptionAlgorithms.RSA_2048_ECB_PKCS8_OAEP_WITH_SHA1_AND_MGF1)]
+ [WechatTenpaySensitiveProperty(scheme: Constants.SignSchemes.WECHATPAY2_SM2_WITH_SM3, algorithm: Constants.EncryptionAlgorithms.SM2_C1C3C2_ASN1)]
+ public string EncryptedCredentialNumber { get; set; } = string.Empty;
+
+ ///
+ /// 获取或设置证件类型。
+ ///
+ [Newtonsoft.Json.JsonProperty("credential_type")]
+ [System.Text.Json.Serialization.JsonPropertyName("credential_type")]
+ public string? CredentialType { get; set; }
+ }
+ }
+
+ ///
+ /// 获取或设置子商户号。
+ ///
+ [Newtonsoft.Json.JsonProperty("sub_mchid")]
+ [System.Text.Json.Serialization.JsonPropertyName("sub_mchid")]
+ public string? SubMerchantId { get; set; }
+
+ ///
+ /// 获取或设置服务商 AppId。
+ ///
+ [Newtonsoft.Json.JsonProperty("sp_appid")]
+ [System.Text.Json.Serialization.JsonPropertyName("sp_appid")]
+ public string AppId { get; set; } = string.Empty;
+
+ ///
+ /// 获取或设置子商户 AppId。
+ ///
+ [Newtonsoft.Json.JsonProperty("sub_appid")]
+ [System.Text.Json.Serialization.JsonPropertyName("sub_appid")]
+ public string? SubAppId { get; set; }
+
+ ///
+ /// 获取或设置用户唯一标识。
+ ///
+ [Newtonsoft.Json.JsonProperty("openid")]
+ [System.Text.Json.Serialization.JsonPropertyName("openid")]
+ public string OpenId { get; set; } = string.Empty;
+
+ ///
+ /// 获取或设置 ETC 授权扣费模板 ID。
+ ///
+ [Newtonsoft.Json.JsonProperty("plan_id")]
+ [System.Text.Json.Serialization.JsonPropertyName("plan_id")]
+ public string PlanId { get; set; } = string.Empty;
+
+ ///
+ /// 获取或设置 ETC 设备号。
+ ///
+ [Newtonsoft.Json.JsonProperty("etc_device_id")]
+ [System.Text.Json.Serialization.JsonPropertyName("etc_device_id")]
+ public string? DeviceId { get; set; }
+
+ ///
+ /// 获取或设置车牌号。
+ ///
+ [Newtonsoft.Json.JsonProperty("plate_number")]
+ [System.Text.Json.Serialization.JsonPropertyName("plate_number")]
+ public string PlateNumber { get; set; } = string.Empty;
+
+ ///
+ /// 获取或设置入场时间。
+ ///
+ [Newtonsoft.Json.JsonProperty("start_time")]
+ [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RFC3339DateTimeOffsetConverter))]
+ [System.Text.Json.Serialization.JsonPropertyName("start_time")]
+ [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RFC3339DateTimeOffsetConverter))]
+ public DateTimeOffset StartTime { get; set; }
+
+ ///
+ /// 获取或设置实名认证信息。
+ ///
+ [Newtonsoft.Json.JsonProperty("identify")]
+ [System.Text.Json.Serialization.JsonPropertyName("identify")]
+ public Types.Identify Identify { get; set; } = new Types.Identify();
+
+ ///
+ /// 获取或设置银行卡号(需使用平台公钥/证书加密)。
+ ///
+ [Newtonsoft.Json.JsonProperty("bank_card_no")]
+ [System.Text.Json.Serialization.JsonPropertyName("bank_card_no")]
+ [WechatTenpaySensitiveProperty(scheme: Constants.SignSchemes.WECHATPAY2_RSA_2048_WITH_SHA256, algorithm: Constants.EncryptionAlgorithms.RSA_2048_ECB_PKCS8_OAEP_WITH_SHA1_AND_MGF1)]
+ [WechatTenpaySensitiveProperty(scheme: Constants.SignSchemes.WECHATPAY2_SM2_WITH_SM3, algorithm: Constants.EncryptionAlgorithms.SM2_C1C3C2_ASN1)]
+ public string? BankCardNumber { get; set; }
+ }
+}
diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Vehicle/ETC/PreopenVehicleETCResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Vehicle/ETC/PreopenVehicleETCResponse.cs
new file mode 100644
index 00000000..4de8694c
--- /dev/null
+++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Vehicle/ETC/PreopenVehicleETCResponse.cs
@@ -0,0 +1,15 @@
+namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
+{
+ ///
+ /// 表示 [POST] /vehicle/etc/preopen 接口的响应。
+ ///
+ public class PreopenVehicleETCResponse : WechatTenpayResponse
+ {
+ ///
+ /// 获取或设置预开通 ID。
+ ///
+ [Newtonsoft.Json.JsonProperty("preopen_id")]
+ [System.Text.Json.Serialization.JsonPropertyName("preopen_id")]
+ public string PreopenId { get; set; } = default!;
+ }
+}
diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/SKIT.FlurlHttpClient.Wechat.TenpayV3.csproj b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/SKIT.FlurlHttpClient.Wechat.TenpayV3.csproj
index 24a528dd..89d43fc7 100644
--- a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/SKIT.FlurlHttpClient.Wechat.TenpayV3.csproj
+++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/SKIT.FlurlHttpClient.Wechat.TenpayV3.csproj
@@ -15,7 +15,7 @@
https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat
Flurl.Http Wechat Weixin MicroMessage Tenpay WechatPay WeixinPay Wxpay 微信 微信支付 微信商户
2.16.0
- 基于 Flurl.Http 的微信支付 API v3 版客户端,支持直连商户、服务商模式,支持基础支付、代金券、商家券、委托营销、消费卡、支付有礼、银行定向促活、微信支付分、微信先享卡、支付即服务、点金计划、智慧商圈、电商收付通、二级商户进件、小微商户进件、消费者投诉、商户违规通知、批量转账到零钱、银行组件、海关报关、融合钱包、微工卡、电子发票等功能。
+ 基于 Flurl.Http 的微信支付 API v3 版客户端,支持直连商户、服务商模式,支持基础支付、代金券、商家券、委托营销、消费卡、支付有礼、银行定向促活、微信支付分、微信先享卡、支付即服务、点金计划、智慧商圈、电商收付通、二级商户进件、小微商户进件、消费者投诉、商户违规通知、批量转账到零钱、银行组件、海关报关、融合钱包、微工卡、电子发票、ETC 扣费等功能。
Fu Diwei
git
https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat.git
diff --git a/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/EventSamples/Vehicle/VehicleETCTransactionResource.json b/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/EventSamples/Vehicle/VehicleETCTransactionResource.json
new file mode 100644
index 00000000..adddbc92
--- /dev/null
+++ b/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/EventSamples/Vehicle/VehicleETCTransactionResource.json
@@ -0,0 +1,9 @@
+{
+ "appid": "wxcbda96de0b165486",
+ "sp_mchid": "10000098",
+ "sp_openid": "onqOjjmM1tad-3ROpncN-yUfa6ua",
+ "sub_mchid": "1900000109",
+ "contract_id": "aAfixCs13LsdKPpfZfDkk2189ssXjfx",
+ "bind_state": "DELETED",
+ "plate_number": "浙ASB945"
+}
diff --git a/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/EventSamples/VehicleParking/VehicleEntranceStateChangeResource.json b/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/EventSamples/Vehicle/VehicleEntranceStateChangeResource.json
similarity index 100%
rename from test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/EventSamples/VehicleParking/VehicleEntranceStateChangeResource.json
rename to test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/EventSamples/Vehicle/VehicleEntranceStateChangeResource.json
diff --git a/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/EventSamples/VehicleParking/VehicleTransactionResource.json b/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/EventSamples/Vehicle/VehicleTransactionResource.json
similarity index 100%
rename from test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/EventSamples/VehicleParking/VehicleTransactionResource.json
rename to test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/EventSamples/Vehicle/VehicleTransactionResource.json
diff --git a/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/ModelSamples/Vehicle/ETC/CreateVehicleETCTransactionHighwayRequest.json b/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/ModelSamples/Vehicle/ETC/CreateVehicleETCTransactionHighwayRequest.json
new file mode 100644
index 00000000..2d2ab4bd
--- /dev/null
+++ b/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/ModelSamples/Vehicle/ETC/CreateVehicleETCTransactionHighwayRequest.json
@@ -0,0 +1,29 @@
+{
+ "out_trade_no": "121775250124070332",
+ "sub_mchid": "1900000109",
+ "appid": "wxd678efh567hg6787",
+ "sub_appid": "wxd678efh567hg6999",
+ "contract_id": "wxd678ef4Fwxd678ef4Fwxd678ef4F21",
+ "description": "商品信息",
+ "attach": "自定义数据",
+ "goods_tag": "test",
+ "highway_info": {
+ "plate_number": "粤B888888",
+ "start_time": "2017-08-26T09:43:39+08:00",
+ "end_time": "2017-08-26T09:43:39+08:00",
+ "channel_type": "ETC",
+ "car_type": "CAR",
+ "entrance": "沿江深圳-大铲湾",
+ "exit": "广珠东线-珠海站",
+ "carrying_capacity": 3,
+ "carrying_range": "6-12"
+ },
+ "amount": {
+ "total": 888,
+ "currency": "CNY"
+ },
+ "device_info": {
+ "device_id": "POS1:1",
+ "device_ip": "123.12.12.123"
+ }
+}
diff --git a/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/ModelSamples/Vehicle/ETC/CreateVehicleETCTransactionHighwayResponse.json b/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/ModelSamples/Vehicle/ETC/CreateVehicleETCTransactionHighwayResponse.json
new file mode 100644
index 00000000..2bceafd5
--- /dev/null
+++ b/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/ModelSamples/Vehicle/ETC/CreateVehicleETCTransactionHighwayResponse.json
@@ -0,0 +1,40 @@
+{
+ "mchid": "1230000109",
+ "sub_mchid": "1900000109",
+ "appid": "wxd678efh567hg6787",
+ "sub_appid": "wxd678efh567hg6999",
+ "out_trade_no": "121775250124070332",
+ "transaction_id": "25012014070332333018",
+ "attach": "自定义数据",
+ "trade_type": "AUTH",
+ "bank_type": "CMC",
+ "success_time": "2017-08-26T10:43:39+08:00",
+ "trade_state": "SUCCESS",
+ "trade_state_desc": "请重新下单支付",
+ "payer": {
+ "openid": "oUpF8uMuAJOM2pxb1Q"
+ },
+ "amount": {
+ "total": 888,
+ "currency": "CNY",
+ "payer_total": 888,
+ "discount_total": 100
+ },
+ "device_info": {
+ "device_id": "POS1:1",
+ "device_ip": "123.12.12.123"
+ },
+ "promotion_detail": [
+ {
+ "promotion_id": "109519",
+ "name": "单品惠-6",
+ "scope": "SINGLE",
+ "type": "DISCOUNT",
+ "activity_id": "931386",
+ "amount": 5,
+ "wxpay_contribute": 0,
+ "merchant_contribute": 0,
+ "other_contribute": 5
+ }
+ ]
+}
diff --git a/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/ModelSamples/Vehicle/ETC/GetVehicleETCContractByContractIdResponse.json b/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/ModelSamples/Vehicle/ETC/GetVehicleETCContractByContractIdResponse.json
new file mode 100644
index 00000000..adddbc92
--- /dev/null
+++ b/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/ModelSamples/Vehicle/ETC/GetVehicleETCContractByContractIdResponse.json
@@ -0,0 +1,9 @@
+{
+ "appid": "wxcbda96de0b165486",
+ "sp_mchid": "10000098",
+ "sp_openid": "onqOjjmM1tad-3ROpncN-yUfa6ua",
+ "sub_mchid": "1900000109",
+ "contract_id": "aAfixCs13LsdKPpfZfDkk2189ssXjfx",
+ "bind_state": "DELETED",
+ "plate_number": "浙ASB945"
+}
diff --git a/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/ModelSamples/Vehicle/ETC/GetVehicleETCContractByOpenIdResponse.json b/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/ModelSamples/Vehicle/ETC/GetVehicleETCContractByOpenIdResponse.json
new file mode 100644
index 00000000..adddbc92
--- /dev/null
+++ b/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/ModelSamples/Vehicle/ETC/GetVehicleETCContractByOpenIdResponse.json
@@ -0,0 +1,9 @@
+{
+ "appid": "wxcbda96de0b165486",
+ "sp_mchid": "10000098",
+ "sp_openid": "onqOjjmM1tad-3ROpncN-yUfa6ua",
+ "sub_mchid": "1900000109",
+ "contract_id": "aAfixCs13LsdKPpfZfDkk2189ssXjfx",
+ "bind_state": "DELETED",
+ "plate_number": "浙ASB945"
+}
diff --git a/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/ModelSamples/Vehicle/ETC/GetVehicleETCTransactionByOutTradeNumberResponse.json b/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/ModelSamples/Vehicle/ETC/GetVehicleETCTransactionByOutTradeNumberResponse.json
new file mode 100644
index 00000000..2bceafd5
--- /dev/null
+++ b/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/ModelSamples/Vehicle/ETC/GetVehicleETCTransactionByOutTradeNumberResponse.json
@@ -0,0 +1,40 @@
+{
+ "mchid": "1230000109",
+ "sub_mchid": "1900000109",
+ "appid": "wxd678efh567hg6787",
+ "sub_appid": "wxd678efh567hg6999",
+ "out_trade_no": "121775250124070332",
+ "transaction_id": "25012014070332333018",
+ "attach": "自定义数据",
+ "trade_type": "AUTH",
+ "bank_type": "CMC",
+ "success_time": "2017-08-26T10:43:39+08:00",
+ "trade_state": "SUCCESS",
+ "trade_state_desc": "请重新下单支付",
+ "payer": {
+ "openid": "oUpF8uMuAJOM2pxb1Q"
+ },
+ "amount": {
+ "total": 888,
+ "currency": "CNY",
+ "payer_total": 888,
+ "discount_total": 100
+ },
+ "device_info": {
+ "device_id": "POS1:1",
+ "device_ip": "123.12.12.123"
+ },
+ "promotion_detail": [
+ {
+ "promotion_id": "109519",
+ "name": "单品惠-6",
+ "scope": "SINGLE",
+ "type": "DISCOUNT",
+ "activity_id": "931386",
+ "amount": 5,
+ "wxpay_contribute": 0,
+ "merchant_contribute": 0,
+ "other_contribute": 5
+ }
+ ]
+}
diff --git a/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/ModelSamples/Vehicle/ETC/GetVehicleETCTransactionByTransactionIdResponse.json b/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/ModelSamples/Vehicle/ETC/GetVehicleETCTransactionByTransactionIdResponse.json
new file mode 100644
index 00000000..2bceafd5
--- /dev/null
+++ b/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/ModelSamples/Vehicle/ETC/GetVehicleETCTransactionByTransactionIdResponse.json
@@ -0,0 +1,40 @@
+{
+ "mchid": "1230000109",
+ "sub_mchid": "1900000109",
+ "appid": "wxd678efh567hg6787",
+ "sub_appid": "wxd678efh567hg6999",
+ "out_trade_no": "121775250124070332",
+ "transaction_id": "25012014070332333018",
+ "attach": "自定义数据",
+ "trade_type": "AUTH",
+ "bank_type": "CMC",
+ "success_time": "2017-08-26T10:43:39+08:00",
+ "trade_state": "SUCCESS",
+ "trade_state_desc": "请重新下单支付",
+ "payer": {
+ "openid": "oUpF8uMuAJOM2pxb1Q"
+ },
+ "amount": {
+ "total": 888,
+ "currency": "CNY",
+ "payer_total": 888,
+ "discount_total": 100
+ },
+ "device_info": {
+ "device_id": "POS1:1",
+ "device_ip": "123.12.12.123"
+ },
+ "promotion_detail": [
+ {
+ "promotion_id": "109519",
+ "name": "单品惠-6",
+ "scope": "SINGLE",
+ "type": "DISCOUNT",
+ "activity_id": "931386",
+ "amount": 5,
+ "wxpay_contribute": 0,
+ "merchant_contribute": 0,
+ "other_contribute": 5
+ }
+ ]
+}
diff --git a/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/ModelSamples/Vehicle/ETC/PreopenVehicleETCRequest.json b/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/ModelSamples/Vehicle/ETC/PreopenVehicleETCRequest.json
new file mode 100644
index 00000000..eefa77d0
--- /dev/null
+++ b/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/ModelSamples/Vehicle/ETC/PreopenVehicleETCRequest.json
@@ -0,0 +1,14 @@
+{
+ "sp_appid": "wx47c677487ce3ac47",
+ "sub_appid": "wxcc603d9f0d54eaf0",
+ "sub_mchid": "1510770601",
+ "openid": "ot35_4gNgXsUuh2sQY0lT9N08AU0",
+ "plan_id": "97619",
+ "etc_device_id": "xxxxxxx",
+ "plate_number": "藏ZZZZZZ",
+ "identify": {
+ "encrypted_real_name": "jUCOynVR0fvpLOX6jBeRlK/TErW6DqEM8JFHX4iL3Rlj2vqaEqktvw1KVjgmQ==",
+ "encrypted_credential_id": "l5CfRt85SAX3GxVYqGQm2Q8cfeFd1dWy40j4s7XpIds8Glw83HG3vN9Q==",
+ "credential_type": "ID_CARD"
+ }
+}
diff --git a/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/ModelSamples/Vehicle/ETC/PreopenVehicleETCResponse.json b/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/ModelSamples/Vehicle/ETC/PreopenVehicleETCResponse.json
new file mode 100644
index 00000000..84a142cc
--- /dev/null
+++ b/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/ModelSamples/Vehicle/ETC/PreopenVehicleETCResponse.json
@@ -0,0 +1,3 @@
+{
+ "preopen_id": "sdjf23kdsHJfdksj8djsK98HJio5hdI0"
+}
diff --git a/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/TestCase_RequestEncryptionTests.cs b/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/TestCase_RequestEncryptionTests.cs
index cbea80a2..1b895402 100644
--- a/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/TestCase_RequestEncryptionTests.cs
+++ b/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/TestCase_RequestEncryptionTests.cs
@@ -1073,6 +1073,50 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
await CreateMockClientUseSM2(autoEncrypt: true).ExecuteCreateTransferBatchAsync(reqB2);
AssertMockRequestModel(reqB2, (cipher) => Utilities.SM2Utility.Decrypt(SM2_PEM_PRIVATE_KEY, cipher));
}
+
+ [Fact(DisplayName = "测试用例:加密请求中的敏感数据([POST] /vehicle/etc/preopen)")]
+ public async Task TestEncryptRequestSensitiveProperty_PreopenVehicleETCRequest()
+ {
+ static Models.PreopenVehicleETCRequest GenerateMockRequestModel()
+ {
+ return new Models.PreopenVehicleETCRequest()
+ {
+ Identify = new Models.PreopenVehicleETCRequest.Types.Identify()
+ {
+ EncryptedRealName = MOCK_PLAIN_STR,
+ EncryptedCredentialNumber = MOCK_PLAIN_STR
+ },
+ BankCardNumber = MOCK_PLAIN_STR
+ };
+ }
+
+ static void AssertMockRequestModel(Models.PreopenVehicleETCRequest request, Func decryptor)
+ {
+ Assert.NotEqual(MOCK_PLAIN_STR, request.Identify!.EncryptedRealName!);
+ Assert.NotEqual(MOCK_PLAIN_STR, request.Identify!.EncryptedCredentialNumber!);
+ Assert.NotEqual(MOCK_PLAIN_STR, request.BankCardNumber!);
+ Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.Identify!.EncryptedRealName!));
+ Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.Identify!.EncryptedCredentialNumber!));
+ Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.BankCardNumber!));
+ Assert.Equal(MOCK_CERT_SN, request.WechatpayCertificateSerialNumber!, ignoreCase: true);
+ }
+
+ var reqA1 = GenerateMockRequestModel();
+ CreateMockClientUseRSA(autoEncrypt: false).EncryptRequestSensitiveProperty(reqA1);
+ AssertMockRequestModel(reqA1, (cipher) => Utilities.RSAUtility.DecryptWithECB(RSA_PEM_PRIVATE_KEY, cipher));
+
+ var reqA2 = GenerateMockRequestModel();
+ CreateMockClientUseSM2(autoEncrypt: false).EncryptRequestSensitiveProperty(reqA2);
+ AssertMockRequestModel(reqA2, (cipher) => Utilities.SM2Utility.Decrypt(SM2_PEM_PRIVATE_KEY, cipher));
+
+ var reqB1 = GenerateMockRequestModel();
+ await CreateMockClientUseRSA(autoEncrypt: true).ExecutePreopenVehicleETCAsync(reqB1);
+ AssertMockRequestModel(reqB1, (cipher) => Utilities.RSAUtility.DecryptWithECB(RSA_PEM_PRIVATE_KEY, cipher));
+
+ var reqB2 = GenerateMockRequestModel();
+ await CreateMockClientUseSM2(autoEncrypt: true).ExecutePreopenVehicleETCAsync(reqB2);
+ AssertMockRequestModel(reqB2, (cipher) => Utilities.SM2Utility.Decrypt(SM2_PEM_PRIVATE_KEY, cipher));
+ }
}
partial class TestCase_RequestEncryptionTests