feat(tenpaybusiness): 新增退款相关接口

This commit is contained in:
Fu Diwei 2023-04-11 15:27:07 +08:00
parent c30f3473a4
commit f0e032849b
17 changed files with 425 additions and 6 deletions

View File

@ -69,7 +69,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Events
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RFC3339NullableDateTimeOffsetConverter))] [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RFC3339NullableDateTimeOffsetConverter))]
[System.Text.Json.Serialization.JsonPropertyName("pay_succ_time")] [System.Text.Json.Serialization.JsonPropertyName("pay_succ_time")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RFC3339NullableDateTimeOffsetConverter))] [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RFC3339NullableDateTimeOffsetConverter))]
public DateTimeOffset? PaySuccessTime { get; set; } public DateTimeOffset? SucceedTime { get; set; }
} }
} }
} }

View File

@ -0,0 +1,90 @@
using System;
namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Events
{
/// <summary>
/// <para>表示 mse_refund.succeeded 通知的数据。</para>
/// </summary>
public class RefundEvent : WechatTenpayBusinessEvent<RefundEvent.Types.EventContent>
{
public static class Types
{
public class EventContent
{
/// <summary>
/// 获取或设置平台退款单号。
/// </summary>
[Newtonsoft.Json.JsonProperty("out_refund_id")]
[System.Text.Json.Serialization.JsonPropertyName("out_refund_id")]
public string OutRefundId { get; set; } = default!;
/// <summary>
/// 获取或设置微企付退款单号。
/// </summary>
[Newtonsoft.Json.JsonProperty("refund_id")]
[System.Text.Json.Serialization.JsonPropertyName("refund_id")]
public string RefundId { get; set; } = default!;
/// <summary>
/// 获取或设置平台支付单号。
/// </summary>
[Newtonsoft.Json.JsonProperty("out_payment_id")]
[System.Text.Json.Serialization.JsonPropertyName("out_payment_id")]
public string OutPaymentId { get; set; } = default!;
/// <summary>
/// 获取或设置微企付支付单号。
/// </summary>
[Newtonsoft.Json.JsonProperty("payment_id")]
[System.Text.Json.Serialization.JsonPropertyName("payment_id")]
public string PaymentId { get; set; } = default!;
/// <summary>
/// 获取或设置原支付金额(单位:分)。
/// </summary>
[Newtonsoft.Json.JsonProperty("total_amount")]
[System.Text.Json.Serialization.JsonPropertyName("total_amount")]
public int TotalAmount { get; set; }
/// <summary>
/// 获取或设置退款金额(单位:分)。
/// </summary>
[Newtonsoft.Json.JsonProperty("refund_amount")]
[System.Text.Json.Serialization.JsonPropertyName("refund_amount")]
public int RefundAmount { get; set; }
/// <summary>
/// 获取或设置退款原因。
/// </summary>
[Newtonsoft.Json.JsonProperty("refund_reason")]
[System.Text.Json.Serialization.JsonPropertyName("refund_reason")]
public string? RefundReason { get; set; }
/// <summary>
/// 获取或设置退款状态。
/// </summary>
[Newtonsoft.Json.JsonProperty("status")]
[System.Text.Json.Serialization.JsonPropertyName("status")]
public string Status { get; set; } = default!;
/// <summary>
/// 获取或设置退款成功时间。
/// </summary>
[Newtonsoft.Json.JsonProperty("succeeded_time")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RFC3339NullableDateTimeOffsetConverter))]
[System.Text.Json.Serialization.JsonPropertyName("succeeded_time")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RFC3339NullableDateTimeOffsetConverter))]
public DateTimeOffset? SucceedTime { get; set; }
/// <summary>
/// 获取或设置退款创建时间。
/// </summary>
[Newtonsoft.Json.JsonProperty("created_time")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RFC3339DateTimeOffsetConverter))]
[System.Text.Json.Serialization.JsonPropertyName("created_time")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RFC3339DateTimeOffsetConverter))]
public DateTimeOffset CreateTime { get; set; }
}
}
}
}

View File

@ -0,0 +1,68 @@
using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Flurl.Http;
namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness
{
public static class WechatTenpayBusinessClientExecuteRefundsExtensions
{
/// <summary>
/// <para>异步调用 [POST] /mse-pay/refunds 接口。</para>
/// <para>REF: https://businesspay.qq.com/p/doc/mse/api/server.html#%E9%80%80%E6%AC%BE%E7%94%B3%E8%AF%B7 </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.CreateRefundResponse> ExecuteCreateRefundAsync(this WechatTenpayBusinessClient client, Models.CreateRefundRequest 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, "mse-pay", "refunds");
return await client.SendRequestWithJsonAsync<Models.CreateRefundResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
}
/// <summary>
/// <para>异步调用 [GET] /mse-pay/refunds/out-refund-id/{out_refund_id} 接口。</para>
/// <para>REF: https://businesspay.qq.com/p/doc/mse/api/server.html#%E9%80%80%E6%AC%BE%E6%9F%A5%E8%AF%A2-%E5%A4%96%E5%8D%95%E5%8F%B7 </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.GetRefundByOutRefundIdResponse> ExecuteGetRefundByOutRefundIdAsync(this WechatTenpayBusinessClient client, Models.GetRefundByOutRefundIdRequest 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, "mse-pay", "refunds", "out-refund-id", request.OutRefundId);
return await client.SendRequestWithJsonAsync<Models.GetRefundByOutRefundIdResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
}
/// <summary>
/// <para>异步调用 [GET] /mse-pay/refunds/refund-id/{refund_id} 接口。</para>
/// <para>REF: https://businesspay.qq.com/p/doc/mse/api/server.html#%E9%80%80%E6%AC%BE%E6%9F%A5%E8%AF%A2-%E5%86%85%E5%8D%95%E5%8F%B7 </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.GetRefundByRefundIdResponse> ExecuteGetRefundByRefundIdAsync(this WechatTenpayBusinessClient client, Models.GetRefundByRefundIdRequest 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, "mse-pay", "refunds", "refund-id", request.RefundId);
return await client.SendRequestWithJsonAsync<Models.GetRefundByRefundIdResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
}
}
}

View File

@ -3,7 +3,6 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Models
/// <summary> /// <summary>
/// <para>表示 [GET] /mse-pay/payments/out-payment-id/{out_payment_id} 接口的响应。</para> /// <para>表示 [GET] /mse-pay/payments/out-payment-id/{out_payment_id} 接口的响应。</para>
/// </summary> /// </summary>
[WechatTenpayBusinessSensitive]
public class GetPaymentByOutPaymentIdResponse : GetPaymentByPaymentIdResponse public class GetPaymentByOutPaymentIdResponse : GetPaymentByPaymentIdResponse
{ {
} }

View File

@ -125,9 +125,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Models
/// 获取或设置付款时间。 /// 获取或设置付款时间。
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("pay_time")] [Newtonsoft.Json.JsonProperty("pay_time")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RegularNullableDateTimeOffsetConverter))] [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RFC3339NullableDateTimeOffsetConverter))]
[System.Text.Json.Serialization.JsonPropertyName("pay_time")] [System.Text.Json.Serialization.JsonPropertyName("pay_time")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RegularNullableDateTimeOffsetConverter))] [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RFC3339NullableDateTimeOffsetConverter))]
public DateTimeOffset? PayTime { get; set; } public DateTimeOffset? SucceedTime { get; set; }
} }
} }

View File

@ -0,0 +1,64 @@
namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Models
{
/// <summary>
/// <para>表示 [POST] /mse-pay/refunds 接口的请求。</para>
/// </summary>
public class CreateRefundRequest : WechatTenpayBusinessRequest
{
/// <summary>
/// 获取或设置企业 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("ent_id")]
[System.Text.Json.Serialization.JsonPropertyName("ent_id")]
public string EnterpriseId { get; set; } = string.Empty;
/// <summary>
/// 获取或设置平台退款单号。
/// </summary>
[Newtonsoft.Json.JsonProperty("out_refund_id")]
[System.Text.Json.Serialization.JsonPropertyName("out_refund_id")]
public string OutRefundId { get; set; } = string.Empty;
/// <summary>
/// 获取或设置平台支付单号。与字段 <see cref="PaymentId"/> 二选一。
/// </summary>
[Newtonsoft.Json.JsonProperty("out_payment_id")]
[System.Text.Json.Serialization.JsonPropertyName("out_payment_id")]
public string? OutPaymentId { get; set; }
/// <summary>
/// 获取或设置微企付支付单号。与字段 <see cref="OutPaymentId"/> 二选一。
/// </summary>
[Newtonsoft.Json.JsonProperty("payment_id")]
[System.Text.Json.Serialization.JsonPropertyName("payment_id")]
public string? PaymentId { get; set; }
/// <summary>
/// 获取或设置原支付金额(单位:分)。
/// </summary>
[Newtonsoft.Json.JsonProperty("total_amount")]
[System.Text.Json.Serialization.JsonPropertyName("total_amount")]
public int TotalAmount { get; set; }
/// <summary>
/// 获取或设置退款金额(单位:分)。
/// </summary>
[Newtonsoft.Json.JsonProperty("refund_amount")]
[System.Text.Json.Serialization.JsonPropertyName("refund_amount")]
public int RefundAmount { get; set; }
/// <summary>
/// 获取或设置退款原因。
/// </summary>
[Newtonsoft.Json.JsonProperty("refund_reason")]
[System.Text.Json.Serialization.JsonPropertyName("refund_reason")]
public string? RefundReason { get; set; }
/// <summary>
/// 获取或设置退款结果通知 URL。
/// </summary>
[Newtonsoft.Json.JsonProperty("server_notify_url")]
[System.Text.Json.Serialization.JsonPropertyName("server_notify_url")]
public string ServerNotifyUrl { get; set; } = string.Empty;
}
}

View File

@ -0,0 +1,9 @@
namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Models
{
/// <summary>
/// <para>表示 [POST] /mse-pay/refunds 接口的响应。</para>
/// </summary>
public class CreateRefundResponse : GetRefundByRefundIdResponse
{
}
}

View File

@ -0,0 +1,15 @@
namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Models
{
/// <summary>
/// <para>表示 [GET] /mse-pay/refunds/out-refund-id/{out_refund_id} 接口的请求。</para>
/// </summary>
public class GetRefundByOutRefundIdRequest : WechatTenpayBusinessRequest
{
/// <summary>
/// 获取或设置平台退款单号。
/// </summary>
[Newtonsoft.Json.JsonIgnore]
[System.Text.Json.Serialization.JsonIgnore]
public string OutRefundId { get; set; } = string.Empty;
}
}

View File

@ -0,0 +1,9 @@
namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Models
{
/// <summary>
/// <para>表示 [GET] /mse-pay/refunds/out-refund-id/{out_refund_id} 接口的响应。</para>
/// </summary>
public class GetRefundByOutRefundIdResponse : GetRefundByRefundIdResponse
{
}
}

View File

@ -0,0 +1,15 @@
namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Models
{
/// <summary>
/// <para>表示 [GET] /mse-pay/refunds/refund-id/{refund_id} 接口的请求。</para>
/// </summary>
public class GetRefundByRefundIdRequest : WechatTenpayBusinessRequest
{
/// <summary>
/// 获取或设置微企付退款单号。
/// </summary>
[Newtonsoft.Json.JsonIgnore]
[System.Text.Json.Serialization.JsonIgnore]
public string RefundId { get; set; } = string.Empty;
}
}

View File

@ -0,0 +1,84 @@
using System;
namespace SKIT.FlurlHttpClient.Wechat.TenpayBusiness.Models
{
/// <summary>
/// <para>表示 [GET] /mse-pay/refunds/refund-id/{refund_id} 接口的响应。</para>
/// </summary>
public class GetRefundByRefundIdResponse : WechatTenpayBusinessResponse
{
/// <summary>
/// 获取或设置平台退款单号。
/// </summary>
[Newtonsoft.Json.JsonProperty("out_refund_id")]
[System.Text.Json.Serialization.JsonPropertyName("out_refund_id")]
public string OutRefundId { get; set; } = default!;
/// <summary>
/// 获取或设置微企付退款单号。
/// </summary>
[Newtonsoft.Json.JsonProperty("refund_id")]
[System.Text.Json.Serialization.JsonPropertyName("refund_id")]
public string RefundId { get; set; } = default!;
/// <summary>
/// 获取或设置平台支付单号。
/// </summary>
[Newtonsoft.Json.JsonProperty("out_payment_id")]
[System.Text.Json.Serialization.JsonPropertyName("out_payment_id")]
public string OutPaymentId { get; set; } = default!;
/// <summary>
/// 获取或设置微企付支付单号。
/// </summary>
[Newtonsoft.Json.JsonProperty("payment_id")]
[System.Text.Json.Serialization.JsonPropertyName("payment_id")]
public string PaymentId { get; set; } = default!;
/// <summary>
/// 获取或设置原支付金额(单位:分)。
/// </summary>
[Newtonsoft.Json.JsonProperty("total_amount")]
[System.Text.Json.Serialization.JsonPropertyName("total_amount")]
public int TotalAmount { get; set; }
/// <summary>
/// 获取或设置退款金额(单位:分)。
/// </summary>
[Newtonsoft.Json.JsonProperty("refund_amount")]
[System.Text.Json.Serialization.JsonPropertyName("refund_amount")]
public int RefundAmount { get; set; }
/// <summary>
/// 获取或设置退款原因。
/// </summary>
[Newtonsoft.Json.JsonProperty("refund_reason")]
[System.Text.Json.Serialization.JsonPropertyName("refund_reason")]
public string? RefundReason { get; set; }
/// <summary>
/// 获取或设置退款状态。
/// </summary>
[Newtonsoft.Json.JsonProperty("status")]
[System.Text.Json.Serialization.JsonPropertyName("status")]
public string Status { get; set; } = default!;
/// <summary>
/// 获取或设置退款成功时间。
/// </summary>
[Newtonsoft.Json.JsonProperty("succeeded_time")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RFC3339NullableDateTimeOffsetConverter))]
[System.Text.Json.Serialization.JsonPropertyName("succeeded_time")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RFC3339NullableDateTimeOffsetConverter))]
public DateTimeOffset? SucceedTime { get; set; }
/// <summary>
/// 获取或设置退款创建时间。
/// </summary>
[Newtonsoft.Json.JsonProperty("created_time")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RFC3339DateTimeOffsetConverter))]
[System.Text.Json.Serialization.JsonPropertyName("created_time")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RFC3339DateTimeOffsetConverter))]
public DateTimeOffset CreateTime { get; set; }
}
}

View File

@ -0,0 +1,20 @@
{
"api_version": "",
"event_id": "",
"event_type": "pay.succeeded",
"live_mode": false,
"pending_webhooks": 0,
"create_time": "2020-01-01T01:02:03+08:00",
"event_content": {
"refund_id": "",
"out_refund_id": "",
"payment_id": "",
"out_payment_id": "",
"total_amount": 0,
"refund_amount": 0,
"refund_reason": "",
"status": "",
"succeeded_time": "2021-06-08T10:34:56+08:00",
"created_time": "2021-06-08T10:34:56+08:00"
}
}

View File

@ -15,5 +15,5 @@
"pay_status": "PROCESSING", "pay_status": "PROCESSING",
"memo": "string", "memo": "string",
"attachment": "string", "attachment": "string",
"pay_time": "2022-11-15 13:25:18" "pay_time": "2019-08-24T14:15:22Z"
} }

View File

@ -0,0 +1,10 @@
{
"ent_id": "string",
"out_refund_id": "string",
"payment_id": "string",
"out_payment_id": "string",
"total_amount": 0,
"refund_amount": 0,
"refund_reason": "string",
"server_notify_url": "string"
}

View File

@ -0,0 +1,12 @@
{
"refund_id": "string",
"out_refund_id": "string",
"payment_id": "string",
"out_payment_id": "string",
"total_amount": 0,
"refund_amount": 0,
"status": "INIT",
"refund_reason": "string",
"succeeded_time": "2019-08-24T14:15:22Z",
"created_time": "2019-08-24T14:15:22Z"
}

View File

@ -0,0 +1,12 @@
{
"refund_id": "string",
"out_refund_id": "string",
"payment_id": "string",
"out_payment_id": "string",
"total_amount": 0,
"refund_amount": 0,
"status": "INIT",
"refund_reason": "string",
"succeeded_time": "2019-08-24T14:15:22Z",
"created_time": "2019-08-24T14:15:22Z"
}

View File

@ -0,0 +1,12 @@
{
"refund_id": "string",
"out_refund_id": "string",
"payment_id": "string",
"out_payment_id": "string",
"total_amount": 0,
"refund_amount": 0,
"status": "INIT",
"refund_reason": "string",
"succeeded_time": "2019-08-24T14:15:22Z",
"created_time": "2019-08-24T14:15:22Z"
}