feat(work): 新增收银台收款工具相关接口

This commit is contained in:
Fu Diwei
2025-09-16 20:30:22 +08:00
parent 8db3a17f64
commit 2c9a54d2b1
30 changed files with 1970 additions and 12 deletions

View File

@@ -0,0 +1,256 @@
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;
using Newtonsoft.Json.Linq;
namespace SKIT.FlurlHttpClient.Wechat.Work
{
public static class WechatWorkClientExecuteCgibinPayToolExtensions
{
#region Invoice
/// <summary>
/// <para>异步调用 [POST] /cgi-bin/paytool/get_invoice_list 接口。</para>
/// <para>
/// REF: <br/>
/// <![CDATA[ https://developer.work.weixin.qq.com/document/path/99436 ]]>
/// </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.CgibinPayToolGetInvoiceListResponse> ExecuteCgibinPayToolGetInvoiceListAsync(this WechatWorkClient client, Models.CgibinPayToolGetInvoiceListRequest 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
.CreateFlurlRequest(request, HttpMethod.Post, "cgi-bin", "paytool", "get_invoice_list")
.SetQueryParam("provider_access_token", request.ProviderAccessToken);
return await client.SendFlurlRequestAsJsonAsync<Models.CgibinPayToolGetInvoiceListResponse>(flurlReq, data: request, cancellationToken: cancellationToken).ConfigureAwait(false);
}
/// <summary>
/// <para>异步调用 [POST] /cgi-bin/paytool/mark_invoice_status 接口。</para>
/// <para>
/// REF: <br/>
/// <![CDATA[ https://developer.work.weixin.qq.com/document/path/99437 ]]>
/// </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.CgibinPayToolMarkInvoiceStatusResponse> ExecuteCgibinPayToolMarkInvoiceStatusAsync(this WechatWorkClient client, Models.CgibinPayToolMarkInvoiceStatusRequest 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
.CreateFlurlRequest(request, HttpMethod.Post, "cgi-bin", "paytool", "mark_invoice_status")
.SetQueryParam("provider_access_token", request.ProviderAccessToken);
return await client.SendFlurlRequestAsJsonAsync<Models.CgibinPayToolMarkInvoiceStatusResponse>(flurlReq, data: request, cancellationToken: cancellationToken).ConfigureAwait(false);
}
#endregion
#region Order
private static T PreprocessRequest<T>(WechatWorkClient client, ref T request)
where T : Models.CgibinPayToolOrderRequestBase, new()
{
if (client is null) throw new ArgumentNullException(nameof(request));
if (request is null) throw new ArgumentNullException(nameof(request));
if (request.NonceString is null)
{
request.NonceString = Guid.NewGuid().ToString("N");
}
if (request.Timestamp is null)
{
request.Timestamp = DateTimeOffset.Now.ToLocalTime().ToUnixTimeSeconds();
}
if (request.Signature is null)
{
if (string.IsNullOrEmpty(client.Credentials.PayToolApiSecret))
throw new WechatWorkException("Could not sign request, because paytool API secret is missing.");
Func<string, JToken, List<string>> flatten = default!;
flatten = (path, token) =>
{
List<string> results = new List<string>();
switch (token.Type)
{
case JTokenType.Null:
break;
case JTokenType.Integer:
case JTokenType.Float:
case JTokenType.String:
{
string key = path;
string val = token.ToString();
if (string.IsNullOrEmpty(key))
throw new InvalidOperationException();
if (!string.IsNullOrEmpty(val))
results.Add($"{key}={val}");
}
break;
case JTokenType.Boolean:
{
string key = path;
string val = token.ToString().ToLower();
if (string.IsNullOrEmpty(key))
throw new InvalidOperationException();
results.Add($"{key}={val}");
}
break;
case JTokenType.Array:
{
foreach (var item in (JArray)token)
{
results.AddRange(flatten(path, item));
}
}
break;
case JTokenType.Object:
{
foreach (JProperty prop in ((JObject)token).Properties())
{
results.AddRange(flatten(prop.Name, prop.Value));
}
}
break;
default:
throw new InvalidOperationException();
}
return results;
};
List<string> tmp = flatten(string.Empty, JObject.Parse(client.JsonSerializer.Serialize(request)));
tmp.Sort(StringComparer.Ordinal);
byte[] keyBytes = Encoding.UTF8.GetBytes(client.Credentials.PayToolApiSecret!);
byte[] msgBytes = Encoding.UTF8.GetBytes(string.Join("&", tmp));
byte[] signBytes = Utilities.HMACUtility.HashWithSHA256(keyBytes, msgBytes);
request.Signature = Convert.ToBase64String(signBytes);
}
return request;
}
/// <summary>
/// <para>异步调用 [POST] /cgi-bin/paytool/open_order 接口。</para>
/// <para>
/// REF: <br/>
/// <![CDATA[ https://developer.work.weixin.qq.com/document/path/98045 ]]>
/// </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.CgibinPayToolOpenOrderResponse> ExecuteCgibinPayToolOpenOrderAsync(this WechatWorkClient client, Models.CgibinPayToolOpenOrderRequest request, CancellationToken cancellationToken = default)
{
if (client is null) throw new ArgumentNullException(nameof(client));
if (request is null) throw new ArgumentNullException(nameof(request));
PreprocessRequest(client, ref request);
IFlurlRequest flurlReq = client
.CreateFlurlRequest(request, HttpMethod.Post, "cgi-bin", "paytool", "open_order")
.SetQueryParam("provider_access_token", request.ProviderAccessToken);
return await client.SendFlurlRequestAsJsonAsync<Models.CgibinPayToolOpenOrderResponse>(flurlReq, data: request, cancellationToken: cancellationToken).ConfigureAwait(false);
}
/// <summary>
/// <para>异步调用 [POST] /cgi-bin/paytool/close_order 接口。</para>
/// <para>
/// REF: <br/>
/// <![CDATA[ https://developer.work.weixin.qq.com/document/path/98046 ]]>
/// </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.CgibinPayToolCloseOrderResponse> ExecuteCgibinPayToolCloseOrderAsync(this WechatWorkClient client, Models.CgibinPayToolCloseOrderRequest request, CancellationToken cancellationToken = default)
{
if (client is null) throw new ArgumentNullException(nameof(client));
if (request is null) throw new ArgumentNullException(nameof(request));
PreprocessRequest(client, ref request);
IFlurlRequest flurlReq = client
.CreateFlurlRequest(request, HttpMethod.Post, "cgi-bin", "paytool", "close_order")
.SetQueryParam("provider_access_token", request.ProviderAccessToken);
return await client.SendFlurlRequestAsJsonAsync<Models.CgibinPayToolCloseOrderResponse>(flurlReq, data: request, cancellationToken: cancellationToken).ConfigureAwait(false);
}
/// <summary>
/// <para>异步调用 [POST] /cgi-bin/paytool/get_order_list 接口。</para>
/// <para>
/// REF: <br/>
/// <![CDATA[ https://developer.work.weixin.qq.com/document/path/98053 ]]>
/// </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.CgibinPayToolGetOrderListResponse> ExecuteCgibinPayToolGetOrderListAsync(this WechatWorkClient client, Models.CgibinPayToolGetOrderListRequest request, CancellationToken cancellationToken = default)
{
if (client is null) throw new ArgumentNullException(nameof(client));
if (request is null) throw new ArgumentNullException(nameof(request));
PreprocessRequest(client, ref request);
IFlurlRequest flurlReq = client
.CreateFlurlRequest(request, HttpMethod.Post, "cgi-bin", "paytool", "get_order_list")
.SetQueryParam("provider_access_token", request.ProviderAccessToken);
return await client.SendFlurlRequestAsJsonAsync<Models.CgibinPayToolGetOrderListResponse>(flurlReq, data: request, cancellationToken: cancellationToken).ConfigureAwait(false);
}
/// <summary>
/// <para>异步调用 [POST] /cgi-bin/paytool/get_order_detail 接口。</para>
/// <para>
/// REF: <br/>
/// <![CDATA[ https://developer.work.weixin.qq.com/document/path/98054 ]]>
/// </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.CgibinPayToolGetOrderDetailResponse> ExecuteCgibinPayToolGetOrderDetailAsync(this WechatWorkClient client, Models.CgibinPayToolGetOrderDetailRequest request, CancellationToken cancellationToken = default)
{
if (client is null) throw new ArgumentNullException(nameof(client));
if (request is null) throw new ArgumentNullException(nameof(request));
PreprocessRequest(client, ref request);
IFlurlRequest flurlReq = client
.CreateFlurlRequest(request, HttpMethod.Post, "cgi-bin", "paytool", "get_order_detail")
.SetQueryParam("provider_access_token", request.ProviderAccessToken);
return await client.SendFlurlRequestAsJsonAsync<Models.CgibinPayToolGetOrderDetailResponse>(flurlReq, data: request, cancellationToken: cancellationToken).ConfigureAwait(false);
}
#endregion
}
}

View File

@@ -259,11 +259,11 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.Models
public string? State { get; set; }
/// <summary>
/// 获取或设置发起添加的成员账号。
/// 获取或设置操作人的成员账号。
/// </summary>
[Newtonsoft.Json.JsonProperty("oper_userid")]
[System.Text.Json.Serialization.JsonPropertyName("oper_userid")]
public string? OperateUserId { get; set; }
public string? OperatorUserId { get; set; }
/// <summary>
/// 获取或设置视频号信息。

View File

@@ -0,0 +1,43 @@
namespace SKIT.FlurlHttpClient.Wechat.Work.Models
{
/// <summary>
/// <para>表示 [POST] /cgi-bin/paytool/get_invoice_list 接口的请求。</para>
/// </summary>
public class CgibinPayToolGetInvoiceListRequest : WechatWorkRequest
{
/// <summary>
/// 获取或设置服务商 AccessToken。
/// </summary>
[Newtonsoft.Json.JsonIgnore]
[System.Text.Json.Serialization.JsonIgnore]
public string ProviderAccessToken { get; set; } = string.Empty;
/// <summary>
/// 获取或设置开票时间开始时间戳。
/// </summary>
[Newtonsoft.Json.JsonProperty("start_time")]
[System.Text.Json.Serialization.JsonPropertyName("start_time")]
public long? StartTimestamp { get; set; }
/// <summary>
/// 获取或设置开票时间结束时间戳。
/// </summary>
[Newtonsoft.Json.JsonProperty("end_time")]
[System.Text.Json.Serialization.JsonPropertyName("end_time")]
public long? EndTimestamp { get; set; }
/// <summary>
/// 获取或设置分页游标。
/// </summary>
[Newtonsoft.Json.JsonProperty("cursor")]
[System.Text.Json.Serialization.JsonPropertyName("cursor")]
public string? Cursor { get; set; }
/// <summary>
/// 获取或设置分页每页数量。
/// </summary>
[Newtonsoft.Json.JsonProperty("limit")]
[System.Text.Json.Serialization.JsonPropertyName("limit")]
public int? Limit { get; set; }
}
}

View File

@@ -0,0 +1,170 @@
namespace SKIT.FlurlHttpClient.Wechat.Work.Models
{
/// <summary>
/// <para>表示 [POST] /cgi-bin/paytool/get_invoice_list 接口的响应。</para>
/// </summary>
public class CgibinPayToolGetInvoiceListResponse : WechatWorkResponse
{
public static class Types
{
public class Invoice
{
/// <summary>
/// 获取或设置开票订单号。
/// </summary>
[Newtonsoft.Json.JsonProperty("order_id")]
[System.Text.Json.Serialization.JsonPropertyName("order_id")]
public string OrderId { get; set; } = default!;
/// <summary>
/// 获取或设置客户企业 CorpId。
/// </summary>
[Newtonsoft.Json.JsonProperty("custom_corpid")]
[System.Text.Json.Serialization.JsonPropertyName("custom_corpid")]
public string? CustomCorpId { get; set; }
/// <summary>
/// 获取或设置申请开票时间戳。
/// </summary>
[Newtonsoft.Json.JsonProperty("apply_time")]
[System.Text.Json.Serialization.JsonPropertyName("apply_time")]
public long ApplyTimestamp { get; set; }
/// <summary>
/// 获取或设置发票类型。
/// </summary>
[Newtonsoft.Json.JsonProperty("invoice_type")]
[System.Text.Json.Serialization.JsonPropertyName("invoice_type")]
public int InvoiceType { get; set; }
/// <summary>
/// 获取或设置实付金额(单位:分)。
/// </summary>
[Newtonsoft.Json.JsonProperty("paid_price")]
[System.Text.Json.Serialization.JsonPropertyName("paid_price")]
public int PaidPrice { get; set; }
/// <summary>
/// 获取或设置开票状态。
/// </summary>
[Newtonsoft.Json.JsonProperty("invoice_status")]
[System.Text.Json.Serialization.JsonPropertyName("invoice_status")]
public int InvoiceStatus { get; set; }
/// <summary>
/// 获取或设置发票抬头。
/// </summary>
[Newtonsoft.Json.JsonProperty("invoice_title")]
[System.Text.Json.Serialization.JsonPropertyName("invoice_title")]
public string InvoiceTitle { get; set; } = default!;
/// <summary>
/// 获取或设置纳税人识别号。
/// </summary>
[Newtonsoft.Json.JsonProperty("tax_number")]
[System.Text.Json.Serialization.JsonPropertyName("tax_number")]
public string TaxNumber { get; set; } = default!;
/// <summary>
/// 获取或设置发票收取方式。
/// </summary>
[Newtonsoft.Json.JsonProperty("send_way")]
[System.Text.Json.Serialization.JsonPropertyName("send_way")]
public int SendWay { get; set; }
/// <summary>
/// 获取或设置联系人姓名。
/// </summary>
[Newtonsoft.Json.JsonProperty("contact_name")]
[System.Text.Json.Serialization.JsonPropertyName("contact_name")]
public string? ContactName { get; set; }
/// <summary>
/// 获取或设置联系电话。
/// </summary>
[Newtonsoft.Json.JsonProperty("contact_tel")]
[System.Text.Json.Serialization.JsonPropertyName("contact_tel")]
public string? ContactTeleNumber { get; set; }
/// <summary>
/// 获取或设置收件地址。
/// </summary>
[Newtonsoft.Json.JsonProperty("contact_addr")]
[System.Text.Json.Serialization.JsonPropertyName("contact_addr")]
public string? ContactAddress { get; set; }
/// <summary>
/// 获取或设置邮政编码。
/// </summary>
[Newtonsoft.Json.JsonProperty("contact_postcode")]
[System.Text.Json.Serialization.JsonPropertyName("contact_postcode")]
public string? ContactPostCode { get; set; }
/// <summary>
/// 获取或设置电子邮箱。
/// </summary>
[Newtonsoft.Json.JsonProperty("receive_email")]
[System.Text.Json.Serialization.JsonPropertyName("receive_email")]
public string? ReceiveEmail { get; set; }
/// <summary>
/// 获取或设置公司地址。
/// </summary>
[Newtonsoft.Json.JsonProperty("company_addr")]
[System.Text.Json.Serialization.JsonPropertyName("company_addr")]
public string CompanyAddress { get; set; } = default!;
/// <summary>
/// 获取或设置公司电话。
/// </summary>
[Newtonsoft.Json.JsonProperty("company_tel")]
[System.Text.Json.Serialization.JsonPropertyName("company_tel")]
public string CompanyTeleNumber { get; set; } = default!;
/// <summary>
/// 获取或设置开户行。
/// </summary>
[Newtonsoft.Json.JsonProperty("bank_name")]
[System.Text.Json.Serialization.JsonPropertyName("bank_name")]
public string BankName { get; set; } = default!;
/// <summary>
/// 获取或设置银行账号。
/// </summary>
[Newtonsoft.Json.JsonProperty("bank_account_number")]
[System.Text.Json.Serialization.JsonPropertyName("bank_account_number")]
public string BankAccountNumber { get; set; } = default!;
/// <summary>
/// 获取或设置开票备注。
/// </summary>
[Newtonsoft.Json.JsonProperty("invoice_note")]
[System.Text.Json.Serialization.JsonPropertyName("invoice_note")]
public string InvoiceNotes { get; set; } = default!;
}
}
/// <summary>
/// 获取或设置发票列表。
/// </summary>
[Newtonsoft.Json.JsonProperty("invoice_list")]
[System.Text.Json.Serialization.JsonPropertyName("invoice_list")]
public Types.Invoice[] InvoiceList { get; set; } = default!;
/// <summary>
/// 获取或设置分页游标。
/// </summary>
[Newtonsoft.Json.JsonProperty("next_cursor")]
[System.Text.Json.Serialization.JsonPropertyName("next_cursor")]
public string? NextCursor { get; set; }
/// <summary>
/// 获取或设置是否还有更多数据。
/// </summary>
[Newtonsoft.Json.JsonProperty("has_more")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.Common.NumericalBooleanConverter))]
[System.Text.Json.Serialization.JsonPropertyName("has_more")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.Common.NumericalBooleanConverter))]
public bool HasMore { get; set; }
}
}

View File

@@ -0,0 +1,43 @@
namespace SKIT.FlurlHttpClient.Wechat.Work.Models
{
/// <summary>
/// <para>表示 [POST] /cgi-bin/paytool/mark_invoice_status 接口的请求。</para>
/// </summary>
public class CgibinPayToolMarkInvoiceStatusRequest : WechatWorkRequest
{
/// <summary>
/// 获取或设置服务商 AccessToken。
/// </summary>
[Newtonsoft.Json.JsonIgnore]
[System.Text.Json.Serialization.JsonIgnore]
public string ProviderAccessToken { get; set; } = string.Empty;
/// <summary>
/// 获取或设置开票订单号。
/// </summary>
[Newtonsoft.Json.JsonProperty("order_id")]
[System.Text.Json.Serialization.JsonPropertyName("order_id")]
public string OrderId { get; set; } = string.Empty;
/// <summary>
/// 获取或设置操作人的成员账号。
/// </summary>
[Newtonsoft.Json.JsonProperty("oper_userid")]
[System.Text.Json.Serialization.JsonPropertyName("oper_userid")]
public string? OperatorUserId { get; set; }
/// <summary>
/// 获取或设置开票状态。
/// </summary>
[Newtonsoft.Json.JsonProperty("invoice_status")]
[System.Text.Json.Serialization.JsonPropertyName("invoice_status")]
public int InvoiceStatus { get; set; }
/// <summary>
/// 获取或设置开票备注。
/// </summary>
[Newtonsoft.Json.JsonProperty("invoice_note")]
[System.Text.Json.Serialization.JsonPropertyName("invoice_note")]
public string InvoiceNotes { get; set; } = string.Empty;
}
}

View File

@@ -0,0 +1,9 @@
namespace SKIT.FlurlHttpClient.Wechat.Work.Models
{
/// <summary>
/// <para>表示 [POST] /cgi-bin/paytool/mark_invoice_status 接口的响应。</para>
/// </summary>
public class CgibinPayToolMarkInvoiceStatusResponse : WechatWorkResponse
{
}
}

View File

@@ -0,0 +1,15 @@
namespace SKIT.FlurlHttpClient.Wechat.Work.Models
{
/// <summary>
/// <para>表示 [POST] /cgi-bin/paytool/close_order 接口的请求。</para>
/// </summary>
public class CgibinPayToolCloseOrderRequest : CgibinPayToolOrderRequestBase
{
/// <summary>
/// 获取或设置收款订单号。
/// </summary>
[Newtonsoft.Json.JsonProperty("order_id")]
[System.Text.Json.Serialization.JsonPropertyName("order_id")]
public string OrderId { get; set; } = string.Empty;
}
}

View File

@@ -0,0 +1,9 @@
namespace SKIT.FlurlHttpClient.Wechat.Work.Models
{
/// <summary>
/// <para>表示 [POST] /cgi-bin/paytool/close_order 接口的响应。</para>
/// </summary>
public class CgibinPayToolCloseOrderResponse : WechatWorkResponse
{
}
}

View File

@@ -0,0 +1,15 @@
namespace SKIT.FlurlHttpClient.Wechat.Work.Models
{
/// <summary>
/// <para>表示 [POST] /cgi-bin/paytool/get_order_detail 接口的请求。</para>
/// </summary>
public class CgibinPayToolGetOrderDetailRequest : CgibinPayToolOrderRequestBase
{
/// <summary>
/// 获取或设置收款订单号。
/// </summary>
[Newtonsoft.Json.JsonProperty("order_id")]
[System.Text.Json.Serialization.JsonPropertyName("order_id")]
public string OrderId { get; set; } = string.Empty;
}
}

View File

@@ -0,0 +1,446 @@
namespace SKIT.FlurlHttpClient.Wechat.Work.Models
{
/// <summary>
/// <para>表示 [POST] /cgi-bin/paytool/get_order_detail 接口的响应。</para>
/// </summary>
public class CgibinPayToolGetOrderDetailResponse : WechatWorkResponse
{
public static class Types
{
public class Order
{
public static class Types
{
public class Product
{
public static class Types
{
public class ProductBase
{
/// <summary>
/// 获取或设置购买类型。
/// </summary>
[Newtonsoft.Json.JsonProperty("order_type")]
[System.Text.Json.Serialization.JsonPropertyName("order_type")]
public int OrderType { get; set; }
/// <summary>
/// 获取或设置是否推送确认提醒。
/// </summary>
[Newtonsoft.Json.JsonProperty("notify_custom_corp")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.Common.NumericalBooleanConverter))]
[System.Text.Json.Serialization.JsonPropertyName("notify_custom_corp")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.Common.NumericalBooleanConverter))]
public bool? IsNotifyCustomCorp { get; set; }
}
public class ThirdPartyApp : ProductBase
{
public static class Types
{
public class BuyInfo
{
public static class Types
{
public class DiscountInfo
{
/// <summary>
/// 获取或设置优惠类型。
/// </summary>
[Newtonsoft.Json.JsonProperty("discount_type")]
[System.Text.Json.Serialization.JsonPropertyName("discount_type")]
public int DiscountType { get; set; }
/// <summary>
/// 获取或设置优惠金额(单位:分)。
/// </summary>
[Newtonsoft.Json.JsonProperty("discount_amount")]
[System.Text.Json.Serialization.JsonPropertyName("discount_amount")]
public int? DiscountAmount { get; set; }
/// <summary>
/// 获取或设置优惠折扣(单位:百分数)。
/// </summary>
[Newtonsoft.Json.JsonProperty("discount_ratio")]
[System.Text.Json.Serialization.JsonPropertyName("discount_ratio")]
public int? DiscountRatio { get; set; }
/// <summary>
/// 获取或设置优惠原因。
/// </summary>
[Newtonsoft.Json.JsonProperty("discount_remarks")]
[System.Text.Json.Serialization.JsonPropertyName("discount_remarks")]
public string? DiscountRemarks { get; set; }
}
}
/// <summary>
/// 获取或设置套件 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("suiteid")]
[System.Text.Json.Serialization.JsonPropertyName("suiteid")]
public string SuiteId { get; set; } = default!;
/// <summary>
/// 获取或设置旧版应用 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("appid")]
[System.Text.Json.Serialization.JsonPropertyName("appid")]
public int? AppId { get; set; }
/// <summary>
/// 获取或设置版本号 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("edition_id")]
[System.Text.Json.Serialization.JsonPropertyName("edition_id")]
public string EditionId { get; set; } = default!;
/// <summary>
/// 获取或设置购买人数。
/// </summary>
[Newtonsoft.Json.JsonProperty("user_count")]
[System.Text.Json.Serialization.JsonPropertyName("user_count")]
public int? UserCount { get; set; }
/// <summary>
/// 获取或设置购买天数。
/// </summary>
[Newtonsoft.Json.JsonProperty("duration_days")]
[System.Text.Json.Serialization.JsonPropertyName("duration_days")]
public int? DurationDays { get; set; }
/// <summary>
/// 获取或设置生效日期字符串格式yyyyMMdd
/// </summary>
[Newtonsoft.Json.JsonProperty("take_effect_date")]
[System.Text.Json.Serialization.JsonPropertyName("take_effect_date")]
public string? TakeEffectDateString { get; set; }
/// <summary>
/// 获取或设置原价(单位:分)。
/// </summary>
[Newtonsoft.Json.JsonProperty("origin_price")]
[System.Text.Json.Serialization.JsonPropertyName("origin_price")]
public int OriginPrice { get; set; }
/// <summary>
/// 获取或设置现价(单位:分)。
/// </summary>
[Newtonsoft.Json.JsonProperty("paid_price")]
[System.Text.Json.Serialization.JsonPropertyName("paid_price")]
public int PaidPrice { get; set; }
}
}
/// <summary>
/// 获取或设置购买应用列表。
/// </summary>
[Newtonsoft.Json.JsonProperty("buy_info_list")]
[System.Text.Json.Serialization.JsonPropertyName("buy_info_list")]
public Types.BuyInfo[] BuyInfoList { get; set; } = default!;
}
public class CustomizedApp : ProductBase
{
public static class Types
{
public class BuyInfo
{
/// <summary>
/// 获取或设置套件 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("suiteid")]
[System.Text.Json.Serialization.JsonPropertyName("suiteid")]
public string SuiteId { get; set; } = default!;
/// <summary>
/// 获取或设置旧版应用 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("appid")]
[System.Text.Json.Serialization.JsonPropertyName("appid")]
public int? AppId { get; set; }
/// <summary>
/// 获取或设置购买人数。
/// </summary>
[Newtonsoft.Json.JsonProperty("user_count")]
[System.Text.Json.Serialization.JsonPropertyName("user_count")]
public int? UserCount { get; set; }
/// <summary>
/// 获取或设置购买天数。
/// </summary>
[Newtonsoft.Json.JsonProperty("duration_days")]
[System.Text.Json.Serialization.JsonPropertyName("duration_days")]
public int? DurationDays { get; set; }
/// <summary>
/// 获取或设置生效日期字符串格式yyyyMMdd
/// </summary>
[Newtonsoft.Json.JsonProperty("take_effect_date")]
[System.Text.Json.Serialization.JsonPropertyName("take_effect_date")]
public string? TakeEffectDateString { get; set; }
/// <summary>
/// 获取或设置原价(单位:分)。
/// </summary>
[Newtonsoft.Json.JsonProperty("origin_price")]
[System.Text.Json.Serialization.JsonPropertyName("origin_price")]
public int OriginPrice { get; set; }
/// <summary>
/// 获取或设置现价(单位:分)。
/// </summary>
[Newtonsoft.Json.JsonProperty("paid_price")]
[System.Text.Json.Serialization.JsonPropertyName("paid_price")]
public int PaidPrice { get; set; }
}
}
/// <summary>
/// 获取或设置购买应用列表。
/// </summary>
[Newtonsoft.Json.JsonProperty("buy_info_list")]
[System.Text.Json.Serialization.JsonPropertyName("buy_info_list")]
public Types.BuyInfo[] BuyInfoList { get; set; } = default!;
}
public class PromotionCase : ProductBase
{
public static class Types
{
public class BuyInfo
{
/// <summary>
/// 获取或设置套件 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("suiteid")]
[System.Text.Json.Serialization.JsonPropertyName("suiteid")]
public string SuiteId { get; set; } = default!;
/// <summary>
/// 获取或设置旧版应用 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("appid")]
[System.Text.Json.Serialization.JsonPropertyName("appid")]
public int? AppId { get; set; }
/// <summary>
/// 获取或设置版本号 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("edition_id")]
[System.Text.Json.Serialization.JsonPropertyName("edition_id")]
public string EditionId { get; set; } = default!;
/// <summary>
/// 获取或设置购买人数。
/// </summary>
[Newtonsoft.Json.JsonProperty("user_count")]
[System.Text.Json.Serialization.JsonPropertyName("user_count")]
public int? UserCount { get; set; }
/// <summary>
/// 获取或设置生效日期字符串格式yyyyMMdd
/// </summary>
[Newtonsoft.Json.JsonProperty("take_effect_date")]
[System.Text.Json.Serialization.JsonPropertyName("take_effect_date")]
public string? TakeEffectDateString { get; set; }
}
}
/// <summary>
/// 获取或设置行业方案 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("case_id")]
[System.Text.Json.Serialization.JsonPropertyName("case_id")]
public string CaseId { get; set; } = default!;
/// <summary>
/// 获取或设置行业方案版本名称
/// </summary>
[Newtonsoft.Json.JsonProperty("promotion_edition_name")]
[System.Text.Json.Serialization.JsonPropertyName("promotion_edition_name")]
public string PromotionEditionName { get; set; } = default!;
/// <summary>
/// 获取或设置购买天数。
/// </summary>
[Newtonsoft.Json.JsonProperty("duration_days")]
[System.Text.Json.Serialization.JsonPropertyName("duration_days")]
public int? DurationDays { get; set; }
/// <summary>
/// 获取或设置购买应用列表。
/// </summary>
[Newtonsoft.Json.JsonProperty("buy_info_list")]
[System.Text.Json.Serialization.JsonPropertyName("buy_info_list")]
public Types.BuyInfo[]? BuyInfoList { get; set; }
}
}
/// <summary>
/// 获取或设置第三方应用商品信息。
/// </summary>
[Newtonsoft.Json.JsonProperty("third_app")]
[System.Text.Json.Serialization.JsonPropertyName("third_app")]
public Types.ThirdPartyApp? ThirdPartyApp { get; set; }
/// <summary>
/// 获取或设置代开发应用商品信息。
/// </summary>
[Newtonsoft.Json.JsonProperty("customized_app")]
[System.Text.Json.Serialization.JsonPropertyName("customized_app")]
public Types.CustomizedApp? CustomizedApp { get; set; }
/// <summary>
/// 获取或设置行业解决方案商品信息。
/// </summary>
[Newtonsoft.Json.JsonProperty("promotion_case")]
[System.Text.Json.Serialization.JsonPropertyName("promotion_case")]
public Types.PromotionCase? PromotionCase { get; set; }
}
}
/// <summary>
/// 获取或设置收款订单号。
/// </summary>
[Newtonsoft.Json.JsonProperty("order_id")]
[System.Text.Json.Serialization.JsonPropertyName("order_id")]
public string OrderId { get; set; } = default!;
/// <summary>
/// 获取或设置客户企业 CorpId。
/// </summary>
[Newtonsoft.Json.JsonProperty("custom_corpid")]
[System.Text.Json.Serialization.JsonPropertyName("custom_corpid")]
public string? CustomCorpId { get; set; }
/// <summary>
/// 获取或设置客户企业简称。
/// </summary>
[Newtonsoft.Json.JsonProperty("custom_corp_name")]
[System.Text.Json.Serialization.JsonPropertyName("custom_corp_name")]
public string? CustomCorpName { get; set; }
/// <summary>
/// 获取或设置创建订单时间戳。
/// </summary>
[Newtonsoft.Json.JsonProperty("create_time")]
[System.Text.Json.Serialization.JsonPropertyName("create_time")]
public long CreateTimestamp { get; set; }
/// <summary>
/// 获取或设置业务类型。
/// </summary>
[Newtonsoft.Json.JsonProperty("business_type")]
[System.Text.Json.Serialization.JsonPropertyName("business_type")]
public int BusinessType { get; set; }
/// <summary>
/// 获取或设置购买内容。
/// </summary>
[Newtonsoft.Json.JsonProperty("buy_content")]
[System.Text.Json.Serialization.JsonPropertyName("buy_content")]
public string BuyContent { get; set; } = default!;
/// <summary>
/// 获取或设置原价(单位:分)。
/// </summary>
[Newtonsoft.Json.JsonProperty("origin_price")]
[System.Text.Json.Serialization.JsonPropertyName("origin_price")]
public int OriginPrice { get; set; }
/// <summary>
/// 获取或设置现价(单位:分)。
/// </summary>
[Newtonsoft.Json.JsonProperty("paid_price")]
[System.Text.Json.Serialization.JsonPropertyName("paid_price")]
public int PaidPrice { get; set; }
/// <summary>
/// 获取或设置订单状态。
/// </summary>
[Newtonsoft.Json.JsonProperty("order_status")]
[System.Text.Json.Serialization.JsonPropertyName("order_status")]
public int OrderStatus { get; set; }
/// <summary>
/// 获取或设置订单来源。
/// </summary>
[Newtonsoft.Json.JsonProperty("order_from")]
[System.Text.Json.Serialization.JsonPropertyName("order_from")]
public int OrderFrom { get; set; }
/// <summary>
/// 获取或设置订单创建人成员账号。
/// </summary>
[Newtonsoft.Json.JsonProperty("creator")]
[System.Text.Json.Serialization.JsonPropertyName("creator")]
public string? CreatorUserId { get; set; }
/// <summary>
/// 获取或设置支付方式。
/// </summary>
[Newtonsoft.Json.JsonProperty("pay_type")]
[System.Text.Json.Serialization.JsonPropertyName("pay_type")]
public int PayType { get; set; }
/// <summary>
/// 获取或设置付款方式。
/// </summary>
[Newtonsoft.Json.JsonProperty("pay_channel")]
[System.Text.Json.Serialization.JsonPropertyName("pay_channel")]
public int? PayChannel { get; set; }
/// <summary>
/// 获取或设置付款流水号。
/// </summary>
[Newtonsoft.Json.JsonProperty("channel_order_id")]
[System.Text.Json.Serialization.JsonPropertyName("channel_order_id")]
public string? ChannelOrderId { get; set; }
/// <summary>
/// 获取或设置付款时间戳。
/// </summary>
[Newtonsoft.Json.JsonProperty("paid_time")]
[System.Text.Json.Serialization.JsonPropertyName("paid_time")]
public long? PaidTimestamp { get; set; }
/// <summary>
/// 获取或设置收入到账类型。
/// </summary>
[Newtonsoft.Json.JsonProperty("income_type")]
[System.Text.Json.Serialization.JsonPropertyName("income_type")]
public int? IncomeType { get; set; }
/// <summary>
/// 获取或设置收入到账时间戳。
/// </summary>
[Newtonsoft.Json.JsonProperty("income_time")]
[System.Text.Json.Serialization.JsonPropertyName("income_time")]
public long? IncomeTimestamp { get; set; }
/// <summary>
/// 获取或设置收入到账金额(单位:分)。
/// </summary>
[Newtonsoft.Json.JsonProperty("income_amount")]
[System.Text.Json.Serialization.JsonPropertyName("income_amount")]
public int? IncomeAmount { get; set; }
/// <summary>
/// 获取或设置商品信息。
/// </summary>
[Newtonsoft.Json.JsonProperty("product_list")]
[System.Text.Json.Serialization.JsonPropertyName("product_list")]
public Types.Product Product { get; set; } = default!;
}
}
/// <summary>
/// 获取或设置订单信息。
/// </summary>
[Newtonsoft.Json.JsonProperty("pay_order")]
[System.Text.Json.Serialization.JsonPropertyName("pay_order")]
public Types.Order Order { get; set; } = default!;
}
}

View File

@@ -0,0 +1,44 @@
namespace SKIT.FlurlHttpClient.Wechat.Work.Models
{
/// <summary>
/// <para>表示 [POST] /cgi-bin/paytool/get_order_list 接口的请求。</para>
/// </summary>
public class CgibinPayToolGetOrderListRequest : CgibinPayToolOrderRequestBase
{
/// <summary>
/// 获取或设置业务类型。
/// </summary>
[Newtonsoft.Json.JsonProperty("business_type")]
[System.Text.Json.Serialization.JsonPropertyName("business_type")]
public int? BusinessType { get; set; }
/// <summary>
/// 获取或设置创建订单时间开始时间戳。
/// </summary>
[Newtonsoft.Json.JsonProperty("start_time")]
[System.Text.Json.Serialization.JsonPropertyName("start_time")]
public long? StartTimestamp { get; set; }
/// <summary>
/// 获取或设置创建订单时间结束时间戳。
/// </summary>
[Newtonsoft.Json.JsonProperty("end_time")]
[System.Text.Json.Serialization.JsonPropertyName("end_time")]
public long? EndTimestamp { get; set; }
/// <summary>
/// 获取或设置分页游标。
/// </summary>
[Newtonsoft.Json.JsonProperty("cursor")]
[System.Text.Json.Serialization.JsonPropertyName("cursor")]
public string? Cursor { get; set; }
/// <summary>
/// 获取或设置分页每页数量。
/// <para>默认值100</para>
/// </summary>
[Newtonsoft.Json.JsonProperty("limit")]
[System.Text.Json.Serialization.JsonPropertyName("limit")]
public int Limit { get; set; } = 100;
}
}

View File

@@ -0,0 +1,107 @@
namespace SKIT.FlurlHttpClient.Wechat.Work.Models
{
/// <summary>
/// <para>表示 [POST] /cgi-bin/paytool/get_order_list 接口的响应。</para>
/// </summary>
public class CgibinPayToolGetOrderListResponse : WechatWorkResponse
{
public static class Types
{
public class Order
{
/// <summary>
/// 获取或设置收款订单号。
/// </summary>
[Newtonsoft.Json.JsonProperty("order_id")]
[System.Text.Json.Serialization.JsonPropertyName("order_id")]
public string OrderId { get; set; } = default!;
/// <summary>
/// 获取或设置客户企业 CorpId。
/// </summary>
[Newtonsoft.Json.JsonProperty("custom_corpid")]
[System.Text.Json.Serialization.JsonPropertyName("custom_corpid")]
public string? CustomCorpId { get; set; }
/// <summary>
/// 获取或设置创建订单时间戳。
/// </summary>
[Newtonsoft.Json.JsonProperty("create_time")]
[System.Text.Json.Serialization.JsonPropertyName("create_time")]
public long CreateTimestamp { get; set; }
/// <summary>
/// 获取或设置购买内容。
/// </summary>
[Newtonsoft.Json.JsonProperty("buy_content")]
[System.Text.Json.Serialization.JsonPropertyName("buy_content")]
public string BuyContent { get; set; } = default!;
/// <summary>
/// 获取或设置原价(单位:分)。
/// </summary>
[Newtonsoft.Json.JsonProperty("origin_price")]
[System.Text.Json.Serialization.JsonPropertyName("origin_price")]
public int OriginPrice { get; set; }
/// <summary>
/// 获取或设置现价(单位:分)。
/// </summary>
[Newtonsoft.Json.JsonProperty("paid_price")]
[System.Text.Json.Serialization.JsonPropertyName("paid_price")]
public int PaidPrice { get; set; }
/// <summary>
/// 获取或设置订单状态。
/// </summary>
[Newtonsoft.Json.JsonProperty("order_status")]
[System.Text.Json.Serialization.JsonPropertyName("order_status")]
public int OrderStatus { get; set; }
/// <summary>
/// 获取或设置订单来源。
/// </summary>
[Newtonsoft.Json.JsonProperty("order_from")]
[System.Text.Json.Serialization.JsonPropertyName("order_from")]
public int OrderFrom { get; set; }
/// <summary>
/// 获取或设置订单创建人成员账号。
/// </summary>
[Newtonsoft.Json.JsonProperty("creator")]
[System.Text.Json.Serialization.JsonPropertyName("creator")]
public string? CreatorUserId { get; set; }
/// <summary>
/// 获取或设置支付方式。
/// </summary>
[Newtonsoft.Json.JsonProperty("pay_type")]
[System.Text.Json.Serialization.JsonPropertyName("pay_type")]
public int PayType { get; set; }
}
}
/// <summary>
/// 获取或设置订单列表。
/// </summary>
[Newtonsoft.Json.JsonProperty("pay_order_list")]
[System.Text.Json.Serialization.JsonPropertyName("pay_order_list")]
public Types.Order[] OrderList { get; set; } = default!;
/// <summary>
/// 获取或设置分页游标。
/// </summary>
[Newtonsoft.Json.JsonProperty("next_cursor")]
[System.Text.Json.Serialization.JsonPropertyName("next_cursor")]
public string? NextCursor { get; set; }
/// <summary>
/// 获取或设置是否还有更多数据。
/// </summary>
[Newtonsoft.Json.JsonProperty("has_more")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.Common.NumericalBooleanConverter))]
[System.Text.Json.Serialization.JsonPropertyName("has_more")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.Common.NumericalBooleanConverter))]
public bool HasMore { get; set; }
}
}

View File

@@ -0,0 +1,323 @@
using System.Collections.Generic;
namespace SKIT.FlurlHttpClient.Wechat.Work.Models
{
/// <summary>
/// <para>表示 [POST] /cgi-bin/paytool/open_order 接口的请求。</para>
/// </summary>
public class CgibinPayToolOpenOrderRequest : CgibinPayToolOrderRequestBase
{
public static class Types
{
public class Product
{
public static class Types
{
public class ProductBase
{
/// <summary>
/// 获取或设置购买类型。
/// </summary>
[Newtonsoft.Json.JsonProperty("order_type")]
[System.Text.Json.Serialization.JsonPropertyName("order_type")]
public int OrderType { get; set; }
/// <summary>
/// 获取或设置是否推送确认提醒。
/// </summary>
[Newtonsoft.Json.JsonProperty("notify_custom_corp")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.Common.NumericalBooleanConverter))]
[System.Text.Json.Serialization.JsonPropertyName("notify_custom_corp")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.Common.NumericalBooleanConverter))]
public bool? IsNotifyCustomCorp { get; set; }
}
public class ThirdPartyApp : ProductBase
{
public static class Types
{
public class BuyInfo
{
public static class Types
{
public class DiscountInfo
{
/// <summary>
/// 获取或设置优惠类型。
/// </summary>
[Newtonsoft.Json.JsonProperty("discount_type")]
[System.Text.Json.Serialization.JsonPropertyName("discount_type")]
public int DiscountType { get; set; }
/// <summary>
/// 获取或设置优惠金额(单位:分)。
/// </summary>
[Newtonsoft.Json.JsonProperty("discount_amount")]
[System.Text.Json.Serialization.JsonPropertyName("discount_amount")]
public int? DiscountAmount { get; set; }
/// <summary>
/// 获取或设置优惠折扣(单位:百分数)。
/// </summary>
[Newtonsoft.Json.JsonProperty("discount_ratio")]
[System.Text.Json.Serialization.JsonPropertyName("discount_ratio")]
public int? DiscountRatio { get; set; }
/// <summary>
/// 获取或设置优惠原因。
/// </summary>
[Newtonsoft.Json.JsonProperty("discount_remarks")]
[System.Text.Json.Serialization.JsonPropertyName("discount_remarks")]
public string? DiscountRemarks { get; set; }
}
}
/// <summary>
/// 获取或设置套件 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("suiteid")]
[System.Text.Json.Serialization.JsonPropertyName("suiteid")]
public string SuiteId { get; set; } = string.Empty;
/// <summary>
/// 获取或设置旧版应用 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("appid")]
[System.Text.Json.Serialization.JsonPropertyName("appid")]
public int? AppId { get; set; }
/// <summary>
/// 获取或设置版本号 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("edition_id")]
[System.Text.Json.Serialization.JsonPropertyName("edition_id")]
public string EditionId { get; set; } = string.Empty;
/// <summary>
/// 获取或设置购买人数。
/// </summary>
[Newtonsoft.Json.JsonProperty("user_count")]
[System.Text.Json.Serialization.JsonPropertyName("user_count")]
public int? UserCount { get; set; }
/// <summary>
/// 获取或设置购买天数。
/// </summary>
[Newtonsoft.Json.JsonProperty("duration_days")]
[System.Text.Json.Serialization.JsonPropertyName("duration_days")]
public int? DurationDays { get; set; }
/// <summary>
/// 获取或设置生效日期字符串格式yyyyMMdd
/// </summary>
[Newtonsoft.Json.JsonProperty("take_effect_date")]
[System.Text.Json.Serialization.JsonPropertyName("take_effect_date")]
public string? TakeEffectDateString { get; set; }
/// <summary>
/// 获取或设置优惠信息。
/// </summary>
[Newtonsoft.Json.JsonProperty("discount_info")]
[System.Text.Json.Serialization.JsonPropertyName("discount_info")]
public Types.DiscountInfo? DiscountInfo { get; set; }
}
}
/// <summary>
/// 获取或设置购买应用列表。
/// </summary>
[Newtonsoft.Json.JsonProperty("buy_info_list")]
[System.Text.Json.Serialization.JsonPropertyName("buy_info_list")]
public IList<Types.BuyInfo> BuyInfoList { get; set; } = new List<Types.BuyInfo>();
}
public class CustomizedApp : ProductBase
{
public static class Types
{
public class BuyInfo
{
/// <summary>
/// 获取或设置套件 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("suiteid")]
[System.Text.Json.Serialization.JsonPropertyName("suiteid")]
public string SuiteId { get; set; } = string.Empty;
/// <summary>
/// 获取或设置旧版应用 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("appid")]
[System.Text.Json.Serialization.JsonPropertyName("appid")]
public int? AppId { get; set; }
/// <summary>
/// 获取或设置购买人数。
/// </summary>
[Newtonsoft.Json.JsonProperty("user_count")]
[System.Text.Json.Serialization.JsonPropertyName("user_count")]
public int? UserCount { get; set; }
/// <summary>
/// 获取或设置购买天数。
/// </summary>
[Newtonsoft.Json.JsonProperty("duration_days")]
[System.Text.Json.Serialization.JsonPropertyName("duration_days")]
public int? DurationDays { get; set; }
/// <summary>
/// 获取或设置生效日期字符串格式yyyyMMdd
/// </summary>
[Newtonsoft.Json.JsonProperty("take_effect_date")]
[System.Text.Json.Serialization.JsonPropertyName("take_effect_date")]
public string? TakeEffectDateString { get; set; }
/// <summary>
/// 获取或设置总价(单位:分)。
/// </summary>
[Newtonsoft.Json.JsonProperty("total_price")]
[System.Text.Json.Serialization.JsonPropertyName("total_price")]
public int TotalPrice { get; set; }
}
}
/// <summary>
/// 获取或设置购买应用列表。
/// </summary>
[Newtonsoft.Json.JsonProperty("buy_info_list")]
[System.Text.Json.Serialization.JsonPropertyName("buy_info_list")]
public IList<Types.BuyInfo> BuyInfoList { get; set; } = new List<Types.BuyInfo>();
}
public class PromotionCase : ProductBase
{
public static class Types
{
public class BuyInfo
{
/// <summary>
/// 获取或设置套件 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("suiteid")]
[System.Text.Json.Serialization.JsonPropertyName("suiteid")]
public string SuiteId { get; set; } = string.Empty;
/// <summary>
/// 获取或设置旧版应用 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("appid")]
[System.Text.Json.Serialization.JsonPropertyName("appid")]
public int? AppId { get; set; }
/// <summary>
/// 获取或设置购买人数。
/// </summary>
[Newtonsoft.Json.JsonProperty("user_count")]
[System.Text.Json.Serialization.JsonPropertyName("user_count")]
public int? UserCount { get; set; }
}
}
/// <summary>
/// 获取或设置行业方案 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("case_id")]
[System.Text.Json.Serialization.JsonPropertyName("case_id")]
public string CaseId { get; set; } = string.Empty;
/// <summary>
/// 获取或设置行业方案版本名称
/// </summary>
[Newtonsoft.Json.JsonProperty("promotion_edition_name")]
[System.Text.Json.Serialization.JsonPropertyName("promotion_edition_name")]
public string PromotionEditionName { get; set; } = string.Empty;
/// <summary>
/// 获取或设置购买天数。
/// </summary>
[Newtonsoft.Json.JsonProperty("duration_days")]
[System.Text.Json.Serialization.JsonPropertyName("duration_days")]
public int? DurationDays { get; set; }
/// <summary>
/// 获取或设置生效日期字符串格式yyyyMMdd
/// </summary>
[Newtonsoft.Json.JsonProperty("take_effect_date")]
[System.Text.Json.Serialization.JsonPropertyName("take_effect_date")]
public string? TakeEffectDateString { get; set; }
/// <summary>
/// 获取或设置购买应用列表。
/// </summary>
[Newtonsoft.Json.JsonProperty("buy_info_list")]
[System.Text.Json.Serialization.JsonPropertyName("buy_info_list")]
public IList<Types.BuyInfo>? BuyInfoList { get; set; }
}
}
/// <summary>
/// 获取或设置第三方应用商品信息。
/// </summary>
[Newtonsoft.Json.JsonProperty("third_app")]
[System.Text.Json.Serialization.JsonPropertyName("third_app")]
public Types.ThirdPartyApp? ThirdPartyApp { get; set; }
/// <summary>
/// 获取或设置代开发应用商品信息。
/// </summary>
[Newtonsoft.Json.JsonProperty("customized_app")]
[System.Text.Json.Serialization.JsonPropertyName("customized_app")]
public Types.CustomizedApp? CustomizedApp { get; set; }
/// <summary>
/// 获取或设置行业解决方案商品信息。
/// </summary>
[Newtonsoft.Json.JsonProperty("promotion_case")]
[System.Text.Json.Serialization.JsonPropertyName("promotion_case")]
public Types.PromotionCase? PromotionCase { get; set; }
}
}
/// <summary>
/// 获取或设置业务类型。
/// </summary>
[Newtonsoft.Json.JsonProperty("business_type")]
[System.Text.Json.Serialization.JsonPropertyName("business_type")]
public int BusinessType { get; set; }
/// <summary>
/// 获取或设置客户企业 CorpId。
/// </summary>
[Newtonsoft.Json.JsonProperty("custom_corpid")]
[System.Text.Json.Serialization.JsonPropertyName("custom_corpid")]
public string? CustomCorpId { get; set; }
/// <summary>
/// 获取或设置支付方式。
/// </summary>
[Newtonsoft.Json.JsonProperty("pay_type")]
[System.Text.Json.Serialization.JsonPropertyName("pay_type")]
public int PayType { get; set; }
/// <summary>
/// 获取或设置服务商订单费用凭证 MediaId。
/// </summary>
[Newtonsoft.Json.JsonProperty("bank_receipt_media_id")]
[System.Text.Json.Serialization.JsonPropertyName("bank_receipt_media_id")]
public string? BandReceiptMediaId { get; set; }
/// <summary>
/// 获取或设置订单创建人成员账号。
/// </summary>
[Newtonsoft.Json.JsonProperty("creator")]
[System.Text.Json.Serialization.JsonPropertyName("creator")]
public string? CreatorUserId { get; set; }
/// <summary>
/// 获取或设置商品信息。
/// </summary>
[Newtonsoft.Json.JsonProperty("product_list")]
[System.Text.Json.Serialization.JsonPropertyName("product_list")]
public Types.Product Product { get; set; } = new Types.Product();
}
}

View File

@@ -0,0 +1,36 @@
namespace SKIT.FlurlHttpClient.Wechat.Work.Models
{
/// <summary>
/// <para>表示 [POST] /cgi-bin/paytool/open_order 接口的响应。</para>
/// </summary>
public class CgibinPayToolOpenOrderResponse : WechatWorkResponse
{
/// <summary>
/// 获取或设置收款订单号。
/// </summary>
[Newtonsoft.Json.JsonProperty("order_id")]
[System.Text.Json.Serialization.JsonPropertyName("order_id")]
public string OrderId { get; set; } = default!;
/// <summary>
/// 获取或设置收款订单链接。
/// </summary>
[Newtonsoft.Json.JsonProperty("order_url")]
[System.Text.Json.Serialization.JsonPropertyName("order_url")]
public string OrderUrl { get; set; } = default!;
/// <summary>
/// 获取或设置原价(单位:分)。
/// </summary>
[Newtonsoft.Json.JsonProperty("origin_price")]
[System.Text.Json.Serialization.JsonPropertyName("origin_price")]
public int? OriginPrice { get; set; }
/// <summary>
/// 获取或设置现价(单位:分)。
/// </summary>
[Newtonsoft.Json.JsonProperty("paid_price")]
[System.Text.Json.Serialization.JsonPropertyName("paid_price")]
public int? PaidPrice { get; set; }
}
}

View File

@@ -0,0 +1,33 @@
namespace SKIT.FlurlHttpClient.Wechat.Work.Models
{
public abstract class CgibinPayToolOrderRequestBase : WechatWorkRequest
{
/// <summary>
/// 获取或设置服务商 AccessToken。
/// </summary>
[Newtonsoft.Json.JsonIgnore]
[System.Text.Json.Serialization.JsonIgnore]
public string ProviderAccessToken { get; set; } = string.Empty;
/// <summary>
/// 获取或设置随机字符串。如果不指定将由系统自动生成。
/// </summary>
[Newtonsoft.Json.JsonProperty("nonce_str")]
[System.Text.Json.Serialization.JsonPropertyName("nonce_str")]
public string? NonceString { get; set; }
/// <summary>
/// 获取或设置请求时间戳。如果不指定将由系统自动生成。
/// </summary>
[Newtonsoft.Json.JsonProperty("ts")]
[System.Text.Json.Serialization.JsonPropertyName("ts")]
public long? Timestamp { get; set; }
/// <summary>
/// 获取或设置请求数字签名。如果不指定将由系统自动生成。
/// </summary>
[Newtonsoft.Json.JsonProperty("sig")]
[System.Text.Json.Serialization.JsonPropertyName("sig")]
public string? Signature { get; set; }
}
}

View File

@@ -54,6 +54,11 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.Settings
/// </summary>
public string? PushToken { get; }
/// <summary>
/// 初始化客户端时 <see cref="WechatWorkClientOptions.PayToolApiSecret"/> 的副本。
/// </summary>
public string? PayToolApiSecret { get; }
internal Credentials(WechatWorkClientOptions options)
{
if (options is null) throw new ArgumentNullException(nameof(options));
@@ -68,6 +73,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.Settings
ModelSecret = options.ModelSecret;
PushEncodingAESKey = options.PushEncodingAESKey;
PushToken = options.PushToken;
PayToolApiSecret = options.PayToolApiSecret;
}
}
}

View File

@@ -66,5 +66,10 @@ namespace SKIT.FlurlHttpClient.Wechat.Work
/// 获取或设置企业微信服务器推送的 Token。
/// </summary>
public string? PushToken { get; set; }
/// <summary>
/// 获取或设置企业微信收银台 API 调用密钥。
/// </summary>
public string? PayToolApiSecret { get; set; }
}
}

View File

@@ -1,26 +1,31 @@
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
{
public class TestCase_RequestSigningTests
public partial class TestCase_RequestSigningTests
{
[Fact(DisplayName = "测试用例:即时配送请求签名")]
public async Task TestImmeDeliveryRequestSignature()
{
var httpClient = new HttpClient(new MockHttpMessageHandler(new HttpClientHandler()));
var mockClient = new WechatApiClient(new WechatApiClientOptions()
{
AppId = "",
AppSecret = "",
ImmeDeliveryAppKey = "test_shop_id",
ImmeDeliveryAppSecret = "test_app_secrect"
});
}, httpClient);
var request = new Models.CgibinExpressLocalBusinessTestUpdateOrderRequest()
{
ShopOrderId = "test_shop_order_id"
};
var response = await mockClient.ExecuteCgibinExpressLocalBusinessTestUpdateOrderAsync(request); // 这里不关心响应结果,只为获得预处理请求
_ = await mockClient.ExecuteCgibinExpressLocalBusinessTestUpdateOrderAsync(request);
Assert.Equal("a93d8d6bae9a9483c1b1d4e8670e7f6226ec94cb", request.DeliverySignature, ignoreCase: true);
}
@@ -28,12 +33,13 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
[Fact(DisplayName = "测试用例:虚拟支付请求签名")]
public async Task TestVirtualPaymentRequestSignature()
{
var httpClient = new HttpClient(new MockHttpMessageHandler(new HttpClientHandler()));
var mockClient = new WechatApiClient(new WechatApiClientOptions()
{
AppId = "wxtest",
AppSecret = "",
VirtualPaymentAppKey = "12345"
});
}, httpClient);
mockClient.Configure(settings =>
{
var jsonOptions = SystemTextJsonSerializer.GetDefaultSerializerOptions();
@@ -50,7 +56,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
UserIp = "127.0.0.1",
SessionKey = "9hAb/NEYUlkaMBEsmFgzig=="
};
var response = await mockClient.ExecuteXPayQueryUserBalanceAsync(request); // 这里不关心响应结果,只为获得预处理请求
_ = await mockClient.ExecuteXPayQueryUserBalanceAsync(request);
Assert.Equal("e690cc22b6378ca9d70fe61727fabf65f0273d436813447816951989867a134c", request.Signature, ignoreCase: true);
Assert.Equal("fb4703e6b7da545a7f43428f02f2a9fa42e895704c6319d01a0aa859cf63253c", request.PaySign, ignoreCase: true);
@@ -59,13 +65,14 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
[Fact(DisplayName = "测试用例:米大师 1.0 请求签名")]
public async Task TestMidasRequestSignature()
{
var httpClient = new HttpClient(new MockHttpMessageHandler(new HttpClientHandler()));
var mockClient = new WechatApiClient(new WechatApiClientOptions()
{
AppId = "wx1234567",
AppSecret = "",
MidasOfferId = "12345678",
MidasAppKey = "zNLgAGgqsEWJOg1nFVaO5r7fAlIQxr1u"
});
}, httpClient);
var request = new Models.CgibinMidasGetBalanceRequest()
{
@@ -74,7 +81,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
Platform = "android",
Timestamp = 1507530737
};
var response = await mockClient.ExecuteCgibinMidasGetBalanceAsync(request); // 这里不关心响应结果,只为获得预处理请求
_ = await mockClient.ExecuteCgibinMidasGetBalanceAsync(request);
Assert.Equal("1ad64e8dcb2ec1dc486b7fdf01f4a15159fc623dc3422470e51cf6870734726b", request.Signature, ignoreCase: true);
}
@@ -82,13 +89,14 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
[Fact(DisplayName = "测试用例:米大师 2.0 请求签名")]
public async Task TestMidasV2RequestSignature()
{
var httpClient = new HttpClient(new MockHttpMessageHandler(new HttpClientHandler()));
var mockClient = new WechatApiClient(new WechatApiClientOptions()
{
AppId = "wx1234567",
AppSecret = "",
MidasOfferIdV2 = "12345678",
MidasAppKeyV2 = "12345"
});
}, httpClient);
mockClient.Configure(settings =>
{
var jsonOptions = SystemTextJsonSerializer.GetDefaultSerializerOptions();
@@ -107,10 +115,43 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
Timestamp = 1668136271,
SessionKey = "9hAb/NEYUlkaMBEsmFgzig=="
};
var response = await mockClient.ExecuteWxaGameGetBalanceAsync(request); // 这里不关心响应结果,只为获得预处理请求
_ = await mockClient.ExecuteWxaGameGetBalanceAsync(request);
Assert.Equal("7ec6d737f118b0c898de39ef1b6b199c48290e699495364fe9d069597a7da125", request.Signature, ignoreCase: true);
Assert.Equal("5fc5460b23b2589efb8adbc2cf08d7a9cd8892b33e084249a26455b7880741a8", request.PaySign, ignoreCase: true);
}
}
partial class TestCase_RequestSigningTests
{
public class MockHttpClient : HttpClient
{
public MockHttpClient()
: base(new MockHttpMessageHandler(new HttpClientHandler()))
{
}
}
public class MockHttpMessageHandler : DelegatingHandler
{
public MockHttpMessageHandler(HttpMessageHandler innerHandler)
: base(innerHandler)
{
}
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
string mockResponseContent = "{\"errcode\":0}";
byte[] mockResponseBytes = Encoding.UTF8.GetBytes(mockResponseContent);
var resp = new HttpResponseMessage
{
RequestMessage = request,
StatusCode = HttpStatusCode.NoContent,
Content = new ByteArrayContent(mockResponseBytes),
};
resp.Headers.TryAddWithoutValidation("Content-Length", mockResponseBytes.Length.ToString());
return Task.FromResult(resp);
}
}
}
}

View File

@@ -0,0 +1,6 @@
{
"start_time": 1680000000,
"end_time": 1680003600,
"cursor": "CURSOR",
"limit": 50
}

View File

@@ -0,0 +1,29 @@
{
"errcode": 0,
"errmsg": "ok",
"has_more": 1,
"next_cursor": "CURSOR",
"invoice_list": [
{
"order_id": "ORDERID",
"custom_corpid": "wwxx",
"apply_time": 1680000000,
"invoice_type": 0,
"paid_price": 9000,
"invoice_status": 1,
"invoice_title": "发票抬头",
"tax_number": "TAXPAYERID",
"send_way": 1,
"contact_name": "张三",
"contact_tel": "12345678901",
"contact_addr": "广东省|广州市|海珠区",
"contact_postcode": "200240",
"receive_email": "jack@qq.com",
"company_addr": "广东省广州市海珠区媒体港",
"company_tel": "187XXXXXXXX",
"bank_name": "中国邮政储蓄银行股份有限公司广州市天河支行",
"bank_account_number": "17631364174811341",
"invoice_note": "开票备注"
}
]
}

View File

@@ -0,0 +1,6 @@
{
"order_id": "ORDERID",
"oper_userid": "USERID",
"invoice_status": 1,
"invoice_note": "NOTE"
}

View File

@@ -0,0 +1,6 @@
{
"order_id": "T0Rkc2g3dWlQNzFLNTRXMDJBV25BNi95OVZZbjBPOE11N2FCWkc0STJRdz0=",
"nonce_str": "129031823",
"ts": 1548302135,
"sig": "mPOwVW/vQ74xN+b+Yu1KMa9RrmhKJaJjAtXHTof+EpU="
}

View File

@@ -0,0 +1,6 @@
{
"order_id": "T0Rkc2g3dWlQNzFLNTRXMDJBV25BNi95OVZZbjBPOE11N2FCWkc0STJRdz0=",
"nonce_str": "129031823",
"ts": 1548302135,
"sig": "mPOwVW/vQ74xN+b+Yu1KMa9RrmhKJaJjAtXHTof+EpU="
}

View File

@@ -0,0 +1,67 @@
{
"errcode": 0,
"errmsg": "ok",
"pay_order": {
"order_id": "ORDERID",
"create_time": 1671161338,
"custom_corpid": "ww0***********7e21",
"buy_content": "BUYCONTENT",
"origin_price": 10000,
"paid_price": 9000,
"order_status": 2,
"order_from": 1,
"creator": "CREATOR",
"pay_type": 1,
"custom_corp_name": "测试企业",
"pay_channel": 1,
"channel_order_id": "4200001711202212169932901772",
"paid_time": 1671161378,
"business_type": 2,
"income_type": 1,
"income_time": 1672111778,
"income_amount": 2,
"product_list": {
"third_app": {
"order_type": 0,
"buy_info_list": [
{
"suiteid": "SUITEID",
"appid": 1,
"edition_id": "版本名字",
"user_count": 10,
"duration_days": 365,
"origin_price": 10000,
"paid_price": 9000,
"take_effect_date": "20221220"
}
]
},
"customized_app": {
"order_type": 2,
"buy_info_list": [
{
"suiteid": "SUITEID",
"user_count": 10,
"duration_days": 365,
"origin_price": 10000,
"paid_price": 9000,
"take_effect_date": "20221220"
}
]
},
"promotion_case": {
"order_type": 0,
"case_id": "CASEID",
"promotion_edition_name": "版本名字",
"buy_info_list": [
{
"suiteid": "SUITEID",
"appid": 1,
"user_count": 10,
"take_effect_date": "20221220"
}
]
}
}
}
}

View File

@@ -0,0 +1,10 @@
{
"business_type": 1,
"start_time": 1670643437,
"end_time": 1671507437,
"cursor": "tJzlB9tdqfh-g7i_J-ehOz_TWcd7dSKa39_AqCIeMFw",
"limit": 0,
"nonce_str": "129031823",
"ts": 1548302135,
"sig": "mPOwVW/vQ74xN+b+Yu1KMa9RrmhKJaJjAtXHTof+EpU="
}

View File

@@ -0,0 +1,20 @@
{
"errcode": 0,
"errmsg": "ok",
"next_cursor": "5f0uN2RNNsR8Dj0G08XUSg==",
"has_more": 1,
"pay_order_list": [
{
"order_id": "ORDERID",
"create_time": 1672220217,
"custom_corpid": "wx9***********65f9",
"buy_content": "BUYCONTENT",
"origin_price": 1000,
"paid_price": 9000,
"order_status": 1,
"order_from": 1,
"creator": "CREATOR",
"pay_type": 2
}
]
}

View File

@@ -0,0 +1,78 @@
{
"business_type": 1,
"custom_corpid": "wx979abee1572365f9",
"pay_type": 1,
"bank_receipt_media_id": "MEDIA_ID_XXX",
"creator": "CREATOR",
"product_list": {
"third_app": {
"order_type": 0,
"buy_info_list": [
{
"suiteid": "wx63bea8582b858ee7",
"appid": 1,
"edition_id": "sp7fd5170a8e807a44",
"duration_days": 1,
"take_effect_date": "20221220",
"user_count": 10,
"discount_info": {
"discount_type": 2,
"discount_amount": 0,
"discount_ratio": 75,
"discount_remarks": "老客户优惠"
}
},
{
"suiteid": "wx46b0217691d307f7",
"appid": 1,
"edition_id": "spb5625fc505870d09",
"duration_days": 1,
"user_count": 10
}
],
"notify_custom_corp": 1
},
"customized_app": {
"order_type": 0,
"buy_info_list": [
{
"suiteid": "dk6e2ed1be411f395a",
"duration_days": 30,
"take_effect_date": "20221220",
"user_count": 10,
"total_price": 250000
},
{
"suiteid": "dk9b5e63db2d5d98a0",
"duration_days": 10,
"take_effect_date": "20221220",
"user_count": 20,
"total_price": 2500
}
],
"notify_custom_corp": 1
},
"promotion_case": {
"order_type": 0,
"case_id": "slne7508097f40c4f8e",
"promotion_edition_name": "固定单价",
"duration_days": 30,
"take_effect_date": "20221230",
"buy_info_list": [
{
"suiteid": "wx8838a73b0f57a7b5",
"appid": 2,
"user_count": 10
},
{
"suiteid": "wx15ab15f7b1ced876",
"user_count": 20
}
],
"notify_custom_corp": 1
}
},
"nonce_str": "129031823",
"ts": 1548302135,
"sig": "mPOwVW/vQ74xN+b+Yu1KMa9RrmhKJaJjAtXHTof+EpU="
}

View File

@@ -0,0 +1,8 @@
{
"errcode": 0,
"errmsg": "ok",
"order_id": "N00000F24364063FC57FACFC5C6A0",
"order_url": "https://open.work.weixin.qq.com/payforapp/PREORDERT0Rkc2g3dWlQNzFLNTRXMDJBV25BNi95OVZZbjBPOE11N2FCWkc0STJRdz0=",
"origin_price": 1000,
"paid_price": 900
}

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Threading.Tasks;
using Xunit;

View File

@@ -0,0 +1,121 @@
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.Work.UnitTests
{
public partial class TestCase_RequestSigningTests
{
[Fact(DisplayName = "测试用例:收银台收款工具接口请求签名")]
public async Task TestPayToolRequestSignature()
{
var httpClient = new HttpClient(new MockHttpMessageHandler(new HttpClientHandler()));
var mockClient = new WechatWorkClient(new WechatWorkClientOptions()
{
PayToolApiSecret = "at23pxnPBNQY3JiA8N5U1gabiQqxZwqH_Gihg7a_wrULmlOPVP-iiRjv9JWYPrDk"
}, new MockHttpClient());
// 简单数据结构
{
var request = new Models.CgibinPayToolCloseOrderRequest()
{
OrderId = "T0Rkc2g3dWlQNzFLNTRXMDJBV25BNi95OVZZbjBPOE11N2FCWkc0STJRdz0=",
NonceString = "129031823",
Timestamp = 1548302135
};
_ = await mockClient.ExecuteCgibinPayToolCloseOrderAsync(request);
Assert.Equal("jzjAGcoLbquKfNVlpqzBJDSdUASP8J7PebdFB6CUnRg=", request.Signature);
}
// 复杂数据结构
{
var request = new Models.CgibinPayToolOpenOrderRequest()
{
BusinessType = 1,
CustomCorpId = "wx979abee1572365f9",
PayType = 1,
BandReceiptMediaId = "MEDIA_ID_XXX",
CreatorUserId = "CREATOR",
Product = new Models.CgibinPayToolOpenOrderRequest.Types.Product()
{
ThirdPartyApp = new Models.CgibinPayToolOpenOrderRequest.Types.Product.Types.ThirdPartyApp()
{
OrderType = 0,
BuyInfoList = new List<Models.CgibinPayToolOpenOrderRequest.Types.Product.Types.ThirdPartyApp.Types.BuyInfo>()
{
new Models.CgibinPayToolOpenOrderRequest.Types.Product.Types.ThirdPartyApp.Types.BuyInfo()
{
SuiteId = "wx63bea8582b858ee7",
AppId = 1,
EditionId = "sp7fd5170a8e807a44",
DurationDays = 1,
TakeEffectDateString = "20221220",
UserCount = 10,
DiscountInfo = new Models.CgibinPayToolOpenOrderRequest.Types.Product.Types.ThirdPartyApp.Types.BuyInfo.Types.DiscountInfo()
{
DiscountType = 2,
DiscountAmount = 0,
DiscountRatio = 75,
DiscountRemarks = "老客户优惠"
}
},
new Models.CgibinPayToolOpenOrderRequest.Types.Product.Types.ThirdPartyApp.Types.BuyInfo()
{
SuiteId = "wx46b0217691d307f7",
AppId = 1,
EditionId = "spb5625fc505870d09",
DurationDays = 1,
UserCount = 10,
}
},
IsNotifyCustomCorp = true
}
},
NonceString = "129031823",
Timestamp = 1548302135
};
_ = await mockClient.ExecuteCgibinPayToolOpenOrderAsync(request);
Assert.Equal("5c6ZV2YFUWSA+2t4i92wUi4INQPYj3m6DArzLXkwxxk=", request.Signature);
}
}
}
partial class TestCase_RequestSigningTests
{
public class MockHttpClient : HttpClient
{
public MockHttpClient()
: base(new MockHttpMessageHandler(new HttpClientHandler()))
{
}
}
public class MockHttpMessageHandler : DelegatingHandler
{
public MockHttpMessageHandler(HttpMessageHandler innerHandler)
: base(innerHandler)
{
}
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
string mockResponseContent = "{\"errcode\":0}";
byte[] mockResponseBytes = Encoding.UTF8.GetBytes(mockResponseContent);
var resp = new HttpResponseMessage
{
RequestMessage = request,
StatusCode = HttpStatusCode.NoContent,
Content = new ByteArrayContent(mockResponseBytes),
};
resp.Headers.TryAddWithoutValidation("Content-Length", mockResponseBytes.Length.ToString());
return Task.FromResult(resp);
}
}
}
}