feat(tenpayv3): 新增服务商批量转账到零钱相关 API 封装

This commit is contained in:
Fu Diwei
2021-07-19 22:05:59 +08:00
parent cee0e743e9
commit d74cc8074e
24 changed files with 921 additions and 20 deletions

View File

@@ -109,6 +109,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter5_1_19.shtml </para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_9_3.shtml </para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/transfer/chapter4_3.shtml </para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/transfer_partner/chapter4_3.shtml </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>

View File

@@ -18,6 +18,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
/// <para>异步调用 [GET] /ecommerce/fund/balance/{sub_mchid} 接口。</para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_7_1.shtml </para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_8_1.shtml </para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/transfer_partner/chapter5_1.shtml </para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/transfer_partner/chapter5_2.shtml </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
@@ -40,6 +42,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
/// <summary>
/// <para>异步调用 [GET] /ecommerce/fund/enddaybalance/{sub_mchid} 接口。</para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_7_2.shtml </para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/transfer_partner/chapter5_3.shtml </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>

View File

@@ -17,6 +17,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
/// <summary>
/// <para>异步调用 [POST] /ecommerce/fund/withdraw 接口。</para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_8_2.shtml </para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/transfer_partner/chapter6_1.shtml </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
@@ -37,6 +38,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
/// <summary>
/// <para>异步调用 [GET] /ecommerce/fund/withdraw/out-request-no/{out_request_no} 接口。</para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_8_3.shtml </para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/transfer_partner/chapter6_2.shtml </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
@@ -57,6 +59,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
/// <summary>
/// <para>异步调用 [GET] /ecommerce/fund/withdraw/{withdraw_id} 接口。</para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_8_3.shtml </para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/transfer_partner/chapter6_2.shtml </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>

View File

@@ -17,12 +17,13 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
/// <summary>
/// <para>异步调用 [GET] /merchantfund/merchant/income-records 接口。</para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/transfer/chapter3_7.shtml </para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/transfer/chapter3_7.shtml </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.QueryMerchantFundIncomeRecordsResponse> ExecuteQueryMerchantFundIncomeRecordsAsync(this WechatTenpayClient client, Models.QueryMerchantFundIncomeRecordsRequest request, CancellationToken cancellationToken = default)
public static async Task<Models.QueryMerchantFundMerchantIncomeRecordsResponse> ExecuteQueryMerchantFundMerchantIncomeRecordsAsync(this WechatTenpayClient client, Models.QueryMerchantFundMerchantIncomeRecordsRequest request, CancellationToken cancellationToken = default)
{
if (client is null) throw new ArgumentNullException(nameof(client));
if (request is null) throw new ArgumentNullException(nameof(request));
@@ -36,7 +37,33 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
if (request.Offset.HasValue)
flurlReq.SetQueryParam("offset", request.Offset);
return await client.SendRequestWithJsonAsync<Models.QueryMerchantFundIncomeRecordsResponse>(flurlReq, cancellationToken: cancellationToken);
return await client.SendRequestWithJsonAsync<Models.QueryMerchantFundMerchantIncomeRecordsResponse>(flurlReq, cancellationToken: cancellationToken);
}
/// <summary>
/// <para>异步调用 [GET] /merchantfund/partner/income-records 接口。</para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/transfer_partner/chapter3_6.shtml </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.QueryMerchantFundPartnerIncomeRecordsResponse> ExecuteQueryMerchantFundPartnerIncomeRecordsAsync(this WechatTenpayClient client, Models.QueryMerchantFundPartnerIncomeRecordsRequest 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, "merchantfund", "partner", "income-records")
.SetQueryParam("sub_mchid", request.SubMerchantId)
.SetQueryParam("account_type", request.AccountType)
.SetQueryParam("date", request.DateString)
.SetQueryParam("limit", request.Limit);
if (request.Offset.HasValue)
flurlReq.SetQueryParam("offset", request.Offset);
return await client.SendRequestWithJsonAsync<Models.QueryMerchantFundPartnerIncomeRecordsResponse>(flurlReq, cancellationToken: cancellationToken);
}
}
}

View File

@@ -74,6 +74,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
/// <summary>
/// <para>异步调用 [GET] /merchant/fund/withdraw/bill-type/{bill_type} 接口。</para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_8_4.shtml </para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/transfer_partner/chapter6_3.shtml </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>

View File

@@ -0,0 +1,133 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Flurl;
using Flurl.Http;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
{
/// <summary>
/// 为 <see cref="WechatTenpayClient"/> 提供服务商转账相关的 API 扩展方法。
/// </summary>
public static class WechatTenpayClientExecutePartnerTransferExtensions
{
#region Batches
/// <summary>
/// <para>异步调用 [POST] /partner-transfer/batches 接口。</para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/transfer_partner/chapter3_1.shtml </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.CreatePartnerTransferBatchResponse> ExecuteCreatePartnerTransferBatchAsync(this WechatTenpayClient client, Models.CreatePartnerTransferBatchRequest 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, "partner-transfer", "batches");
return await client.SendRequestWithJsonAsync<Models.CreatePartnerTransferBatchResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
}
/// <summary>
/// <para>异步调用 [GET] /partner-transfer/batches/batch-id/{batch_id} 接口。</para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/transfer_partner/chapter3_2.shtml </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.GetPartnerTransferBatchByBatchIdResponse> ExecuteGetPartnerTransferBatchByBatchIdAsync(this WechatTenpayClient client, Models.GetPartnerTransferBatchByBatchIdRequest 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, "partner-transfer", "batches", "batch-id", request.BatchId)
.SetQueryParam("need_query_detail", request.RequireQueryDetail);
if (request.Offset.HasValue)
flurlReq.SetQueryParam("offset", request.Offset.Value);
if (request.Limit.HasValue)
flurlReq.SetQueryParam("limit", request.Limit.Value);
if (!string.IsNullOrEmpty(request.DetailStatus))
flurlReq.SetQueryParam("detail_status", request.DetailStatus);
return await client.SendRequestWithJsonAsync<Models.GetPartnerTransferBatchByBatchIdResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
}
/// <summary>
/// <para>异步调用 [GET] /partner-transfer/batches/batch-id/{batch_id}/details/detail-id/{detail_id} 接口。</para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/transfer_partner/chapter3_3.shtml </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.GetPartnerTransferBatchDetailByDetailIdResponse> ExecuteGetPartnerTransferBatchDetailByDetailIdAsync(this WechatTenpayClient client, Models.GetPartnerTransferBatchDetailByDetailIdRequest 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, "partner-transfer", "batches", "batch-id", request.BatchId, "details", "detail-id", request.DetailId);
return await client.SendRequestWithJsonAsync<Models.GetPartnerTransferBatchDetailByDetailIdResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
}
/// <summary>
/// <para>异步调用 [GET] /partner-transfer/batches/out-batch-no/{out_batch_no} 接口。</para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/transfer_partner/chapter3_4.shtml </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.GetPartnerTransferBatchByOutBatchNumberResponse> ExecuteGetPartnerTransferBatchByOutBatchNumberAsync(this WechatTenpayClient client, Models.GetPartnerTransferBatchByOutBatchNumberRequest 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, "partner-transfer", "batches", "out-batch-no", request.OutBatchNumber)
.SetQueryParam("need_query_detail", request.RequireQueryDetail);
if (request.Offset.HasValue)
flurlReq.SetQueryParam("offset", request.Offset.Value);
if (request.Limit.HasValue)
flurlReq.SetQueryParam("limit", request.Limit.Value);
if (!string.IsNullOrEmpty(request.DetailStatus))
flurlReq.SetQueryParam("detail_status", request.DetailStatus);
return await client.SendRequestWithJsonAsync<Models.GetPartnerTransferBatchByOutBatchNumberResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
}
/// <summary>
/// <para>异步调用 [GET] /partner-transfer/batches/out-batch-no/{out_batch_no}/details/out-detail-no/{out_detail_no} 接口。</para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/transfer_partner/chapter3_5.shtml </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.GetPartnerTransferBatchDetailByOutDetailNumberResponse> ExecuteGetPartnerTransferBatchDetailByOutDetailNumberAsync(this WechatTenpayClient client, Models.GetPartnerTransferBatchDetailByOutDetailNumberRequest 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, "partner-transfer", "batches", "out-batch-no", request.OutBatchNumber, "details", "out-detail-no", request.OutDetailNumber);
return await client.SendRequestWithJsonAsync<Models.GetPartnerTransferBatchDetailByOutDetailNumberResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
}
#endregion
}
}

View File

@@ -135,6 +135,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
/// <summary>
/// <para>异步调用 [POST] /transfer/bill-receipt 接口。</para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/transfer/chapter4_1.shtml </para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/transfer_partner/chapter4_1.shtml </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
@@ -154,6 +155,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
/// <summary>
/// <para>异步调用 [GET] /transfer/bill-receipt/{out_batch_no} 接口。</para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/transfer/chapter4_2.shtml </para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/transfer_partner/chapter4_2.shtml </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
@@ -175,6 +177,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
/// <summary>
/// <para>异步调用 [POST] /transfer-detail/electronic-receipts 接口。</para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/transfer/chapter4_4.shtml </para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/transfer_partner/chapter4_4.shtml </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
@@ -194,6 +197,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
/// <summary>
/// <para>异步调用 [GET] /transfer-detail/electronic-receipts 接口。</para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/transfer/chapter4_5.shtml </para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/transfer_partner/chapter4_5.shtml </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>

View File

@@ -381,5 +381,75 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
return response;
}
/// <summary>
/// <para>解密响应中返回的敏感数据。该方法会改变传入的响应信息。</para>
/// </summary>
/// <param name="client"></param>
/// <param name="response"></param>
/// <returns></returns>
public static Models.GetPartnerTransferBatchDetailByOutDetailNumberResponse DecryptResponseEncryptedData(this WechatTenpayClient client, ref Models.GetPartnerTransferBatchDetailByOutDetailNumberResponse response)
{
if (client == null) throw new ArgumentNullException(nameof(client));
if (response == null) throw new ArgumentNullException(nameof(response));
if (string.IsNullOrEmpty(client.WechatMerchantCertPrivateKey))
throw new Exceptions.WechatTenpayResponseDecryptionException("Decrypt response failed, because of there is no merchant private key.");
if (!response.IsSuccessful())
throw new Exceptions.WechatTenpayResponseDecryptionException("Decrypt response failed, because of the response is not successful.");
if (!string.IsNullOrEmpty(response.UserName))
{
try
{
response.UserName = Utilities.RSAUtility.DecryptWithECB(
client.WechatMerchantCertPrivateKey,
response.UserName
);
}
catch (Exception ex)
{
throw new Exceptions.WechatTenpayResponseDecryptionException("Decrypt response failed.", ex);
}
}
return response;
}
/// <summary>
/// <para>解密响应中返回的敏感数据。该方法会改变传入的响应信息。</para>
/// </summary>
/// <param name="client"></param>
/// <param name="response"></param>
/// <returns></returns>
public static Models.GetPartnerTransferBatchDetailByDetailIdResponse DecryptResponseEncryptedData(this WechatTenpayClient client, ref Models.GetPartnerTransferBatchDetailByDetailIdResponse response)
{
if (client == null) throw new ArgumentNullException(nameof(client));
if (response == null) throw new ArgumentNullException(nameof(response));
if (string.IsNullOrEmpty(client.WechatMerchantCertPrivateKey))
throw new Exceptions.WechatTenpayResponseDecryptionException("Decrypt response failed, because of there is no merchant private key.");
if (!response.IsSuccessful())
throw new Exceptions.WechatTenpayResponseDecryptionException("Decrypt response failed, because of the response is not successful.");
if (!string.IsNullOrEmpty(response.UserName))
{
try
{
response.UserName = Utilities.RSAUtility.DecryptWithECB(
client.WechatMerchantCertPrivateKey,
response.UserName
);
}
catch (Exception ex)
{
throw new Exceptions.WechatTenpayResponseDecryptionException("Decrypt response failed.", ex);
}
}
return response;
}
}
}