feat(tenpayv3): 新增校园轻松付相关接口

This commit is contained in:
Fu Diwei 2023-04-10 15:33:55 +08:00
parent 4dd39db436
commit 3822f2b43f
38 changed files with 1345 additions and 70 deletions

View File

@ -46,13 +46,15 @@
| √ | 经营能力:点金计划 | 服务商 | |
| √ | 经营能力:区块链电子发票 | 直连商户 | |
| √ | 经营能力:出租车电子发票 | 服务商 | |
| √ | 经营能力:微信支付分停车服务 | 直连商户 & 服务商 | |
| √ | 经营能力:租用充电宝隔夜归还 | 直连商户 | |
| √ | 经营能力ETC 扣费 | 服务商 | |
| √ | 经营能力:教育续费通 | 直连商户 | |
| √ | 经营能力:校园轻松付 | 服务商 | |
| √ | 行业方案:电商收付通 | 服务商 | |
| √ | 行业方案:智慧商圈 | 直连商户 & 服务商 | |
| √ | 行业方案:微信支付分停车服务 | 直连商户 & 服务商 | |
| √ | 行业方案:租用充电宝隔夜归还 | 直连商户 | |
| √ | 行业方案:微信点餐订单 | 服务商 | |
| √ | 行业方案:微信寄快递 | 服务商 | |
| √ | 行业方案ETC 扣费 | 服务商 | |
| √ | 营销工具:代金券 | 直连商户 & 服务商 | |
| √ | 营销工具:商家券 | 直连商户 & 服务商 | |
| √ | 营销工具:委托营销 | 直连商户 & 服务商 | |
@ -75,7 +77,6 @@
| √ | 其他能力:图片上传 | 直连商户 & 服务商 | |
| √ | 其他能力:视频上传 | 直连商户 & 服务商 | |
| √ | 其他能力:优惠费率活动 | 服务商 | |
| √ | 其他能力:校园续费通 | 直连商户 | |
| √ | 境外支付:子商户进件 | 服务商 | |
| √ | 境外支付:融合钱包 | 服务商 | |
| √ | 境外支付:委托代扣 | 直连商户 & 服务商 | |
@ -275,6 +276,34 @@
- 预扣费通知:`NotifyPAPPayContract`
- 微信支付分停车服务
- 查询车牌服务开通信息:`GetVehicleParkingService`
- 创建停车入场:`CreateVehicleParking`
- 扣费受理:`CreateVehicleTransactionParking`
- 查询订单:`GetVehicleTransactionByOutTradeNumber`
- 教育续费通:
- 预签约:`PresignEducationPAPPayContract`
- 通过协议号查询签约:`GetEducationPAPPayContractByContractId`
- 通过用户标识查询签约:`QueryEducationPAPPayUserContracts`
- 解约:`TerminateEducationPAPPayContract`
- 发送扣款预通知:`SendEducationPAPPayContractNotification`
- 教育通扣款受理:`CreateEducationPAPPayTransaction`
- 微信订单号查单:`GetEducationPAPPayTransactionById`
- 商户订单号查单:`GetEducationPAPPayTransactionByOutTradeNumber`
- 行业方案
- 智慧商圈
@ -287,16 +316,6 @@
- 商圈会员停车状态同步:`NotifyBusinessCircleParkings`
- 微信支付分停车服务
- 查询车牌服务开通信息:`GetVehicleParkingService`
- 创建停车入场:`CreateVehicleParking`
- 扣费受理:`CreateVehicleTransactionParking`
- 查询订单:`GetVehicleTransactionByOutTradeNumber`
- 营销工具
- 代金券
@ -505,24 +524,6 @@
- 查询支行列表:`QueryCapitalBanksBranches`
- 校园续费通:
- 预签约:`PresignEducationPAPPayContract`
- 通过协议号查询签约:`GetEducationPAPPayContractByContractId`
- 通过用户标识查询签约:`QueryEducationPAPPayUserContracts`
- 解约:`TerminateEducationPAPPayContract`
- 发送扣款预通知:`SendEducationPAPPayContractNotification`
- 教育通扣款受理:`CreateEducationPAPPayTransaction`
- 微信订单号查单:`GetEducationPAPPayTransactionById`
- 商户订单号查单:`GetEducationPAPPayTransactionByOutTradeNumber`
</details>
---
@ -741,6 +742,34 @@
- 预扣费通知:`NotifyPartnerPAPPayContract`
- 微信支付分停车服务
- 查询车牌服务开通信息:`GetVehicleParkingService`
- 创建停车入场:`CreateVehicleParking`
- 扣费受理:`CreateVehicleTransactionParking`
- 查询订单:`GetVehicleTransactionByOutTradeNumber`
- 校园轻松付:
- 预签约:`PresignEducationSchoolPayContract`
- 通过协议号查询签约:`GetEducationSchoolPayContractByContractId`
- 商户主动解约:`TerminateEducationSchoolPayContract`
- 查询用户签约列表:`QueryEducationSchoolPayUserContracts`
- 扣款:`CreateEducationSchoolPayTransaction`
- 微信支付订单号查单:`GetEducationSchoolPayTransactionById`
- 商户订单号查单:`GetEducationSchoolPayTransactionByOutTradeNumber`
- 商户查询用户欠款状态:`GetEducationSchoolPayUserDebtState`
- 行业方案
- 电商收付通(商户进件)
@ -891,16 +920,6 @@
- 商圈会员停车状态同步:`NotifyBusinessCircleParkings`
- 微信支付分停车服务
- 查询车牌服务开通信息:`GetVehicleParkingService`
- 创建停车入场:`CreateVehicleParking`
- 扣费受理:`CreateVehicleTransactionParking`
- 查询订单:`GetVehicleTransactionByOutTradeNumber`
- 营销工具
- 代金券

View File

@ -0,0 +1,177 @@
using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Flurl.Http;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
{
public static class WechatTenpayClientExecuteEducationSchoolPayExtensions
{
/// <summary>
/// <para>异步调用 [POST] /eduschoolpay/contracts/presign 接口。</para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter5_3_1.shtml </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.PresignEducationSchoolPayContractResponse> ExecutePresignEducationSchoolPayContractAsync(this WechatTenpayClient client, Models.PresignEducationSchoolPayContractRequest 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, "eduschoolpay", "contracts", "presign");
return await client.SendRequestWithJsonAsync<Models.PresignEducationSchoolPayContractResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
}
/// <summary>
/// <para>异步调用 [GET] /eduschoolpay/contracts/{contract_id} 接口。</para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter5_3_2.shtml </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.GetEducationSchoolPayContractByContractIdResponse> ExecuteGetEducationSchoolPayContractByContractIdAsync(this WechatTenpayClient client, Models.GetEducationSchoolPayContractByContractIdRequest 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, "eduschoolpay", "contracts", request.ContractId);
return await client.SendRequestWithJsonAsync<Models.GetEducationSchoolPayContractByContractIdResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
}
/// <summary>
/// <para>异步调用 [GET] /eduschoolpay/users/{openid}/contracts 接口。</para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter5_3_4.shtml </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.QueryEducationSchoolPayUserContractsResponse> ExecuteQueryEducationSchoolPayUserContractsAsync(this WechatTenpayClient client, Models.QueryEducationSchoolPayUserContractsRequest 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, "eduschoolpay", "users", request.OpenId, "contracts")
.SetQueryParam("plan_id", request.PlanId)
.SetQueryParam("contract_status", request.ContractStatus); ;
if (request.Limit != null)
flurlReq.SetQueryParam("limit", request.Limit.Value);
if (request.Offset != null)
flurlReq.SetQueryParam("offset", request.Offset.Value);
return await client.SendRequestWithJsonAsync<Models.QueryEducationSchoolPayUserContractsResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
}
/// <summary>
/// <para>异步调用 [POST] /eduschoolpay/contracts/{contract_id}/terminate 接口。</para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter5_3_3.shtml </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.TerminateEducationSchoolPayContractResponse> ExecuteTerminateEducationSchoolPayContractAsync(this WechatTenpayClient client, Models.TerminateEducationSchoolPayContractRequest 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, "eduschoolpay", "contracts", request.ContractId, "terminate");
return await client.SendRequestWithJsonAsync<Models.TerminateEducationSchoolPayContractResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
}
/// <summary>
/// <para>异步调用 [POST] /eduschoolpay/transactions 接口。</para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter5_3_6.shtml </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.CreateEducationSchoolPayTransactionResponse> ExecuteCreateEducationSchoolPayTransactionAsync(this WechatTenpayClient client, Models.CreateEducationSchoolPayTransactionRequest 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, "eduschoolpay", "transactions");
return await client.SendRequestWithJsonAsync<Models.CreateEducationSchoolPayTransactionResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
}
/// <summary>
/// <para>异步调用 [GET] /eduschoolpay/transactions/out-trade-no/{out_trade_no} 接口。</para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter5_3_8.shtml </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.GetEducationSchoolPayTransactionByOutTradeNumberResponse> ExecuteGetEducationSchoolPayTransactionByOutTradeNumberAsync(this WechatTenpayClient client, Models.GetEducationSchoolPayTransactionByOutTradeNumberRequest 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, "eduschoolpay", "transactions", "out-trade-no", request.OutTradeNumber);
if (request.SubMerchantId != null)
flurlReq.SetQueryParam("sub_mchid", request.SubMerchantId);
return await client.SendRequestWithJsonAsync<Models.GetEducationSchoolPayTransactionByOutTradeNumberResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
}
/// <summary>
/// <para>异步调用 [GET] /eduschoolpay/transactions/id/{transaction_id} 接口。</para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter5_3_7.shtml </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.GetEducationSchoolPayTransactionByIdResponse> ExecuteGetEducationSchoolPayTransactionByIdAsync(this WechatTenpayClient client, Models.GetEducationSchoolPayTransactionByIdRequest 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, "eduschoolpay", "transactions", "id", request.TransactionId);
if (request.SubMerchantId != null)
flurlReq.SetQueryParam("sub_mchid", request.SubMerchantId);
return await client.SendRequestWithJsonAsync<Models.GetEducationSchoolPayTransactionByIdResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
}
/// <summary>
/// <para>异步调用 [GET] /eduschoolpay/users/{openid}/debt-state 接口。</para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter5_3_9.shtml </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.GetEducationSchoolPayUserDebtStateResponse> ExecuteGetEducationSchoolPayUserDebtStateAsync(this WechatTenpayClient client, Models.GetEducationSchoolPayUserDebtStateRequest 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, "eduschoolpay", "users", request.OpenId, "debt-state");
return await client.SendRequestWithJsonAsync<Models.GetEducationSchoolPayUserDebtStateResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
}
}
}

View File

@ -1,5 +1,3 @@
using System.Collections.Generic;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
{
/// <summary>

View File

@ -29,10 +29,10 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// 获取或设置签约时间。
/// </summary>
[Newtonsoft.Json.JsonProperty("create_time")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RFC3339NullableDateTimeOffsetConverter))]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RFC3339DateTimeOffsetConverter))]
[System.Text.Json.Serialization.JsonPropertyName("create_time")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RFC3339NullableDateTimeOffsetConverter))]
public DateTimeOffset? CreateTime { get; set; }
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RFC3339DateTimeOffsetConverter))]
public DateTimeOffset CreateTime { get; set; }
}
}

View File

@ -31,7 +31,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary>
[Newtonsoft.Json.JsonProperty("user_id")]
[System.Text.Json.Serialization.JsonPropertyName("user_id")]
public string UserDisplayName { get; set; } = string.Empty;
public string UserDisplayId { get; set; } = string.Empty;
/// <summary>
/// 获取或设置首次扣款日期字符串格式yyyy-MM-dd

View File

@ -1,5 +1,3 @@
using System;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
{
/// <summary>

View File

@ -20,7 +20,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
[System.Text.Json.Serialization.JsonPropertyName("encrypted_phone_number")]
[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 EncryptedPhoneNumber { get; set; } = string.Empty;
public string MobileNumber { get; set; } = string.Empty;
/// <summary>
/// 获取或设置会员卡 Code。

View File

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models

View File

@ -19,7 +19,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
[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;
public string RealName { get; set; } = string.Empty;
/// <summary>
/// 获取或设置证件号码(需使用平台公钥/证书加密)。
@ -28,7 +28,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
[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;
public string CredentialNumber { get; set; } = string.Empty;
/// <summary>
/// 获取或设置证件类型。

View File

@ -32,7 +32,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// </summary>
[Newtonsoft.Json.JsonProperty("name")]
[System.Text.Json.Serialization.JsonPropertyName("name")]
public string? Name { get; set; }
public string? MerchantName { get; set; }
/// <summary>
/// 获取或设置接收方个人姓名(需使用平台公钥/证书加密)。
@ -41,7 +41,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
[System.Text.Json.Serialization.JsonPropertyName("encrypted_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? EncryptedName { get; set; }
public string? UserName { get; set; }
/// <summary>
/// 获取或设置与分账方的关系类型。

View File

@ -0,0 +1,142 @@
using System;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
{
/// <summary>
/// <para>表示 [POST] /eduschoolpay/transactions 接口的请求。</para>
/// </summary>
public class CreateEducationSchoolPayTransactionRequest : WechatTenpayRequest
{
public static class Types
{
public class Amount : CreateEducationPAPPayTransactionRequest.Types.Amount
{
}
public class Scene
{
/// <summary>
/// 获取或设置消费时间。
/// </summary>
[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; }
/// <summary>
/// 获取或设置学校编号。
/// </summary>
[Newtonsoft.Json.JsonProperty("school_id")]
[System.Text.Json.Serialization.JsonPropertyName("school_id")]
public string SchoolId { get; set; } = string.Empty;
/// <summary>
/// 获取或设置消费场景类型。
/// </summary>
[Newtonsoft.Json.JsonProperty("scene_type")]
[System.Text.Json.Serialization.JsonPropertyName("scene_type")]
public string SceneType { get; set; } = string.Empty;
}
public class Device : CreateEducationPAPPayTransactionRequest.Types.Device
{
}
public class Settlement : CreatePayPartnerTransactionAppRequest.Types.Settlement
{
}
}
/// <summary>
/// 获取或设置微信 AppId。
/// </summary>
[Newtonsoft.Json.JsonProperty("appid")]
[System.Text.Json.Serialization.JsonPropertyName("appid")]
public string AppId { get; set; } = string.Empty;
/// <summary>
/// 获取或设置子商户号。
/// </summary>
[Newtonsoft.Json.JsonProperty("sub_mchid")]
[System.Text.Json.Serialization.JsonPropertyName("sub_mchid")]
public string? SubMerchantId { get; set; } = string.Empty;
/// <summary>
/// 获取或设置子商户 AppId。
/// </summary>
[Newtonsoft.Json.JsonProperty("sub_appid")]
[System.Text.Json.Serialization.JsonPropertyName("sub_appid")]
public string? SubAppId { get; set; } = string.Empty;
/// <summary>
/// 获取或设置签约协议号。
/// </summary>
[Newtonsoft.Json.JsonProperty("contract_id")]
[System.Text.Json.Serialization.JsonPropertyName("contract_id")]
public string ContractId { get; set; } = string.Empty;
/// <summary>
/// 获取或设置商户用户账号。
/// </summary>
[Newtonsoft.Json.JsonProperty("user_id")]
[System.Text.Json.Serialization.JsonPropertyName("user_id")]
public string UserDisplayId { get; set; } = string.Empty;
/// <summary>
/// 获取或设置商户订单号。
/// </summary>
[Newtonsoft.Json.JsonProperty("out_trade_no")]
[System.Text.Json.Serialization.JsonPropertyName("out_trade_no")]
public string OutTradeNumber { get; set; } = string.Empty;
/// <summary>
/// 获取或设置商品描述。
/// </summary>
[Newtonsoft.Json.JsonProperty("description")]
[System.Text.Json.Serialization.JsonPropertyName("description")]
public string Description { get; set; } = string.Empty;
/// <summary>
/// 获取或设置附加数据。
/// </summary>
[Newtonsoft.Json.JsonProperty("attach")]
[System.Text.Json.Serialization.JsonPropertyName("attach")]
public string? Attachment { get; set; }
/// <summary>
/// 获取或设置订单优惠标记。
/// </summary>
[Newtonsoft.Json.JsonProperty("goods_tag")]
[System.Text.Json.Serialization.JsonPropertyName("goods_tag")]
public string? GoodsTag { get; set; }
/// <summary>
/// 获取或设置金额信息。
/// </summary>
[Newtonsoft.Json.JsonProperty("amount")]
[System.Text.Json.Serialization.JsonPropertyName("amount")]
public Types.Amount Amount { get; set; } = new Types.Amount();
/// <summary>
/// 获取或设置场景信息。
/// </summary>
[Newtonsoft.Json.JsonProperty("scene_info")]
[System.Text.Json.Serialization.JsonPropertyName("scene_info")]
public Types.Scene Scene { get; set; } = new Types.Scene();
/// <summary>
/// 获取或设置设备信息。
/// </summary>
[Newtonsoft.Json.JsonProperty("device_info")]
[System.Text.Json.Serialization.JsonPropertyName("device_info")]
public Types.Device? Device { get; set; }
/// <summary>
/// 获取或设置结算信息。
/// </summary>
[Newtonsoft.Json.JsonProperty("settle_info")]
[System.Text.Json.Serialization.JsonPropertyName("settle_info")]
public Types.Settlement? Settlement { get; set; }
}
}

View File

@ -0,0 +1,9 @@
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
{
/// <summary>
/// <para>表示 [POST] /eduschoolpay/transactions 接口的响应。</para>
/// </summary>
public class CreateEducationSchoolPayTransactionResponse : GetEducationSchoolPayTransactionByOutTradeNumberResponse
{
}
}

View File

@ -0,0 +1,15 @@
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
{
/// <summary>
/// <para>表示 [GET] /eduschoolpay/contracts/{contract_id} 接口的请求。</para>
/// </summary>
public class GetEducationSchoolPayContractByContractIdRequest : WechatTenpayRequest
{
/// <summary>
/// 获取或设置签约协议号。
/// </summary>
[Newtonsoft.Json.JsonIgnore]
[System.Text.Json.Serialization.JsonIgnore]
public string ContractId { get; set; } = string.Empty;
}
}

View File

@ -0,0 +1,68 @@
using System;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
{
/// <summary>
/// <para>表示 [GET] /eduschoolpay/contracts/{contract_id} 接口的响应。</para>
/// </summary>
public class GetEducationSchoolPayContractByContractIdResponse : WechatTenpayResponse
{
/// <summary>
/// 获取或设置微信商户号。
/// </summary>
[Newtonsoft.Json.JsonProperty("mchid")]
[System.Text.Json.Serialization.JsonPropertyName("mchid")]
public string MerchantId { get; set; } = default!;
/// <summary>
/// 获取或设置微信 AppId。
/// </summary>
[Newtonsoft.Json.JsonProperty("appid")]
[System.Text.Json.Serialization.JsonPropertyName("appid")]
public string AppId { get; set; } = default!;
/// <summary>
/// 获取或设置模板 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("plan_id")]
[System.Text.Json.Serialization.JsonPropertyName("plan_id")]
public string PlanId { get; set; } = default!;
/// <summary>
/// 获取或设置商户签约号。
/// </summary>
[Newtonsoft.Json.JsonProperty("out_contract_code")]
[System.Text.Json.Serialization.JsonPropertyName("out_contract_code")]
public string OutContractCode { get; set; } = default!;
/// <summary>
/// 获取或设置签约协议号。
/// </summary>
[Newtonsoft.Json.JsonProperty("contract_id")]
[System.Text.Json.Serialization.JsonPropertyName("contract_id")]
public string ContractId { get; set; } = default!;
/// <summary>
/// 获取或设置用户唯一标识。
/// </summary>
[Newtonsoft.Json.JsonProperty("openid")]
[System.Text.Json.Serialization.JsonPropertyName("openid")]
public string OpenId { get; set; } = default!;
/// <summary>
/// 获取或设置签约状态。
/// </summary>
[Newtonsoft.Json.JsonProperty("contract_status")]
[System.Text.Json.Serialization.JsonPropertyName("contract_status")]
public string Status { get; set; } = default!;
/// <summary>
/// 获取或设置签约时间。
/// </summary>
[Newtonsoft.Json.JsonProperty("create_time")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RFC3339DateTimeOffsetConverter))]
[System.Text.Json.Serialization.JsonPropertyName("create_time")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RFC3339DateTimeOffsetConverter))]
public DateTimeOffset CreateTime { get; set; }
}
}

View File

@ -0,0 +1,22 @@
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
{
/// <summary>
/// <para>表示 [GET] /eduschoolpay/transactions/id/{transaction_id} 接口的请求。</para>
/// </summary>
public class GetEducationSchoolPayTransactionByIdRequest : WechatTenpayRequest
{
/// <summary>
/// 获取或设置微信支付订单号。
/// </summary>
[Newtonsoft.Json.JsonIgnore]
[System.Text.Json.Serialization.JsonIgnore]
public string TransactionId { get; set; } = string.Empty;
/// <summary>
/// 获取或设置子商户号。
/// </summary>
[Newtonsoft.Json.JsonIgnore]
[System.Text.Json.Serialization.JsonIgnore]
public string? SubMerchantId { get; set; }
}
}

View File

@ -0,0 +1,9 @@
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
{
/// <summary>
/// <para>表示 [GET] /eduschoolpay/transactions/id/{transaction_id} 接口的响应。</para>
/// </summary>
public class GetEducationSchoolPayTransactionByIdResponse : GetEducationSchoolPayTransactionByOutTradeNumberResponse
{
}
}

View File

@ -0,0 +1,22 @@
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
{
/// <summary>
/// <para>表示 [GET] /eduschoolpay/transactions/out-trade-no/{out_trade_no} 接口的请求。</para>
/// </summary>
public class GetEducationSchoolPayTransactionByOutTradeNumberRequest : WechatTenpayRequest
{
/// <summary>
/// 获取或设置商户订单号。
/// </summary>
[Newtonsoft.Json.JsonIgnore]
[System.Text.Json.Serialization.JsonIgnore]
public string OutTradeNumber { get; set; } = string.Empty;
/// <summary>
/// 获取或设置子商户号。
/// </summary>
[Newtonsoft.Json.JsonIgnore]
[System.Text.Json.Serialization.JsonIgnore]
public string? SubMerchantId { get; set; }
}
}

View File

@ -0,0 +1,149 @@
using System;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
{
/// <summary>
/// <para>表示 [GET] /eduschoolpay/transactions/out-trade-no/{out_trade_no} 接口的响应。</para>
/// </summary>
public class GetEducationSchoolPayTransactionByOutTradeNumberResponse : WechatTenpayResponse
{
public static class Types
{
public class Payer : GetEducationPAPPayTransactionByOutTradeNumberResponse.Types.Payer
{
/// <summary>
/// 获取或设置用户在子商户下唯一标识。
/// </summary>
[Newtonsoft.Json.JsonProperty("sub_openid")]
[System.Text.Json.Serialization.JsonPropertyName("sub_openid")]
public string? SubOpenId { get; set; }
}
public class Amount : GetEducationPAPPayTransactionByOutTradeNumberResponse.Types.Amount
{
}
public class Device : GetEducationPAPPayTransactionByOutTradeNumberResponse.Types.Device
{
}
public class Promotion : GetEducationPAPPayTransactionByOutTradeNumberResponse.Types.Promotion
{
}
}
/// <summary>
/// 获取或设置微信商户号。
/// </summary>
[Newtonsoft.Json.JsonProperty("mchid")]
[System.Text.Json.Serialization.JsonPropertyName("mchid")]
public string MerchantId { get; set; } = default!;
/// <summary>
/// 获取或设置微信 AppId。
/// </summary>
[Newtonsoft.Json.JsonProperty("appid")]
[System.Text.Json.Serialization.JsonPropertyName("appid")]
public string AppId { get; set; } = default!;
/// <summary>
/// 获取或设置子商户号。
/// </summary>
[Newtonsoft.Json.JsonProperty("sub_mchid")]
[System.Text.Json.Serialization.JsonPropertyName("sub_mchid")]
public string? SubMerchantId { get; set; }
/// <summary>
/// 获取或设置子商户 AppId。
/// </summary>
[Newtonsoft.Json.JsonProperty("sub_appid")]
[System.Text.Json.Serialization.JsonPropertyName("sub_appid")]
public string? SubAppId { get; set; } = default!;
/// <summary>
/// 获取或设置商户订单号。
/// </summary>
[Newtonsoft.Json.JsonProperty("out_trade_no")]
[System.Text.Json.Serialization.JsonPropertyName("out_trade_no")]
public string OutTradeNumber { get; set; } = default!;
/// <summary>
/// 获取或设置微信支付订单号。
/// </summary>
[Newtonsoft.Json.JsonProperty("transaction_id")]
[System.Text.Json.Serialization.JsonPropertyName("transaction_id")]
public string? TransactionId { get; set; } = default!;
/// <summary>
/// 获取或设置交易类型。
/// </summary>
[Newtonsoft.Json.JsonProperty("trade_type")]
[System.Text.Json.Serialization.JsonPropertyName("trade_type")]
public string TradeType { get; set; } = default!;
/// <summary>
/// 获取或设置交易状态。
/// </summary>
[Newtonsoft.Json.JsonProperty("trade_state")]
[System.Text.Json.Serialization.JsonPropertyName("trade_state")]
public string TradeState { get; set; } = default!;
/// <summary>
/// 获取或设置交易状态描述。
/// </summary>
[Newtonsoft.Json.JsonProperty("trade_state_desc")]
[System.Text.Json.Serialization.JsonPropertyName("trade_state_desc")]
public string TradeStateDescription { get; set; } = default!;
/// <summary>
/// 获取或设置付款银行类型。
/// </summary>
[Newtonsoft.Json.JsonProperty("bank_type")]
[System.Text.Json.Serialization.JsonPropertyName("bank_type")]
public string? BankType { get; set; }
/// <summary>
/// 获取或设置附加数据。
/// </summary>
[Newtonsoft.Json.JsonProperty("attach")]
[System.Text.Json.Serialization.JsonPropertyName("attach")]
public string? Attachment { get; set; }
/// <summary>
/// 获取或设置支付完成时间。
/// </summary>
[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; }
/// <summary>
/// 获取或设置支付者信息。
/// </summary>
[Newtonsoft.Json.JsonProperty("payer")]
[System.Text.Json.Serialization.JsonPropertyName("payer")]
public Types.Payer? Payer { get; set; }
/// <summary>
/// 获取或设置金额信息。
/// </summary>
[Newtonsoft.Json.JsonProperty("amount")]
[System.Text.Json.Serialization.JsonPropertyName("amount")]
public Types.Amount Amount { get; set; } = default!;
/// <summary>
/// 获取或设置设备信息。
/// </summary>
[Newtonsoft.Json.JsonProperty("device_info")]
[System.Text.Json.Serialization.JsonPropertyName("device_info")]
public Types.Device? Device { get; set; }
/// <summary>
/// 获取或设置优惠信息。
/// </summary>
[Newtonsoft.Json.JsonProperty("promotion_detail")]
[System.Text.Json.Serialization.JsonPropertyName("promotion_detail")]
public Types.Promotion[]? PromotionList { get; set; }
}
}

View File

@ -0,0 +1,15 @@
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
{
/// <summary>
/// <para>表示 [GET] /eduschoolpay/users/{openid}/debt-state 接口的请求。</para>
/// </summary>
public class GetEducationSchoolPayUserDebtStateRequest : WechatTenpayRequest
{
/// <summary>
/// 获取或设置用户唯一标识。
/// </summary>
[Newtonsoft.Json.JsonIgnore]
[System.Text.Json.Serialization.JsonIgnore]
public string OpenId { get; set; } = string.Empty;
}
}

View File

@ -0,0 +1,47 @@
using System;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
{
/// <summary>
/// <para>表示 [GET] /eduschoolpay/users/{openid}/debt-state 接口的响应。</para>
/// </summary>
public class GetEducationSchoolPayUserDebtStateResponse : WechatTenpayResponse
{
/// <summary>
/// 获取或设置微信 AppId。
/// </summary>
[Newtonsoft.Json.JsonProperty("appid")]
[System.Text.Json.Serialization.JsonPropertyName("appid")]
public string AppId { get; set; } = default!;
/// <summary>
/// 获取或设置用户唯一标识。
/// </summary>
[Newtonsoft.Json.JsonProperty("openid")]
[System.Text.Json.Serialization.JsonPropertyName("openid")]
public string OpenId { get; set; } = default!;
/// <summary>
/// 获取或设置用户状态。
/// </summary>
[Newtonsoft.Json.JsonProperty("state")]
[System.Text.Json.Serialization.JsonPropertyName("state")]
public string State { get; set; } = default!;
/// <summary>
/// 获取或设置欠款笔数。
/// </summary>
[Newtonsoft.Json.JsonProperty("debt_count")]
[System.Text.Json.Serialization.JsonPropertyName("debt_count")]
public int DebtCount { get; set; }
/// <summary>
/// 获取或设置更新时间。
/// </summary>
[Newtonsoft.Json.JsonProperty("update_time")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RFC3339DateTimeOffsetConverter))]
[System.Text.Json.Serialization.JsonPropertyName("update_time")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RFC3339DateTimeOffsetConverter))]
public DateTimeOffset UpdateTime { get; set; }
}
}

View File

@ -0,0 +1,145 @@
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
{
/// <summary>
/// <para>表示 [POST] /eduschoolpay/contracts/presign 接口的请求。</para>
/// </summary>
[WechatTenpaySensitive]
public class PresignEducationSchoolPayContractRequest : WechatTenpayRequest
{
public static class Types
{
public class Identity
{
/// <summary>
/// 获取或设置真实姓名(需使用平台公钥/证书加密)。
/// </summary>
[Newtonsoft.Json.JsonProperty("real_name")]
[System.Text.Json.Serialization.JsonPropertyName("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 RealName { get; set; } = string.Empty;
/// <summary>
/// 获取或设置证件号码(需使用平台公钥/证书加密)。
/// </summary>
[Newtonsoft.Json.JsonProperty("id_card_number")]
[System.Text.Json.Serialization.JsonPropertyName("id_card_number")]
[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? CredentialNumber { get; set; }
/// <summary>
/// 获取或设置证件类型。
/// </summary>
[Newtonsoft.Json.JsonProperty("credential_type")]
[System.Text.Json.Serialization.JsonPropertyName("credential_type")]
public string? CredentialType { get; set; }
}
public class BankCard
{
/// <summary>
/// 获取或设置银行类型。
/// </summary>
[Newtonsoft.Json.JsonProperty("bank_type")]
[System.Text.Json.Serialization.JsonPropertyName("bank_type")]
public string? BankType { get; set; }
/// <summary>
/// 获取或设置银行卡号(需使用平台公钥/证书加密)。
/// </summary>
[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; } = string.Empty;
/// <summary>
/// 获取或设置银行卡有效期字符串单位MM/yy
/// </summary>
[Newtonsoft.Json.JsonProperty("valid_thru")]
[System.Text.Json.Serialization.JsonPropertyName("valid_thru")]
public string? ValidDateString { get; set; }
/// <summary>
/// 获取或设置银行卡开卡预留手机号(需使用平台公钥/证书加密)。
/// </summary>
[Newtonsoft.Json.JsonProperty("phone")]
[System.Text.Json.Serialization.JsonPropertyName("phone")]
[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 MobileNumber { get; set; } = string.Empty;
}
}
/// <summary>
/// 获取或设置微信 AppId。
/// </summary>
[Newtonsoft.Json.JsonProperty("appid")]
[System.Text.Json.Serialization.JsonPropertyName("appid")]
public string AppId { get; set; } = string.Empty;
/// <summary>
/// 获取或设置模板 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("plan_id")]
[System.Text.Json.Serialization.JsonPropertyName("plan_id")]
public string PlanId { get; set; } = string.Empty;
/// <summary>
/// 获取或设置用户唯一标识。
/// </summary>
[Newtonsoft.Json.JsonProperty("openid")]
[System.Text.Json.Serialization.JsonPropertyName("openid")]
public string OpenId { get; set; } = string.Empty;
/// <summary>
/// 获取或设置商户用户账号。
/// </summary>
[Newtonsoft.Json.JsonProperty("user_id")]
[System.Text.Json.Serialization.JsonPropertyName("user_id")]
public string UserDisplayId { get; set; } = string.Empty;
/// <summary>
/// 获取或设置学校编号。
/// </summary>
[Newtonsoft.Json.JsonProperty("school_id")]
[System.Text.Json.Serialization.JsonPropertyName("school_id")]
public string SchoolId { get; set; } = string.Empty;
/// <summary>
/// 获取或设置商户签约号。
/// </summary>
[Newtonsoft.Json.JsonProperty("out_contract_code")]
[System.Text.Json.Serialization.JsonPropertyName("out_contract_code")]
public string OutContractCode { get; set; } = string.Empty;
/// <summary>
/// 获取或设置签约模式。
/// </summary>
[Newtonsoft.Json.JsonProperty("contract_mode")]
[System.Text.Json.Serialization.JsonPropertyName("contract_mode")]
public string? ContractMode { get; set; }
/// <summary>
/// 获取或设置是否允许降级为普通签约模式。
/// </summary>
[Newtonsoft.Json.JsonProperty("downgrade_default_contract")]
[System.Text.Json.Serialization.JsonPropertyName("downgrade_default_contract")]
public bool? AllowDowngradeDefaultContract { get; set; }
/// <summary>
/// 获取或设置实名信息。
/// </summary>
[Newtonsoft.Json.JsonProperty("identity")]
[System.Text.Json.Serialization.JsonPropertyName("identity")]
public Types.Identity? Identity { get; set; }
/// <summary>
/// 获取或设置银行卡信息。
/// </summary>
[Newtonsoft.Json.JsonProperty("bank_card")]
[System.Text.Json.Serialization.JsonPropertyName("bank_card")]
public Types.BankCard? BankCard { get; set; }
}
}

View File

@ -0,0 +1,15 @@
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
{
/// <summary>
/// <para>表示 [POST] /eduschoolpay/contracts/presign 接口的响应。</para>
/// </summary>
public class PresignEducationSchoolPayContractResponse : WechatTenpayResponse
{
/// <summary>
/// 获取或设置预签约码。
/// </summary>
[Newtonsoft.Json.JsonProperty("presign_token")]
[System.Text.Json.Serialization.JsonPropertyName("presign_token")]
public string PresignToken { get; set; } = default!;
}
}

View File

@ -0,0 +1,44 @@
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
{
/// <summary>
/// <para>表示 [GET] /eduschoolpay/users/{openid}/contracts 接口的请求。</para>
/// </summary>
public class QueryEducationSchoolPayUserContractsRequest : WechatTenpayRequest
{
/// <summary>
/// 获取或设置模板 ID。
/// </summary>
[Newtonsoft.Json.JsonIgnore]
[System.Text.Json.Serialization.JsonIgnore]
public string PlanId { get; set; } = string.Empty;
/// <summary>
/// 获取或设置用户唯一标识。
/// </summary>
[Newtonsoft.Json.JsonIgnore]
[System.Text.Json.Serialization.JsonIgnore]
public string OpenId { get; set; } = string.Empty;
/// <summary>
/// 获取或设置签约状态。
/// <para>默认值ALL</para>
/// </summary>
[Newtonsoft.Json.JsonIgnore]
[System.Text.Json.Serialization.JsonIgnore]
public string ContractStatus { get; set; } = "ALL";
/// <summary>
/// 获取或设置分页大小。
/// </summary>
[Newtonsoft.Json.JsonIgnore]
[System.Text.Json.Serialization.JsonIgnore]
public int? Limit { get; set; }
/// <summary>
/// 获取或设置分页开始位置。
/// </summary>
[Newtonsoft.Json.JsonIgnore]
[System.Text.Json.Serialization.JsonIgnore]
public int? Offset { get; set; }
}
}

View File

@ -0,0 +1,102 @@
using System;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
{
/// <summary>
/// <para>表示 [GET] /eduschoolpay/users/{openid}/contracts 接口的响应。</para>
/// </summary>
public class QueryEducationSchoolPayUserContractsResponse : WechatTenpayResponse
{
public static class Types
{
public class UserContract
{
/// <summary>
/// 获取或设置微信商户号。
/// </summary>
[Newtonsoft.Json.JsonProperty("mchid")]
[System.Text.Json.Serialization.JsonPropertyName("mchid")]
public string MerchantId { get; set; } = default!;
/// <summary>
/// 获取或设置微信 AppId。
/// </summary>
[Newtonsoft.Json.JsonProperty("appid")]
[System.Text.Json.Serialization.JsonPropertyName("appid")]
public string AppId { get; set; } = default!;
/// <summary>
/// 获取或设置模板 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("plan_id")]
[System.Text.Json.Serialization.JsonPropertyName("plan_id")]
public string PlanId { get; set; } = default!;
/// <summary>
/// 获取或设置商户签约号。
/// </summary>
[Newtonsoft.Json.JsonProperty("out_contract_code")]
[System.Text.Json.Serialization.JsonPropertyName("out_contract_code")]
public string OutContractCode { get; set; } = default!;
/// <summary>
/// 获取或设置签约协议号。
/// </summary>
[Newtonsoft.Json.JsonProperty("contract_id")]
[System.Text.Json.Serialization.JsonPropertyName("contract_id")]
public string ContractId { get; set; } = default!;
/// <summary>
/// 获取或设置用户唯一标识。
/// </summary>
[Newtonsoft.Json.JsonProperty("openid")]
[System.Text.Json.Serialization.JsonPropertyName("openid")]
public string OpenId { get; set; } = default!;
/// <summary>
/// 获取或设置签约状态。
/// </summary>
[Newtonsoft.Json.JsonProperty("contract_status")]
[System.Text.Json.Serialization.JsonPropertyName("contract_status")]
public string Status { get; set; } = default!;
/// <summary>
/// 获取或设置签约时间。
/// </summary>
[Newtonsoft.Json.JsonProperty("create_time")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RFC3339DateTimeOffsetConverter))]
[System.Text.Json.Serialization.JsonPropertyName("create_time")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RFC3339DateTimeOffsetConverter))]
public DateTimeOffset CreateTime { get; set; }
}
}
/// <summary>
/// 获取或设置签约列表。
/// </summary>
[Newtonsoft.Json.JsonProperty("data")]
[System.Text.Json.Serialization.JsonPropertyName("data")]
public Types.UserContract[] UserContractList { get; set; } = default!;
/// <summary>
/// 获取或设置分页开始位置。
/// </summary>
[Newtonsoft.Json.JsonProperty("offset")]
[System.Text.Json.Serialization.JsonPropertyName("offset")]
public int Offset { get; set; }
/// <summary>
/// 获取或设置分页大小。
/// </summary>
[Newtonsoft.Json.JsonProperty("limit")]
[System.Text.Json.Serialization.JsonPropertyName("limit")]
public int Limit { get; set; }
/// <summary>
/// 获取或设置数据总条数。
/// </summary>
[Newtonsoft.Json.JsonProperty("total_count")]
[System.Text.Json.Serialization.JsonPropertyName("total_count")]
public int TotalCount { get; set; }
}
}

View File

@ -0,0 +1,15 @@
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
{
/// <summary>
/// <para>表示 [POST] /eduschoolpay/contracts/{contract_id}/terminate 接口的请求。</para>
/// </summary>
public class TerminateEducationSchoolPayContractRequest : WechatTenpayRequest
{
/// <summary>
/// 获取或设置签约协议号。
/// </summary>
[Newtonsoft.Json.JsonIgnore]
[System.Text.Json.Serialization.JsonIgnore]
public string ContractId { get; set; } = string.Empty;
}
}

View File

@ -0,0 +1,9 @@
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
{
/// <summary>
/// <para>表示 [POST] /eduschoolpay/contracts/{contract_id}/terminate 接口的响应。</para>
/// </summary>
public class TerminateEducationSchoolPayContractResponse : WechatTenpayResponse
{
}
}

View File

@ -1,4 +1,4 @@
using System;
using System;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
{

View File

@ -15,7 +15,7 @@
<PackageProjectUrl>https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat</PackageProjectUrl>
<PackageTags>Flurl.Http Wechat Weixin MicroMessage Tenpay WechatPay WeixinPay Wxpay 微信 微信支付 微信商户</PackageTags>
<Version>2.18.0</Version>
<Description>基于 Flurl.Http 的微信支付 API v3 版客户端,支持直连商户、服务商模式,支持基础支付、代金券、商家券、委托营销、消费卡、支付有礼、银行定向促活、微信支付分、微信先享卡、支付即服务、点金计划、智慧商圈、电商收付通、二级商户进件、小微商户进件、消费者投诉、商户违规通知、批量转账到零钱、银行组件、海关报关、融合钱包、微工卡、电子发票、车主平台、教育续费通等功能。</Description>
<Description>基于 Flurl.Http 的微信支付 API v3 版客户端,支持直连商户、服务商模式,支持基础支付、代金券、商家券、委托营销、消费卡、支付有礼、银行定向促活、微信支付分、微信先享卡、支付即服务、点金计划、智慧商圈、电商收付通、二级商户进件、小微商户进件、消费者投诉、商户违规通知、批量转账到零钱、银行组件、海关报关、融合钱包、微工卡、电子发票、车主平台、教育续费通、校园轻松付等功能。</Description>
<Authors>Fu Diwei</Authors>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat.git</RepositoryUrl>

View File

@ -0,0 +1,24 @@
{
"appid": "wx8888888888888888",
"sub_mchid": "1900000109",
"sub_appid": "wx8888888888888888",
"description": "中山大学-第二食堂-海鲜炒饭",
"attach": "自定义数据",
"out_trade_no": "121775250124070332",
"goods_tag": "test",
"contract_id": "2045011120563805041758214605",
"user_id": "20200330tony",
"amount": {
"total": 888,
"currency": "CNY"
},
"scene_info": {
"start_time": "2017-08-26T09:43:39+08:00",
"school_id": "18260256813396",
"scene_type": "CANTEEN"
},
"device_info": {
"device_id": "12343232",
"device_ip": "123.12.12.123"
}
}

View File

@ -0,0 +1,41 @@
{
"mchid": "1230000109",
"appid": "wx8888888888888888",
"sub_mchid": "1900000109",
"sub_appid": "wx8888888888888888",
"out_trade_no": "201407033233368018",
"transaction_id": "25012014070332333018",
"trade_type": "AUTH",
"trade_state": "SUCCESS",
"trade_state_desc": "支付成功",
"bank_type": "ICBC_DEBIT",
"attach": "自定义数据",
"success_time": "2020-03-26T10:43:39+08:00",
"payer": {
"openid": "oUpF8uMuAJOM2pxb1Q",
"sub_openid": "oUpF8uMuAJOM2pxb1Q"
},
"amount": {
"total": 888,
"payer_total": 888,
"discount_total": 100,
"currency": "CNY"
},
"device_info": {
"device_id": "12343232",
"device_ip": "123.12.12.123"
},
"promotion_detail": [
{
"coupon_id": "109519",
"name": "单品惠-6",
"scope": "GLOBALSINGLE",
"type": "DISCOUNTCOUPON",
"amount": 5,
"stock_id": "931386",
"wechatpay_contribute": 0,
"merchant_contribute": 0,
"other_contribute": 0
}
]
}

View File

@ -0,0 +1,10 @@
{
"contract_id": "2045011120563805041758214605",
"mchid": "1230000109",
"appid": "wx8888888888888888",
"openid": "oUpF8uMuAJOM2pxb1Q",
"plan_id": "101164396123311331",
"contract_status": "ADD",
"create_time": "2017-08-26T09:43:39+08:00",
"out_contract_code": "20190806125346"
}

View File

@ -0,0 +1,41 @@
{
"mchid": "1230000109",
"appid": "wx8888888888888888",
"sub_mchid": "1900000109",
"sub_appid": "wx8888888888888888",
"out_trade_no": "201407033233368018",
"transaction_id": "25012014070332333018",
"trade_type": "AUTH",
"trade_state": "SUCCESS",
"trade_state_desc": "支付成功",
"bank_type": "ICBC_DEBIT",
"attach": "自定义数据",
"success_time": "2020-03-26T10:43:39+08:00",
"payer": {
"openid": "oUpF8uMuAJOM2pxb1Q",
"sub_openid": "oUpF8uMuAJOM2pxb1Q"
},
"amount": {
"total": 888,
"payer_total": 888,
"discount_total": 100,
"currency": "CNY"
},
"device_info": {
"device_id": "12343232",
"device_ip": "123.12.12.123"
},
"promotion_detail": [
{
"coupon_id": "109519",
"name": "单品惠-6",
"scope": "GLOBALSINGLE",
"type": "DISCOUNTCOUPON",
"amount": 5,
"stock_id": "931386",
"wechatpay_contribute": 0,
"merchant_contribute": 0,
"other_contribute": 0
}
]
}

View File

@ -0,0 +1,41 @@
{
"mchid": "1230000109",
"appid": "wx8888888888888888",
"sub_mchid": "1900000109",
"sub_appid": "wx8888888888888888",
"out_trade_no": "201407033233368018",
"transaction_id": "25012014070332333018",
"trade_type": "AUTH",
"trade_state": "SUCCESS",
"trade_state_desc": "支付成功",
"bank_type": "ICBC_DEBIT",
"attach": "自定义数据",
"success_time": "2020-03-26T10:43:39+08:00",
"payer": {
"openid": "oUpF8uMuAJOM2pxb1Q",
"sub_openid": "oUpF8uMuAJOM2pxb1Q"
},
"amount": {
"total": 888,
"payer_total": 888,
"discount_total": 100,
"currency": "CNY"
},
"device_info": {
"device_id": "12343232",
"device_ip": "123.12.12.123"
},
"promotion_detail": [
{
"coupon_id": "109519",
"name": "单品惠-6",
"scope": "GLOBALSINGLE",
"type": "DISCOUNTCOUPON",
"amount": 5,
"stock_id": "931386",
"wechatpay_contribute": 0,
"merchant_contribute": 0,
"other_contribute": 0
}
]
}

View File

@ -0,0 +1,7 @@
{
"appid": "wx8888888888888888",
"openid": "oUpF8uMuAJOM2pxb1Q",
"state": "FORBIDDEN",
"debt_count": 2,
"update_time": "2017-08-26T09:43:39+08:00"
}

View File

@ -0,0 +1,21 @@
{
"appid": "wx8888888888888888",
"openid": "oUpF8uMuAJOM2pxb1Q",
"plan_id": "101164396123311331",
"user_id": "20200330tony",
"school_id": "18260256813396",
"out_contract_code": "20190806125346",
"contract_mode": "LIMIT_BANK_CARD",
"downgrade_default_contract": false,
"identity": {
"real_name": "6TqLAZvNZ4AXLNHLMbjA1yKq2k5krHM09m3tCuR",
"credential_type": "IDENTITY_CARD",
"id_card_number": "6TqLAZvNZ4AXLNHLMbjA1yKq2k5krHM09m3tCuR"
},
"bank_card": {
"bank_card_no": "6TqLAZvNZ4AXLNHLMbjA1yKq2k5krHM09m3tCuR",
"valid_thru": "08/21",
"phone": "j6PlFRRJ4nvGSbtDZzXbXScACvDSnIny67zk3BgT5uIbK4VfGmcjPBEk2mt5ASZ6UUHB4Gy0IZpbuanF9",
"bank_type": "CMC"
}
}

View File

@ -0,0 +1,17 @@
{
"data": [
{
"contract_id": "2045011120563805041758214605",
"mchid": "1230000109",
"appid": "wx8888888888888888",
"openid": "oUpF8uMuAJOM2pxb1Q",
"plan_id": "101164396123311331",
"contract_status": "ADD",
"create_time": "2017-08-26T09:43:39+08:00",
"out_contract_code": "20190806125346"
}
],
"offset": 10,
"limit": 20,
"total_count": 1234
}

View File

@ -487,14 +487,14 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
{
return new Models.AddEcommerceProfitSharingReceiverRequest()
{
EncryptedName = MOCK_PLAIN_STR
UserName = MOCK_PLAIN_STR
};
}
static void AssertMockRequestModel(Models.AddEcommerceProfitSharingReceiverRequest request, Func<string, string> decryptor)
{
Assert.NotEqual(MOCK_PLAIN_STR, request.EncryptedName!);
Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.EncryptedName!));
Assert.NotEqual(MOCK_PLAIN_STR, request.UserName!);
Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.UserName!));
Assert.Equal(MOCK_CERT_SN, request.WechatpayCertificateSerialNumber!, ignoreCase: true);
}
@ -515,6 +515,56 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
AssertMockRequestModel(reqB2, (cipher) => Utilities.SM2Utility.Decrypt(SM2_PEM_PRIVATE_KEY, cipher));
}
[Fact(DisplayName = "测试用例:加密请求中的敏感数据([POST] /eduschoolpay/contracts/presign")]
public async Task TestEncryptRequestSensitiveProperty_PresignEducationSchoolPayContractRequest()
{
static Models.PresignEducationSchoolPayContractRequest GenerateMockRequestModel()
{
return new Models.PresignEducationSchoolPayContractRequest()
{
Identity = new Models.PresignEducationSchoolPayContractRequest.Types.Identity()
{
RealName = MOCK_PLAIN_STR,
CredentialNumber = MOCK_PLAIN_STR
},
BankCard = new Models.PresignEducationSchoolPayContractRequest.Types.BankCard()
{
BankCardNumber = MOCK_PLAIN_STR,
MobileNumber = MOCK_PLAIN_STR
}
};
}
static void AssertMockRequestModel(Models.PresignEducationSchoolPayContractRequest request, Func<string, string> decryptor)
{
Assert.NotEqual(MOCK_PLAIN_STR, request.Identity!.RealName!);
Assert.NotEqual(MOCK_PLAIN_STR, request.Identity!.CredentialNumber!);
Assert.NotEqual(MOCK_PLAIN_STR, request.BankCard!.BankCardNumber!);
Assert.NotEqual(MOCK_PLAIN_STR, request.BankCard!.MobileNumber!);
Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.Identity!.RealName!));
Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.Identity!.CredentialNumber!));
Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.BankCard!.BankCardNumber!));
Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.BankCard!.MobileNumber!));
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).ExecutePresignEducationSchoolPayContractAsync(reqB1);
AssertMockRequestModel(reqB1, (cipher) => Utilities.RSAUtility.DecryptWithECB(RSA_PEM_PRIVATE_KEY, cipher));
var reqB2 = GenerateMockRequestModel();
await CreateMockClientUseSM2(autoEncrypt: true).ExecutePresignEducationSchoolPayContractAsync(reqB2);
AssertMockRequestModel(reqB2, (cipher) => Utilities.SM2Utility.Decrypt(SM2_PEM_PRIVATE_KEY, cipher));
}
[Fact(DisplayName = "测试用例:加密请求中的敏感数据([POST] /marketing/membercard-open/cards/{card_id}/phone-membercard/import")]
public async Task TestEncryptRequestSensitiveProperty_ImportMarketingMemberCardOpenCardPhoneRequest()
{
@ -522,14 +572,14 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
{
return new Models.ImportMarketingMemberCardOpenCardPhoneRequest()
{
EncryptedPhoneNumber = MOCK_PLAIN_STR
MobileNumber = MOCK_PLAIN_STR
};
}
static void AssertMockRequestModel(Models.ImportMarketingMemberCardOpenCardPhoneRequest request, Func<string, string> decryptor)
{
Assert.NotEqual(MOCK_PLAIN_STR, request.EncryptedPhoneNumber!);
Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.EncryptedPhoneNumber!));
Assert.NotEqual(MOCK_PLAIN_STR, request.MobileNumber!);
Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.MobileNumber!));
Assert.Equal(MOCK_CERT_SN, request.WechatpayCertificateSerialNumber!, ignoreCase: true);
}
@ -1083,8 +1133,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
{
Identify = new Models.PreopenVehicleETCRequest.Types.Identify()
{
EncryptedRealName = MOCK_PLAIN_STR,
EncryptedCredentialNumber = MOCK_PLAIN_STR
RealName = MOCK_PLAIN_STR,
CredentialNumber = MOCK_PLAIN_STR
},
BankCardNumber = MOCK_PLAIN_STR
};
@ -1092,11 +1142,11 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
static void AssertMockRequestModel(Models.PreopenVehicleETCRequest request, Func<string, string> decryptor)
{
Assert.NotEqual(MOCK_PLAIN_STR, request.Identify!.EncryptedRealName!);
Assert.NotEqual(MOCK_PLAIN_STR, request.Identify!.EncryptedCredentialNumber!);
Assert.NotEqual(MOCK_PLAIN_STR, request.Identify!.RealName!);
Assert.NotEqual(MOCK_PLAIN_STR, request.Identify!.CredentialNumber!);
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.Identify!.RealName!));
Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.Identify!.CredentialNumber!));
Assert.Equal(MOCK_PLAIN_STR, decryptor.Invoke(request.BankCardNumber!));
Assert.Equal(MOCK_CERT_SN, request.WechatpayCertificateSerialNumber!, ignoreCase: true);
}