feat(wxapi): 新增小程序虚拟支付相关接口

This commit is contained in:
Fu Diwei
2023-08-27 18:53:52 +08:00
parent f8347ef9ef
commit f93d6139d1
67 changed files with 1980 additions and 16 deletions

View File

@@ -38,10 +38,11 @@ var options = new WechatApiClientOptions()
AppSecret = "微信 AppSecret",
ImmeDeliveryAppKey = "即时配送相关服务 AppKey不用则不填",
ImmeDeliveryAppSecret = "即时配送相关服务 AppSecret不用则不填",
MidasOfferId = "米大师(虚拟支付 1.0)相关服务 OfferId,不用则不填",
MidasOfferIdV2 = "米大师(虚拟支付 2.0相关服务 OfferId不用则不填",
MidasAppKey = "米大师(虚拟支付 1.0相关服务 AppKey不用则不填",
MidasAppKeyV2 = "米大师(虚拟支付 2.0相关服务 AppKey,不用则不填"
VirtualPaymentAppKey = "虚拟支付相关服务 AppKey,不用则不填",
MidasOfferId = "米大师 1.0 相关服务 OfferId不用则不填",
MidasAppKey = "米大师 1.0 相关服务 AppKey不用则不填",
MidasOfferIdV2 = "米大师 2.0 相关服务 OfferId,不用则不填",
MidasAppKeyV2 = "米大师 2.0 相关服务 AppKey不用则不填"
};
var client = new WechatApiClient(options);
```

View File

@@ -0,0 +1,119 @@
namespace SKIT.FlurlHttpClient.Wechat.Api.Events
{
/// <summary>
/// <para>表示 EVENT.xpay_coin_pay_notify 事件的数据。</para>
/// <para>https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/industry/virtual-payment.html </para>
/// </summary>
public class XPayCoinPayNotifyEvent : WechatApiEvent, WechatApiEvent.Serialization.IJsonSerializable, WechatApiEvent.Serialization.IXmlSerializable
{
public static class Types
{
public class WechatpayInfo
{
/// <summary>
/// 获取或设置商户订单号。
/// </summary>
[Newtonsoft.Json.JsonProperty("MchOrderNo")]
[System.Text.Json.Serialization.JsonPropertyName("MchOrderNo")]
[System.Xml.Serialization.XmlElement("MchOrderNo")]
public string MerchantOrderNumber { get; set; } = default!;
/// <summary>
/// 获取或设置微信支付订单号。
/// </summary>
[Newtonsoft.Json.JsonProperty("TransactionId")]
[System.Text.Json.Serialization.JsonPropertyName("TransactionId")]
[System.Xml.Serialization.XmlElement("TransactionId")]
public string TransactionId { get; set; } = default!;
/// <summary>
/// 获取或设置支付时间戳。
/// </summary>
[Newtonsoft.Json.JsonProperty("PaidTime")]
[System.Text.Json.Serialization.JsonPropertyName("PaidTime")]
[System.Text.Json.Serialization.JsonNumberHandling(System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString)]
[System.Xml.Serialization.XmlElement("PaidTime")]
public long PayTimestamp { get; set; }
}
public class CoinInfo
{
/// <summary>
/// 获取或设置数量。
/// </summary>
[Newtonsoft.Json.JsonProperty("Quantity")]
[System.Text.Json.Serialization.JsonPropertyName("Quantity")]
[System.Text.Json.Serialization.JsonNumberHandling(System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString)]
[System.Xml.Serialization.XmlElement("Quantity")]
public int Quantity { get; set; }
/// <summary>
/// 获取或设置原始价格(单位:分)。
/// </summary>
[Newtonsoft.Json.JsonProperty("OrigPrice")]
[System.Text.Json.Serialization.JsonPropertyName("OrigPrice")]
[System.Text.Json.Serialization.JsonNumberHandling(System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString)]
[System.Xml.Serialization.XmlElement("OrigPrice")]
public int OriginalPrice { get; set; }
/// <summary>
/// 获取或设置实付价格(单位:分)。
/// </summary>
[Newtonsoft.Json.JsonProperty("ActualPrice")]
[System.Text.Json.Serialization.JsonPropertyName("ActualPrice")]
[System.Text.Json.Serialization.JsonNumberHandling(System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString)]
[System.Xml.Serialization.XmlElement("ActualPrice")]
public int ActualPrice { get; set; }
/// <summary>
/// 获取或设置透传信息。
/// </summary>
[Newtonsoft.Json.JsonProperty("Attach")]
[System.Text.Json.Serialization.JsonPropertyName("Attach")]
[System.Xml.Serialization.XmlElement("Attach", IsNullable = true)]
public string? Attachment { get; set; }
}
}
/// <summary>
/// 获取或设置用户 OpenId。
/// </summary>
[Newtonsoft.Json.JsonProperty("OpenId")]
[System.Text.Json.Serialization.JsonPropertyName("OpenId")]
[System.Xml.Serialization.XmlElement("OpenId")]
public string OpenId { get; set; } = default!;
/// <summary>
/// 获取或设置业务订单号。
/// </summary>
[Newtonsoft.Json.JsonProperty("OutTradeNo")]
[System.Text.Json.Serialization.JsonPropertyName("OutTradeNo")]
[System.Xml.Serialization.XmlElement("OutTradeNo")]
public string OutTradeNumber { get; set; } = default!;
/// <summary>
/// 获取或设置虚拟支付环境。
/// </summary>
[Newtonsoft.Json.JsonProperty("Env")]
[System.Text.Json.Serialization.JsonPropertyName("Env")]
[System.Text.Json.Serialization.JsonNumberHandling(System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString)]
[System.Xml.Serialization.XmlElement("Env")]
public int Environment { get; set; }
/// <summary>
/// 获取或设置微信支付信息。
/// </summary>
[Newtonsoft.Json.JsonProperty("WeChatPayInfo")]
[System.Text.Json.Serialization.JsonPropertyName("WeChatPayInfo")]
[System.Xml.Serialization.XmlElement("WeChatPayInfo", IsNullable = true)]
public Types.WechatpayInfo? WechatpayInfo { get; set; }
/// <summary>
/// 获取或设置代币信息。
/// </summary>
[Newtonsoft.Json.JsonProperty("CoinInfo")]
[System.Text.Json.Serialization.JsonPropertyName("CoinInfo")]
[System.Xml.Serialization.XmlElement("CoinInfo", IsNullable = true)]
public Types.CoinInfo? CoinInfo { get; set; }
}
}

View File

@@ -0,0 +1,127 @@
namespace SKIT.FlurlHttpClient.Wechat.Api.Events
{
/// <summary>
/// <para>表示 EVENT.xpay_goods_deliver_notify 事件的数据。</para>
/// <para>https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/industry/virtual-payment.html </para>
/// </summary>
public class XPayGoodsDeliverNotifyEvent : WechatApiEvent, WechatApiEvent.Serialization.IJsonSerializable, WechatApiEvent.Serialization.IXmlSerializable
{
public static class Types
{
public class WechatpayInfo
{
/// <summary>
/// 获取或设置商户订单号。
/// </summary>
[Newtonsoft.Json.JsonProperty("MchOrderNo")]
[System.Text.Json.Serialization.JsonPropertyName("MchOrderNo")]
[System.Xml.Serialization.XmlElement("MchOrderNo")]
public string MerchantOrderNumber { get; set; } = default!;
/// <summary>
/// 获取或设置微信支付订单号。
/// </summary>
[Newtonsoft.Json.JsonProperty("TransactionId")]
[System.Text.Json.Serialization.JsonPropertyName("TransactionId")]
[System.Xml.Serialization.XmlElement("TransactionId")]
public string TransactionId { get; set; } = default!;
/// <summary>
/// 获取或设置支付时间戳。
/// </summary>
[Newtonsoft.Json.JsonProperty("PaidTime")]
[System.Text.Json.Serialization.JsonPropertyName("PaidTime")]
[System.Text.Json.Serialization.JsonNumberHandling(System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString)]
[System.Xml.Serialization.XmlElement("PaidTime")]
public long PayTimestamp { get; set; }
}
public class GoodsInfo
{
/// <summary>
/// 获取或设置道具 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("ProductId")]
[System.Text.Json.Serialization.JsonPropertyName("ProductId")]
[System.Xml.Serialization.XmlElement("ProductId")]
public string ProductId { get; set; } = default!;
/// <summary>
/// 获取或设置数量。
/// </summary>
[Newtonsoft.Json.JsonProperty("Quantity")]
[System.Text.Json.Serialization.JsonPropertyName("Quantity")]
[System.Text.Json.Serialization.JsonNumberHandling(System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString)]
[System.Xml.Serialization.XmlElement("Quantity")]
public int Quantity { get; set; }
/// <summary>
/// 获取或设置原始价格(单位:分)。
/// </summary>
[Newtonsoft.Json.JsonProperty("OrigPrice")]
[System.Text.Json.Serialization.JsonPropertyName("OrigPrice")]
[System.Text.Json.Serialization.JsonNumberHandling(System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString)]
[System.Xml.Serialization.XmlElement("OrigPrice")]
public int OriginalPrice { get; set; }
/// <summary>
/// 获取或设置实付价格(单位:分)。
/// </summary>
[Newtonsoft.Json.JsonProperty("ActualPrice")]
[System.Text.Json.Serialization.JsonPropertyName("ActualPrice")]
[System.Text.Json.Serialization.JsonNumberHandling(System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString)]
[System.Xml.Serialization.XmlElement("ActualPrice")]
public int ActualPrice { get; set; }
/// <summary>
/// 获取或设置透传信息。
/// </summary>
[Newtonsoft.Json.JsonProperty("Attach")]
[System.Text.Json.Serialization.JsonPropertyName("Attach")]
[System.Xml.Serialization.XmlElement("Attach", IsNullable = true)]
public string? Attachment { get; set; }
}
}
/// <summary>
/// 获取或设置用户 OpenId。
/// </summary>
[Newtonsoft.Json.JsonProperty("OpenId")]
[System.Text.Json.Serialization.JsonPropertyName("OpenId")]
[System.Xml.Serialization.XmlElement("OpenId")]
public string OpenId { get; set; } = default!;
/// <summary>
/// 获取或设置业务订单号。
/// </summary>
[Newtonsoft.Json.JsonProperty("OutTradeNo")]
[System.Text.Json.Serialization.JsonPropertyName("OutTradeNo")]
[System.Xml.Serialization.XmlElement("OutTradeNo")]
public string OutTradeNumber { get; set; } = default!;
/// <summary>
/// 获取或设置虚拟支付环境。
/// </summary>
[Newtonsoft.Json.JsonProperty("Env")]
[System.Text.Json.Serialization.JsonPropertyName("Env")]
[System.Text.Json.Serialization.JsonNumberHandling(System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString)]
[System.Xml.Serialization.XmlElement("Env")]
public int Environment { get; set; }
/// <summary>
/// 获取或设置微信支付信息。
/// </summary>
[Newtonsoft.Json.JsonProperty("WeChatPayInfo")]
[System.Text.Json.Serialization.JsonPropertyName("WeChatPayInfo")]
[System.Xml.Serialization.XmlElement("WeChatPayInfo", IsNullable = true)]
public Types.WechatpayInfo? WechatpayInfo { get; set; }
/// <summary>
/// 获取或设置道具信息。
/// </summary>
[Newtonsoft.Json.JsonProperty("GoodsInfo")]
[System.Text.Json.Serialization.JsonPropertyName("GoodsInfo")]
[System.Xml.Serialization.XmlElement("GoodsInfo", IsNullable = true)]
public Types.GoodsInfo? GoodsInfo { get; set; }
}
}

View File

@@ -1,13 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using Flurl;
using Flurl.Http;
using Newtonsoft.Json.Converters;
namespace SKIT.FlurlHttpClient.Wechat.Api
{
@@ -36,7 +32,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api
request.SignMethod = Constants.MidasSignMethods.HMAC_SHA256;
}
if (request.Signature == null)
if (request.Signature == null && request.SessionKey != null)
{
tmpRawData = tmpRawData ?? client.JsonSerializer.Serialize(request);
@@ -45,7 +41,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api
case Constants.MidasSignMethods.HMAC_SHA256:
{
string msgText = tmpRawData;
request.Signature = Utilities.HMACUtility.HashWithSHA256(request.SessionKey ?? string.Empty, msgText).ToLower();
request.Signature = Utilities.HMACUtility.HashWithSHA256(request.SessionKey, msgText).ToLower();
}
break;

View File

@@ -0,0 +1,364 @@
using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Flurl;
using Flurl.Http;
namespace SKIT.FlurlHttpClient.Wechat.Api
{
public static class WechatApiClientExecuteXPayExtensions
{
private static T PreprocessRequest<T>(WechatApiClient client, ref T request)
where T : Models.XPayRequestBase, new()
{
if (client == null) throw new ArgumentNullException(nameof(request));
if (request == null) throw new ArgumentNullException(nameof(request));
string? tmpRawData = null; // 用于缓存待签名数据中的请求正文部分,避免序列化多次浪费性能
if (request.Signature == null && request.SessionKey != null)
{
tmpRawData = tmpRawData ?? client.JsonSerializer.Serialize(request);
string msgText = tmpRawData;
request.Signature = Utilities.HMACUtility.HashWithSHA256(request.SessionKey, msgText).ToLower();
}
if (request.PaySign == null)
{
tmpRawData = tmpRawData ?? client.JsonSerializer.Serialize(request);
string msgText = $"{request.GetRequestPath()}&{tmpRawData}";
request.PaySign = Utilities.HMACUtility.HashWithSHA256(client.Credentials.VirtualPaymentAppKey ?? string.Empty, msgText).ToLower();
}
return request;
}
/// <summary>
/// <para>异步调用 [POST] /xpay/query_user_balance 接口。</para>
/// <para>REF: https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/industry/virtual-payment.html#_2-3-%E6%9C%8D%E5%8A%A1%E5%99%A8API </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.XPayQueryUserBalanceResponse> ExecuteXPayQueryUserBalanceAsync(this WechatApiClient client, Models.XPayQueryUserBalanceRequest 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
.CreateRequest(request, HttpMethod.Post, "xpay", "query_user_balance")
.SetQueryParam("access_token", request.AccessToken)
.SetQueryParam("signature", request.Signature)
.SetQueryParam("pay_sig", request.PaySign);
return await client.SendRequestWithJsonAsync<Models.XPayQueryUserBalanceResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
}
/// <summary>
/// <para>异步调用 [POST] /xpay/currency_pay 接口。</para>
/// <para>REF: https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/industry/virtual-payment.html#_2-3-%E6%9C%8D%E5%8A%A1%E5%99%A8API </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.XPayCurrencyPayResponse> ExecuteXPayCurrencyPayAsync(this WechatApiClient client, Models.XPayCurrencyPayRequest 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
.CreateRequest(request, HttpMethod.Post, "xpay", "currency_pay")
.SetQueryParam("access_token", request.AccessToken)
.SetQueryParam("signature", request.Signature)
.SetQueryParam("pay_sig", request.PaySign);
return await client.SendRequestWithJsonAsync<Models.XPayCurrencyPayResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
}
/// <summary>
/// <para>异步调用 [POST] /xpay/cancel_currency_pay 接口。</para>
/// <para>REF: https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/industry/virtual-payment.html#_2-3-%E6%9C%8D%E5%8A%A1%E5%99%A8API </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.XPayCancelCurrencyPayResponse> ExecuteXPayCancelCurrencyPayAsync(this WechatApiClient client, Models.XPayCancelCurrencyPayRequest 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
.CreateRequest(request, HttpMethod.Post, "xpay", "cancel_currency_pay")
.SetQueryParam("access_token", request.AccessToken)
.SetQueryParam("signature", request.Signature)
.SetQueryParam("pay_sig", request.PaySign);
return await client.SendRequestWithJsonAsync<Models.XPayCancelCurrencyPayResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
}
/// <summary>
/// <para>异步调用 [POST] /xpay/notify_provide_goods 接口。</para>
/// <para>REF: https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/industry/virtual-payment.html#_2-3-%E6%9C%8D%E5%8A%A1%E5%99%A8API </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.XPayNotifyProvideGoodsResponse> ExecuteXPayNotifyProvideGoodsAsync(this WechatApiClient client, Models.XPayNotifyProvideGoodsRequest 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
.CreateRequest(request, HttpMethod.Post, "xpay", "notify_provide_goods")
.SetQueryParam("access_token", request.AccessToken)
.SetQueryParam("pay_sig", request.PaySign);
return await client.SendRequestWithJsonAsync<Models.XPayNotifyProvideGoodsResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
}
/// <summary>
/// <para>异步调用 [POST] /xpay/present_currency 接口。</para>
/// <para>REF: https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/industry/virtual-payment.html#_2-3-%E6%9C%8D%E5%8A%A1%E5%99%A8API </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.XPayPresentCurrencyResponse> ExecuteXPayPresentCurrencyAsync(this WechatApiClient client, Models.XPayPresentCurrencyRequest 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
.CreateRequest(request, HttpMethod.Post, "xpay", "present_currency")
.SetQueryParam("access_token", request.AccessToken)
.SetQueryParam("pay_sig", request.PaySign);
return await client.SendRequestWithJsonAsync<Models.XPayPresentCurrencyResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
}
/// <summary>
/// <para>异步调用 [POST] /xpay/download_bill 接口。</para>
/// <para>REF: https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/industry/virtual-payment.html#_2-3-%E6%9C%8D%E5%8A%A1%E5%99%A8API </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.XPayDownloadBillResponse> ExecuteXPayDownloadBillAsync(this WechatApiClient client, Models.XPayDownloadBillRequest 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
.CreateRequest(request, HttpMethod.Post, "xpay", "download_bill")
.SetQueryParam("access_token", request.AccessToken)
.SetQueryParam("pay_sig", request.PaySign);
return await client.SendRequestWithJsonAsync<Models.XPayDownloadBillResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
}
/// <summary>
/// <para>异步调用 [POST] /xpay/query_order 接口。</para>
/// <para>REF: https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/industry/virtual-payment.html#_2-3-%E6%9C%8D%E5%8A%A1%E5%99%A8API </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.XPayQueryOrderResponse> ExecuteXPayQueryOrderAsync(this WechatApiClient client, Models.XPayQueryOrderRequest 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
.CreateRequest(request, HttpMethod.Post, "xpay", "query_order")
.SetQueryParam("access_token", request.AccessToken)
.SetQueryParam("pay_sig", request.PaySign);
return await client.SendRequestWithJsonAsync<Models.XPayQueryOrderResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
}
/// <summary>
/// <para>异步调用 [POST] /xpay/refund_order 接口。</para>
/// <para>REF: https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/industry/virtual-payment.html#_2-3-%E6%9C%8D%E5%8A%A1%E5%99%A8API </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.XPayRefundOrderResponse> ExecuteXPayRefundOrderAsync(this WechatApiClient client, Models.XPayRefundOrderRequest 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
.CreateRequest(request, HttpMethod.Post, "xpay", "refund_order")
.SetQueryParam("access_token", request.AccessToken)
.SetQueryParam("pay_sig", request.PaySign);
return await client.SendRequestWithJsonAsync<Models.XPayRefundOrderResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
}
/// <summary>
/// <para>异步调用 [POST] /xpay/create_withdraw_order 接口。</para>
/// <para>REF: https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/industry/virtual-payment.html#_2-3-%E6%9C%8D%E5%8A%A1%E5%99%A8API </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.XPayCreateWithdrawOrderResponse> ExecuteXPayCreateWithdrawOrderAsync(this WechatApiClient client, Models.XPayCreateWithdrawOrderRequest 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
.CreateRequest(request, HttpMethod.Post, "xpay", "create_withdraw_order")
.SetQueryParam("access_token", request.AccessToken)
.SetQueryParam("pay_sig", request.PaySign);
return await client.SendRequestWithJsonAsync<Models.XPayCreateWithdrawOrderResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
}
/// <summary>
/// <para>异步调用 [POST] /xpay/query_withdraw_order 接口。</para>
/// <para>REF: https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/industry/virtual-payment.html#_2-3-%E6%9C%8D%E5%8A%A1%E5%99%A8API </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.XPayQueryWithdrawOrderResponse> ExecuteXPayQueryWithdrawOrderAsync(this WechatApiClient client, Models.XPayQueryWithdrawOrderRequest 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
.CreateRequest(request, HttpMethod.Post, "xpay", "query_withdraw_order")
.SetQueryParam("access_token", request.AccessToken)
.SetQueryParam("pay_sig", request.PaySign);
return await client.SendRequestWithJsonAsync<Models.XPayQueryWithdrawOrderResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
}
/// <summary>
/// <para>异步调用 [POST] /xpay/start_upload_goods 接口。</para>
/// <para>REF: https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/industry/virtual-payment.html#_2-3-%E6%9C%8D%E5%8A%A1%E5%99%A8API </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.XPayStartUploadGoodsResponse> ExecuteXPayStartUploadGoodsAsync(this WechatApiClient client, Models.XPayStartUploadGoodsRequest 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
.CreateRequest(request, HttpMethod.Post, "xpay", "start_upload_goods")
.SetQueryParam("access_token", request.AccessToken)
.SetQueryParam("pay_sig", request.PaySign);
return await client.SendRequestWithJsonAsync<Models.XPayStartUploadGoodsResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
}
/// <summary>
/// <para>异步调用 [POST] /xpay/query_upload_goods 接口。</para>
/// <para>REF: https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/industry/virtual-payment.html#_2-3-%E6%9C%8D%E5%8A%A1%E5%99%A8API </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.XPayQueryUploadGoodsResponse> ExecuteXPayQueryUploadGoodsAsync(this WechatApiClient client, Models.XPayQueryUploadGoodsRequest 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
.CreateRequest(request, HttpMethod.Post, "xpay", "query_upload_goods")
.SetQueryParam("access_token", request.AccessToken)
.SetQueryParam("pay_sig", request.PaySign);
return await client.SendRequestWithJsonAsync<Models.XPayQueryUploadGoodsResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
}
/// <summary>
/// <para>异步调用 [POST] /xpay/start_publish_goods 接口。</para>
/// <para>REF: https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/industry/virtual-payment.html#_2-3-%E6%9C%8D%E5%8A%A1%E5%99%A8API </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.XPayStartPublishGoodsResponse> ExecuteXPayStartPublishGoodsAsync(this WechatApiClient client, Models.XPayStartPublishGoodsRequest 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
.CreateRequest(request, HttpMethod.Post, "xpay", "start_publish_goods")
.SetQueryParam("access_token", request.AccessToken)
.SetQueryParam("pay_sig", request.PaySign);
return await client.SendRequestWithJsonAsync<Models.XPayStartPublishGoodsResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
}
/// <summary>
/// <para>异步调用 [POST] /xpay/query_publish_goods 接口。</para>
/// <para>REF: https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/industry/virtual-payment.html#_2-3-%E6%9C%8D%E5%8A%A1%E5%99%A8API </para>
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<Models.XPayQueryPublishGoodsResponse> ExecuteXPayQueryPublishGoodsAsync(this WechatApiClient client, Models.XPayQueryPublishGoodsRequest 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
.CreateRequest(request, HttpMethod.Post, "xpay", "query_publish_goods")
.SetQueryParam("access_token", request.AccessToken)
.SetQueryParam("pay_sig", request.PaySign);
return await client.SendRequestWithJsonAsync<Models.XPayQueryPublishGoodsResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
}
}
}

View File

@@ -49,7 +49,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.Models
/// </summary>
[Newtonsoft.Json.JsonIgnore]
[System.Text.Json.Serialization.JsonIgnore]
public string SessionKey { get; set; } = string.Empty;
public string? SessionKey { get; set; }
/// <summary>
/// 获取或设置用于用户登录态签名的方式。

View File

@@ -20,7 +20,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.Models
public string BillNumber { get; set; } = string.Empty;
/// <summary>
/// 获取或设置本次退回的退游戏币的数量。
/// 获取或设置本次退回的游戏币的数量。
/// </summary>
[Newtonsoft.Json.JsonProperty("amount")]
[System.Text.Json.Serialization.JsonPropertyName("amount")]

View File

@@ -20,7 +20,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.Models
public int Balance { get; set; }
/// <summary>
/// 获取或设置本次扣的赠送币的数量。
/// 获取或设置本次扣的赠送币的数量。
/// </summary>
[Newtonsoft.Json.JsonProperty("used_present_amount")]
[System.Text.Json.Serialization.JsonPropertyName("used_present_amount")]

View File

@@ -0,0 +1,56 @@
namespace SKIT.FlurlHttpClient.Wechat.Api.Models
{
public abstract class XPayRequestBase : WechatApiRequest
{
/// <summary>
/// 获取或设置用户唯一标识。
/// </summary>
[Newtonsoft.Json.JsonProperty("openid")]
[System.Text.Json.Serialization.JsonPropertyName("openid")]
public string? OpenId { get; set; }
/// <summary>
/// 获取或设置虚拟支付环境。
/// </summary>
[Newtonsoft.Json.JsonProperty("env")]
[System.Text.Json.Serialization.JsonPropertyName("env")]
public int Environment { get; set; }
/// <summary>
/// 获取或设置用户 IP。
/// </summary>
[Newtonsoft.Json.JsonProperty("user_ip")]
[System.Text.Json.Serialization.JsonPropertyName("user_ip")]
public string? UserIp { get; set; }
/// <summary>
/// 获取或设置平台类型。
/// </summary>
[Newtonsoft.Json.JsonProperty("device_type")]
[System.Text.Json.Serialization.JsonPropertyName("device_type")]
public int? DeviceType { get; set; }
/// <summary>
/// 获取或设置用于用户登录态签名的会话密钥。
/// </summary>
[Newtonsoft.Json.JsonIgnore]
[System.Text.Json.Serialization.JsonIgnore]
public string? SessionKey { get; set; }
/// <summary>
/// 获取或设置用户登录态签名。如果不指定将由系统自动生成。
/// </summary>
[Newtonsoft.Json.JsonIgnore]
[System.Text.Json.Serialization.JsonIgnore]
public string? Signature { get; set; }
/// <summary>
/// 获取或设置支付签名。如果不指定将由系统自动生成。
/// </summary>
[Newtonsoft.Json.JsonIgnore]
[System.Text.Json.Serialization.JsonIgnore]
public string? PaySign { get; set; }
protected internal abstract string GetRequestPath();
}
}

View File

@@ -0,0 +1,34 @@
namespace SKIT.FlurlHttpClient.Wechat.Api.Models
{
/// <summary>
/// <para>表示 [POST] /xpay/cancel_currency_pay 接口的请求。</para>
/// </summary>
public class XPayCancelCurrencyPayRequest : XPayRequestBase, IInferable<XPayCancelCurrencyPayRequest, XPayCancelCurrencyPayResponse>
{
/// <summary>
/// 获取或设置扣除代币的订单号。
/// </summary>
[Newtonsoft.Json.JsonProperty("pay_order_id")]
[System.Text.Json.Serialization.JsonPropertyName("pay_order_id")]
public string PayOrderId { 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("amount")]
[System.Text.Json.Serialization.JsonPropertyName("amount")]
public int Amount { get; set; }
protected internal override string GetRequestPath()
{
return "/xpay/cancel_currency_pay";
}
}
}

View File

@@ -0,0 +1,15 @@
namespace SKIT.FlurlHttpClient.Wechat.Api.Models
{
/// <summary>
/// <para>表示 [POST] /xpay/cancel_currency_pay 接口的响应。</para>
/// </summary>
public class XPayCancelCurrencyPayResponse : WechatApiResponse
{
/// <summary>
/// 获取或设置退回代币的订单号。
/// </summary>
[Newtonsoft.Json.JsonProperty("order_id")]
[System.Text.Json.Serialization.JsonPropertyName("order_id")]
public string OrderId { get; set; } = default!;
}
}

View File

@@ -0,0 +1,29 @@
namespace SKIT.FlurlHttpClient.Wechat.Api.Models
{
/// <summary>
/// <para>表示 [POST] /xpay/create_withdraw_order 接口的请求。</para>
/// </summary>
public class XPayCreateWithdrawOrderRequest : XPayRequestBase, IInferable<XPayCreateWithdrawOrderRequest, XPayCreateWithdrawOrderResponse>
{
/// <summary>
/// 获取或设置提现单号。
/// </summary>
[Newtonsoft.Json.JsonProperty("withdraw_no")]
[System.Text.Json.Serialization.JsonPropertyName("withdraw_no")]
public string WithdrawNumber { get; set; } = string.Empty;
/// <summary>
/// 获取或设置提现金额(单位:元)。
/// </summary>
[Newtonsoft.Json.JsonProperty("withdraw_amount")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.TextualDoubleConverter))]
[System.Text.Json.Serialization.JsonPropertyName("withdraw_amount")]
[System.Text.Json.Serialization.JsonNumberHandling(System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString | System.Text.Json.Serialization.JsonNumberHandling.WriteAsString)]
public double? Amount { get; set; }
protected internal override string GetRequestPath()
{
return "/xpay/create_withdraw_order";
}
}
}

View File

@@ -0,0 +1,22 @@
namespace SKIT.FlurlHttpClient.Wechat.Api.Models
{
/// <summary>
/// <para>表示 [POST] /xpay/create_withdraw_order 接口的响应。</para>
/// </summary>
public class XPayCreateWithdrawOrderResponse : WechatApiResponse
{
/// <summary>
/// 获取或设置提现单号。
/// </summary>
[Newtonsoft.Json.JsonProperty("withdraw_no")]
[System.Text.Json.Serialization.JsonPropertyName("withdraw_no")]
public string WithdrawNumber { get; set; } = default!;
/// <summary>
/// 获取或设置微信内部提现单号。
/// </summary>
[Newtonsoft.Json.JsonProperty("wx_withdraw_no")]
[System.Text.Json.Serialization.JsonPropertyName("wx_withdraw_no")]
public string WxWithdrawNumber { get; set; } = default!;
}
}

View File

@@ -0,0 +1,41 @@
namespace SKIT.FlurlHttpClient.Wechat.Api.Models
{
/// <summary>
/// <para>表示 [POST] /xpay/currency_pay 接口的请求。</para>
/// </summary>
public class XPayCurrencyPayRequest : XPayRequestBase, IInferable<XPayCurrencyPayRequest, XPayCurrencyPayResponse>
{
/// <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("amount")]
[System.Text.Json.Serialization.JsonPropertyName("amount")]
public int Amount { get; set; }
/// <summary>
/// 获取或设置物品信息。
/// </summary>
[Newtonsoft.Json.JsonProperty("payitem")]
[System.Text.Json.Serialization.JsonPropertyName("payitem")]
public string? PayItem { get; set; }
/// <summary>
/// 获取或设置备注。
/// </summary>
[Newtonsoft.Json.JsonProperty("remark")]
[System.Text.Json.Serialization.JsonPropertyName("remark")]
public string? Remark { get; set; }
protected internal override string GetRequestPath()
{
return "/xpay/currency_pay";
}
}
}

View File

@@ -0,0 +1,29 @@
namespace SKIT.FlurlHttpClient.Wechat.Api.Models
{
/// <summary>
/// <para>表示 [POST] /xpay/currency_pay 接口的响应。</para>
/// </summary>
public class XPayCurrencyPayResponse : WechatApiResponse
{
/// <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("balance")]
[System.Text.Json.Serialization.JsonPropertyName("balance")]
public int Balance { get; set; }
/// <summary>
/// 获取或设置本次扣除的赠送币的数量。
/// </summary>
[Newtonsoft.Json.JsonProperty("used_present_amount")]
[System.Text.Json.Serialization.JsonPropertyName("used_present_amount")]
public int UsedPresentAmount { get; set; }
}
}

View File

@@ -0,0 +1,27 @@
namespace SKIT.FlurlHttpClient.Wechat.Api.Models
{
/// <summary>
/// <para>表示 [POST] /xpay/download_bill 接口的请求。</para>
/// </summary>
public class XPayDownloadBillRequest : XPayRequestBase, IInferable<XPayDownloadBillRequest, XPayDownloadBillResponse>
{
/// <summary>
/// 获取或设置起始日期字符串格式yyyyMMdd
/// </summary>
[Newtonsoft.Json.JsonProperty("begin_ds")]
[System.Text.Json.Serialization.JsonPropertyName("begin_ds")]
public string BeginDateString { get; set; } = string.Empty;
/// <summary>
/// 获取或设置截止日期字符串格式yyyyMMdd
/// </summary>
[Newtonsoft.Json.JsonProperty("end_ds")]
[System.Text.Json.Serialization.JsonPropertyName("end_ds")]
public string EndDateString { get; set; } = string.Empty;
protected internal override string GetRequestPath()
{
return "/xpay/download_bill";
}
}
}

View File

@@ -0,0 +1,15 @@
namespace SKIT.FlurlHttpClient.Wechat.Api.Models
{
/// <summary>
/// <para>表示 [POST] /xpay/download_bill 接口的响应。</para>
/// </summary>
public class XPayDownloadBillResponse : WechatApiResponse
{
/// <summary>
/// 获取或设置下载地址。
/// </summary>
[Newtonsoft.Json.JsonProperty("url")]
[System.Text.Json.Serialization.JsonPropertyName("url")]
public string Url { get; set; } = default!;
}
}

View File

@@ -0,0 +1,27 @@
namespace SKIT.FlurlHttpClient.Wechat.Api.Models
{
/// <summary>
/// <para>表示 [POST] /xpay/notify_provide_goods 接口的请求。</para>
/// </summary>
public class XPayNotifyProvideGoodsRequest : XPayRequestBase, IInferable<XPayNotifyProvideGoodsRequest, XPayNotifyProvideGoodsResponse>
{
/// <summary>
/// 获取或设置订单号。与字段 <see cref="WxOrderId"/> 二选一。
/// </summary>
[Newtonsoft.Json.JsonProperty("order_id")]
[System.Text.Json.Serialization.JsonPropertyName("order_id")]
public string? OrderId { get; set; }
/// <summary>
/// 获取或设置微信内部订单号。与字段 <see cref="OrderId"/> 二选一。
/// </summary>
[Newtonsoft.Json.JsonProperty("wx_order_id")]
[System.Text.Json.Serialization.JsonPropertyName("wx_order_id")]
public string? WxOrderId { get; set; }
protected internal override string GetRequestPath()
{
return "/xpay/notify_provide_goods";
}
}
}

View File

@@ -0,0 +1,9 @@
namespace SKIT.FlurlHttpClient.Wechat.Api.Models
{
/// <summary>
/// <para>表示 [POST] /xpay/notify_provide_goods 接口的响应。</para>
/// </summary>
public class XPayNotifyProvideGoodsResponse : WechatApiResponse
{
}
}

View File

@@ -0,0 +1,27 @@
namespace SKIT.FlurlHttpClient.Wechat.Api.Models
{
/// <summary>
/// <para>表示 [POST] /xpay/present_currency 接口的请求。</para>
/// </summary>
public class XPayPresentCurrencyRequest : XPayRequestBase, IInferable<XPayPresentCurrencyRequest, XPayPresentCurrencyResponse>
{
/// <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("amount")]
[System.Text.Json.Serialization.JsonPropertyName("amount")]
public int Amount { get; set; }
protected internal override string GetRequestPath()
{
return "/xpay/present_currency";
}
}
}

View File

@@ -0,0 +1,29 @@
namespace SKIT.FlurlHttpClient.Wechat.Api.Models
{
/// <summary>
/// <para>表示 [POST] /xpay/present_currency 接口的响应。</para>
/// </summary>
public class XPayPresentCurrencyResponse : WechatApiResponse
{
/// <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("balance")]
[System.Text.Json.Serialization.JsonPropertyName("balance")]
public int Balance { get; set; }
/// <summary>
/// 获取或设置赠送后的代币余额。
/// </summary>
[Newtonsoft.Json.JsonProperty("present_balance")]
[System.Text.Json.Serialization.JsonPropertyName("present_balance")]
public int PresentBalance { get; set; }
}
}

View File

@@ -0,0 +1,27 @@
namespace SKIT.FlurlHttpClient.Wechat.Api.Models
{
/// <summary>
/// <para>表示 [POST] /xpay/query_order 接口的请求。</para>
/// </summary>
public class XPayQueryOrderRequest : XPayRequestBase, IInferable<XPayQueryOrderRequest, XPayQueryOrderResponse>
{
/// <summary>
/// 获取或设置订单号。与字段 <see cref="WxOrderId"/> 二选一。
/// </summary>
[Newtonsoft.Json.JsonProperty("order_id")]
[System.Text.Json.Serialization.JsonPropertyName("order_id")]
public string? OrderId { get; set; }
/// <summary>
/// 获取或设置微信内部订单号。与字段 <see cref="OrderId"/> 二选一。
/// </summary>
[Newtonsoft.Json.JsonProperty("wx_order_id")]
[System.Text.Json.Serialization.JsonPropertyName("wx_order_id")]
public string? WxOrderId { get; set; }
protected internal override string GetRequestPath()
{
return "/xpay/query_order";
}
}
}

View File

@@ -0,0 +1,154 @@
namespace SKIT.FlurlHttpClient.Wechat.Api.Models
{
/// <summary>
/// <para>表示 [POST] /xpay/query_order 接口的响应。</para>
/// </summary>
public class XPayQueryOrderResponse : WechatApiResponse
{
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>
/// 获取或设置虚拟支付环境。
/// </summary>
[Newtonsoft.Json.JsonProperty("env_type")]
[System.Text.Json.Serialization.JsonPropertyName("env_type")]
public int Environment { get; set; }
/// <summary>
/// 获取或设置订单类型。
/// </summary>
[Newtonsoft.Json.JsonProperty("order_type")]
[System.Text.Json.Serialization.JsonPropertyName("order_type")]
public int OrderType { get; set; }
/// <summary>
/// 获取或设置订单状态。
/// </summary>
[Newtonsoft.Json.JsonProperty("status")]
[System.Text.Json.Serialization.JsonPropertyName("status")]
public int Status { get; set; }
/// <summary>
/// 获取或设置业务类型。
/// </summary>
[Newtonsoft.Json.JsonProperty("biz_type")]
[System.Text.Json.Serialization.JsonPropertyName("biz_type")]
public int BusinessType { get; set; }
/// <summary>
/// 获取或设置订单金额(单位:分)。
/// </summary>
[Newtonsoft.Json.JsonProperty("order_fee")]
[System.Text.Json.Serialization.JsonPropertyName("order_fee")]
public int OrderFee { get; set; }
/// <summary>
/// 获取或设置订单优惠金额(单位:分)。
/// </summary>
[Newtonsoft.Json.JsonProperty("coupon_fee")]
[System.Text.Json.Serialization.JsonPropertyName("coupon_fee")]
public int CouponFee { get; set; }
/// <summary>
/// 获取或设置用户支付金额(单位:分)。
/// </summary>
[Newtonsoft.Json.JsonProperty("paid_fee")]
[System.Text.Json.Serialization.JsonPropertyName("paid_fee")]
public int PaidFee { get; set; }
/// <summary>
/// 获取或设置退款金额(单位:分)。
/// </summary>
[Newtonsoft.Json.JsonProperty("refund_fee")]
[System.Text.Json.Serialization.JsonPropertyName("refund_fee")]
public int? RefundFee { get; set; }
/// <summary>
/// 获取或设置剩余金额(单位:分)。
/// </summary>
[Newtonsoft.Json.JsonProperty("left_fee")]
[System.Text.Json.Serialization.JsonPropertyName("left_fee")]
public int? LeftFee { get; set; }
/// <summary>
/// 获取或设置付款时间戳。
/// </summary>
[Newtonsoft.Json.JsonProperty("paid_time")]
[System.Text.Json.Serialization.JsonPropertyName("paid_time")]
public long? PayTimestamp { get; set; }
/// <summary>
/// 获取或设置发货时间戳。
/// </summary>
[Newtonsoft.Json.JsonProperty("provide_time")]
[System.Text.Json.Serialization.JsonPropertyName("provide_time")]
public long? ProvideTimestamp { 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("update_time")]
[System.Text.Json.Serialization.JsonPropertyName("update_time")]
public long UpdateTimestamp { get; set; }
/// <summary>
/// 获取或设置订单创建时传的信息。
/// </summary>
[Newtonsoft.Json.JsonProperty("biz_meta")]
[System.Text.Json.Serialization.JsonPropertyName("biz_meta")]
public string? BusinessMeta { get; set; }
/// <summary>
/// 获取或设置下单时米大师返回的 Token。
/// </summary>
[Newtonsoft.Json.JsonProperty("token")]
[System.Text.Json.Serialization.JsonPropertyName("token")]
public string? MidasToken { get; set; }
/// <summary>
/// 获取或设置微信内部单号。
/// </summary>
[Newtonsoft.Json.JsonProperty("wx_order_id")]
[System.Text.Json.Serialization.JsonPropertyName("wx_order_id")]
public string WxOrderId { get; set; } = default!;
/// <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("wxpay_order_id")]
[System.Text.Json.Serialization.JsonPropertyName("wxpay_order_id")]
public string? TransactionId { get; set; }
}
}
/// <summary>
/// 获取或设置订单信息。
/// </summary>
[Newtonsoft.Json.JsonProperty("order")]
[System.Text.Json.Serialization.JsonPropertyName("order")]
public Types.Order Order { get; set; } = default!;
}
}

View File

@@ -0,0 +1,13 @@
namespace SKIT.FlurlHttpClient.Wechat.Api.Models
{
/// <summary>
/// <para>表示 [POST] /xpay/query_publish_goods 接口的请求。</para>
/// </summary>
public class XPayQueryPublishGoodsRequest : XPayRequestBase, IInferable<XPayQueryPublishGoodsRequest, XPayQueryPublishGoodsResponse>
{
protected internal override string GetRequestPath()
{
return "/xpay/query_publish_goods";
}
}
}

View File

@@ -0,0 +1,49 @@
namespace SKIT.FlurlHttpClient.Wechat.Api.Models
{
/// <summary>
/// <para>表示 [POST] /xpay/query_publish_goods 接口的响应。</para>
/// </summary>
public class XPayQueryPublishGoodsResponse : WechatApiResponse
{
public static class Types
{
public class PublishItem
{
/// <summary>
/// 获取或设置道具 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("id")]
[System.Text.Json.Serialization.JsonPropertyName("id")]
public string Id { get; set; } = default!;
/// <summary>
/// 获取或设置发布状态。
/// </summary>
[Newtonsoft.Json.JsonProperty("publish_status")]
[System.Text.Json.Serialization.JsonPropertyName("publish_status")]
public int PublishStatus { get; set; }
/// <summary>
/// 获取或设置发布失败原因。
/// </summary>
[Newtonsoft.Json.JsonProperty("errmsg")]
[System.Text.Json.Serialization.JsonPropertyName("errmsg")]
public string? FailReason { get; set; }
}
}
/// <summary>
/// 获取或设置道具列表。
/// </summary>
[Newtonsoft.Json.JsonProperty("publish_item")]
[System.Text.Json.Serialization.JsonPropertyName("publish_item")]
public Types.PublishItem[] PublishItemList { get; set; } = default!;
/// <summary>
/// 获取或设置发布状态。
/// </summary>
[Newtonsoft.Json.JsonProperty("status")]
[System.Text.Json.Serialization.JsonPropertyName("status")]
public int Status { get; set; }
}
}

View File

@@ -0,0 +1,13 @@
namespace SKIT.FlurlHttpClient.Wechat.Api.Models
{
/// <summary>
/// <para>表示 [POST] /xpay/query_upload_goods 接口的请求。</para>
/// </summary>
public class XPayQueryUploadGoodsRequest : XPayRequestBase, IInferable<XPayQueryUploadGoodsRequest, XPayQueryUploadGoodsResponse>
{
protected internal override string GetRequestPath()
{
return "/xpay/query_upload_goods";
}
}
}

View File

@@ -0,0 +1,77 @@
namespace SKIT.FlurlHttpClient.Wechat.Api.Models
{
/// <summary>
/// <para>表示 [POST] /xpay/query_upload_goods 接口的响应。</para>
/// </summary>
public class XPayQueryUploadGoodsResponse : WechatApiResponse
{
public static class Types
{
public class UploadItem
{
/// <summary>
/// 获取或设置道具 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("id")]
[System.Text.Json.Serialization.JsonPropertyName("id")]
public string Id { get; set; } = default!;
/// <summary>
/// 获取或设置道具名称。
/// </summary>
[Newtonsoft.Json.JsonProperty("name")]
[System.Text.Json.Serialization.JsonPropertyName("name")]
public string Name { get; set; } = default!;
/// <summary>
/// 获取或设置道具单价(单位:分)。
/// </summary>
[Newtonsoft.Json.JsonProperty("price")]
[System.Text.Json.Serialization.JsonPropertyName("price")]
public int Price { get; set; }
/// <summary>
/// 获取或设置备注。
/// </summary>
[Newtonsoft.Json.JsonProperty("remark")]
[System.Text.Json.Serialization.JsonPropertyName("remark")]
public string? Remark { get; set; }
/// <summary>
/// 获取或设置图片 URL。
/// </summary>
[Newtonsoft.Json.JsonProperty("item_url")]
[System.Text.Json.Serialization.JsonPropertyName("item_url")]
public string? PictureUrl { get; set; }
/// <summary>
/// 获取或设置上传状态。
/// </summary>
[Newtonsoft.Json.JsonProperty("upload_status")]
[System.Text.Json.Serialization.JsonPropertyName("upload_status")]
public int UploadStatus { get; set; }
/// <summary>
/// 获取或设置上传失败原因。
/// </summary>
[Newtonsoft.Json.JsonProperty("errmsg")]
[System.Text.Json.Serialization.JsonPropertyName("errmsg")]
public string? FailReason { get; set; }
}
}
/// <summary>
/// 获取或设置道具列表。
/// </summary>
[Newtonsoft.Json.JsonProperty("upload_item")]
[System.Text.Json.Serialization.JsonPropertyName("upload_item")]
public Types.UploadItem[] UploadItemList { get; set; } = default!;
/// <summary>
/// 获取或设置上传状态。
/// </summary>
[Newtonsoft.Json.JsonProperty("status")]
[System.Text.Json.Serialization.JsonPropertyName("status")]
public int Status { get; set; }
}
}

View File

@@ -0,0 +1,13 @@
namespace SKIT.FlurlHttpClient.Wechat.Api.Models
{
/// <summary>
/// <para>表示 [POST] /xpay/query_user_balance 接口的请求。</para>
/// </summary>
public class XPayQueryUserBalanceRequest : XPayRequestBase, IInferable<XPayQueryUserBalanceRequest, XPayQueryUserBalanceResponse>
{
protected internal override string GetRequestPath()
{
return "/xpay/query_user_balance";
}
}
}

View File

@@ -0,0 +1,59 @@
namespace SKIT.FlurlHttpClient.Wechat.Api.Models
{
/// <summary>
/// <para>表示 [POST] /xpay/query_user_balance 接口的响应。</para>
/// </summary>
public class XPayQueryUserBalanceResponse : WechatApiResponse
{
/// <summary>
/// 获取或设置代币总余额。
/// </summary>
[Newtonsoft.Json.JsonProperty("balance")]
[System.Text.Json.Serialization.JsonPropertyName("balance")]
public int Balance { get; set; }
/// <summary>
/// 获取或设置赠送账户的代币余额。
/// </summary>
[Newtonsoft.Json.JsonProperty("present_balance")]
[System.Text.Json.Serialization.JsonPropertyName("present_balance")]
public int PresentBalance { get; set; }
/// <summary>
/// 获取或设置是否满足首充活动。
/// </summary>
[Newtonsoft.Json.JsonProperty("first_save_flag")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.NumericalBooleanConverter))]
[System.Text.Json.Serialization.JsonPropertyName("first_save_flag")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.NumericalBooleanConverter))]
public bool IsFirstSave { get; set; }
/// <summary>
/// 获取或设置累计现金充值获得的代币数量。
/// </summary>
[Newtonsoft.Json.JsonProperty("sum_save")]
[System.Text.Json.Serialization.JsonPropertyName("sum_save")]
public int SumSave { get; set; }
/// <summary>
/// 获取或设置累计赠送的代币数量。
/// </summary>
[Newtonsoft.Json.JsonProperty("sum_present")]
[System.Text.Json.Serialization.JsonPropertyName("sum_present")]
public int SumPresent { get; set; }
/// <summary>
/// 获取或设置累计获得的代币数量。
/// </summary>
[Newtonsoft.Json.JsonProperty("sum_balance")]
[System.Text.Json.Serialization.JsonPropertyName("sum_balance")]
public int SumBalance { get; set; }
/// <summary>
/// 获取或设置累计总消耗代币数量。
/// </summary>
[Newtonsoft.Json.JsonProperty("sum_cost")]
[System.Text.Json.Serialization.JsonPropertyName("sum_cost")]
public int SumCost { get; set; }
}
}

View File

@@ -0,0 +1,20 @@
namespace SKIT.FlurlHttpClient.Wechat.Api.Models
{
/// <summary>
/// <para>表示 [POST] /xpay/query_withdraw_order 接口的请求。</para>
/// </summary>
public class XPayQueryWithdrawOrderRequest : XPayRequestBase, IInferable<XPayQueryWithdrawOrderRequest, XPayQueryWithdrawOrderResponse>
{
/// <summary>
/// 获取或设置提现单号。
/// </summary>
[Newtonsoft.Json.JsonProperty("withdraw_no")]
[System.Text.Json.Serialization.JsonPropertyName("withdraw_no")]
public string WithdrawNumber { get; set; } = string.Empty;
protected internal override string GetRequestPath()
{
return "/xpay/query_withdraw_order";
}
}
}

View File

@@ -0,0 +1,60 @@
namespace SKIT.FlurlHttpClient.Wechat.Api.Models
{
/// <summary>
/// <para>表示 [POST] /xpay/query_withdraw_order 接口的响应。</para>
/// </summary>
public class XPayQueryWithdrawOrderResponse : WechatApiResponse
{
/// <summary>
/// 获取或设置提现单号。
/// </summary>
[Newtonsoft.Json.JsonProperty("withdraw_no")]
[System.Text.Json.Serialization.JsonPropertyName("withdraw_no")]
public string WithdrawNumber { get; set; } = default!;
/// <summary>
/// 获取或设置提现金额(单位:元)。
/// </summary>
[Newtonsoft.Json.JsonProperty("withdraw_amount")]
[System.Text.Json.Serialization.JsonPropertyName("withdraw_amount")]
[System.Text.Json.Serialization.JsonNumberHandling(System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString | System.Text.Json.Serialization.JsonNumberHandling.WriteAsString)]
public double Amount { get; set; }
/// <summary>
/// 获取或设置提现状态。
/// </summary>
[Newtonsoft.Json.JsonProperty("status")]
[System.Text.Json.Serialization.JsonPropertyName("status")]
public int Status { get; set; }
/// <summary>
/// 获取或设置成功时间戳。
/// </summary>
[Newtonsoft.Json.JsonProperty("withdraw_success_timestamp")]
[System.Text.Json.Serialization.JsonPropertyName("withdraw_success_timestamp")]
[System.Text.Json.Serialization.JsonNumberHandling(System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString)]
public long? SuccessTimestamp { get; set; }
/// <summary>
/// 获取或设置失败原因。
/// </summary>
[Newtonsoft.Json.JsonProperty("fail_reason")]
[System.Text.Json.Serialization.JsonPropertyName("fail_reason")]
public string? FailReason { get; set; }
/// <summary>
/// 获取或设置创建时间戳。
/// </summary>
[Newtonsoft.Json.JsonProperty("create_time")]
[System.Text.Json.Serialization.JsonPropertyName("create_time")]
[System.Text.Json.Serialization.JsonNumberHandling(System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString)]
public long CreateTimestamp { get; set; }
/// <summary>
/// 获取或设置微信内部提现单号。
/// </summary>
[Newtonsoft.Json.JsonProperty("wx_withdraw_no")]
[System.Text.Json.Serialization.JsonPropertyName("wx_withdraw_no")]
public string WxWithdrawNumber { get; set; } = default!;
}
}

View File

@@ -0,0 +1,69 @@
namespace SKIT.FlurlHttpClient.Wechat.Api.Models
{
/// <summary>
/// <para>表示 [POST] /xpay/refund_order 接口的请求。</para>
/// </summary>
public class XPayRefundOrderRequest : XPayRequestBase, IInferable<XPayRefundOrderRequest, XPayRefundOrderResponse>
{
/// <summary>
/// 获取或设置订单号。与字段 <see cref="PayWxOrderId"/> 二选一。
/// </summary>
[Newtonsoft.Json.JsonProperty("order_id")]
[System.Text.Json.Serialization.JsonPropertyName("order_id")]
public string? PayOrderId { get; set; }
/// <summary>
/// 获取或设置微信内部订单号。与字段 <see cref="PayOrderId"/> 二选一。
/// </summary>
[Newtonsoft.Json.JsonProperty("wx_order_id")]
[System.Text.Json.Serialization.JsonPropertyName("wx_order_id")]
public string? PayWxOrderId { get; set; }
/// <summary>
/// 获取或设置退款订单号。
/// </summary>
[Newtonsoft.Json.JsonProperty("refund_order_id")]
[System.Text.Json.Serialization.JsonPropertyName("refund_order_id")]
public string RefundOrderId { get; set; } = string.Empty;
/// <summary>
/// 获取或设置退款金额(单位:分)。
/// </summary>
[Newtonsoft.Json.JsonProperty("refund_fee")]
[System.Text.Json.Serialization.JsonPropertyName("refund_fee")]
public int RefundFee { get; set; }
/// <summary>
/// 获取或设置剩余金额(单位:分)。
/// </summary>
[Newtonsoft.Json.JsonProperty("left_fee")]
[System.Text.Json.Serialization.JsonPropertyName("left_fee")]
public int LeftFee { get; set; }
/// <summary>
/// 获取或设置自定义信息。
/// </summary>
[Newtonsoft.Json.JsonProperty("biz_meta")]
[System.Text.Json.Serialization.JsonPropertyName("biz_meta")]
public string? BusinessMeta { 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("req_from")]
[System.Text.Json.Serialization.JsonPropertyName("req_from")]
public string? RefundFrom { get; set; }
protected internal override string GetRequestPath()
{
return "/xpay/refund_order";
}
}
}

View File

@@ -0,0 +1,36 @@
namespace SKIT.FlurlHttpClient.Wechat.Api.Models
{
/// <summary>
/// <para>表示 [POST] /xpay/refund_order 接口的响应。</para>
/// </summary>
public class XPayRefundOrderResponse : WechatApiResponse
{
/// <summary>
/// 获取或设置订单号。
/// </summary>
[Newtonsoft.Json.JsonProperty("pay_order_id")]
[System.Text.Json.Serialization.JsonPropertyName("pay_order_id")]
public string PayOrderId { get; set; } = default!;
/// <summary>
/// 获取或设置微信内部订单号。
/// </summary>
[Newtonsoft.Json.JsonProperty("pay_wx_order_id")]
[System.Text.Json.Serialization.JsonPropertyName("pay_wx_order_id")]
public string PayWxOrderId { get; set; } = default!;
/// <summary>
/// 获取或设置退款订单号。
/// </summary>
[Newtonsoft.Json.JsonProperty("refund_order_id")]
[System.Text.Json.Serialization.JsonPropertyName("refund_order_id")]
public string RefundOrderId { get; set; } = default!;
/// <summary>
/// 获取或设置微信内部退款订单号。
/// </summary>
[Newtonsoft.Json.JsonProperty("refund_wx_order_id")]
[System.Text.Json.Serialization.JsonPropertyName("refund_wx_order_id")]
public string RefundWxOrderId { get; set; } = default!;
}
}

View File

@@ -0,0 +1,35 @@
using System.Collections.Generic;
namespace SKIT.FlurlHttpClient.Wechat.Api.Models
{
/// <summary>
/// <para>表示 [POST] /xpay/start_publish_goods 接口的请求。</para>
/// </summary>
public class XPayStartPublishGoodsRequest : XPayRequestBase, IInferable<XPayStartPublishGoodsRequest, XPayStartPublishGoodsResponse>
{
public static class Types
{
public class PublishItem
{
/// <summary>
/// 获取或设置道具 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("id")]
[System.Text.Json.Serialization.JsonPropertyName("id")]
public string Id { get; set; } = string.Empty;
}
}
/// <summary>
/// 获取或设置道具列表。
/// </summary>
[Newtonsoft.Json.JsonProperty("publish_item")]
[System.Text.Json.Serialization.JsonPropertyName("publish_item")]
public IList<Types.PublishItem> PublishItemList { get; set; } = new List<Types.PublishItem>();
protected internal override string GetRequestPath()
{
return "/xpay/start_publish_goods";
}
}
}

View File

@@ -0,0 +1,9 @@
namespace SKIT.FlurlHttpClient.Wechat.Api.Models
{
/// <summary>
/// <para>表示 [POST] /xpay/start_publish_goods 接口的响应。</para>
/// </summary>
public class XPayStartPublishGoodsResponse : WechatApiResponse
{
}
}

View File

@@ -0,0 +1,63 @@
using System.Collections.Generic;
namespace SKIT.FlurlHttpClient.Wechat.Api.Models
{
/// <summary>
/// <para>表示 [POST] /xpay/start_upload_goods 接口的请求。</para>
/// </summary>
public class XPayStartUploadGoodsRequest : XPayRequestBase, IInferable<XPayStartUploadGoodsRequest, XPayStartUploadGoodsResponse>
{
public static class Types
{
public class UploadItem
{
/// <summary>
/// 获取或设置道具 ID。
/// </summary>
[Newtonsoft.Json.JsonProperty("id")]
[System.Text.Json.Serialization.JsonPropertyName("id")]
public string Id { get; set; } = string.Empty;
/// <summary>
/// 获取或设置道具名称。
/// </summary>
[Newtonsoft.Json.JsonProperty("name")]
[System.Text.Json.Serialization.JsonPropertyName("name")]
public string Name { get; set; } = string.Empty;
/// <summary>
/// 获取或设置道具单价(单位:分)。
/// </summary>
[Newtonsoft.Json.JsonProperty("price")]
[System.Text.Json.Serialization.JsonPropertyName("price")]
public int Price { get; set; }
/// <summary>
/// 获取或设置备注。
/// </summary>
[Newtonsoft.Json.JsonProperty("remark")]
[System.Text.Json.Serialization.JsonPropertyName("remark")]
public string? Remark { get; set; }
/// <summary>
/// 获取或设置图片 URL。
/// </summary>
[Newtonsoft.Json.JsonProperty("item_url")]
[System.Text.Json.Serialization.JsonPropertyName("item_url")]
public string? PictureUrl { get; set; }
}
}
/// <summary>
/// 获取或设置道具列表。
/// </summary>
[Newtonsoft.Json.JsonProperty("upload_item")]
[System.Text.Json.Serialization.JsonPropertyName("upload_item")]
public IList<Types.UploadItem> UploadItemList { get; set; } = new List<Types.UploadItem>();
protected internal override string GetRequestPath()
{
return "/xpay/start_upload_goods";
}
}
}

View File

@@ -0,0 +1,9 @@
namespace SKIT.FlurlHttpClient.Wechat.Api.Models
{
/// <summary>
/// <para>表示 [POST] /xpay/start_upload_goods 接口的响应。</para>
/// </summary>
public class XPayStartUploadGoodsResponse : WechatApiResponse
{
}
}

View File

@@ -34,6 +34,11 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.Settings
/// </summary>
public string? ImmeDeliveryAppSecret { get; }
/// <summary>
/// 初始化客户端时 <see cref="WechatApiClientOptions.VirtualPaymentAppKey"/> 的副本。
/// </summary>
public string? VirtualPaymentAppKey { get; }
/// <summary>
/// 初始化客户端时 <see cref="WechatApiClientOptions.MidasAppKey"/> 的副本。
/// </summary>
@@ -64,6 +69,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.Settings
PushToken = options.PushToken;
ImmeDeliveryAppKey = options.ImmeDeliveryAppKey;
ImmeDeliveryAppSecret = options.ImmeDeliveryAppSecret;
VirtualPaymentAppKey = options.VirtualPaymentAppKey;
MidasAppKey = options.MidasAppKey;
MidasOfferId = options.MidasOfferId;
MidasAppKeyV2 = options.MidasAppKeyV2;

View File

@@ -47,6 +47,11 @@ namespace SKIT.FlurlHttpClient.Wechat.Api
/// </summary>
public string? ImmeDeliveryAppSecret { get; set; }
/// <summary>
/// 获取或设置虚拟支付 AppKey用于小程序虚拟支付相关接口
/// </summary>
public string? VirtualPaymentAppKey { get; set; }
/// <summary>
/// 获取或设置米大师平台 OfferId用于小游戏虚拟支付 1.0 相关接口)。
/// </summary>

View File

@@ -0,0 +1,21 @@
{
"ToUserName": "",
"FromUserName": "",
"CreateTime": 0,
"MsgType": "event",
"Event": "xpay_coin_pay_notify",
"OpenId": "",
"OutTradeNo": "",
"Env": 0,
"WeChatPayInfo": {
"MchOrderNo": "",
"TransactionId": "",
"PaidTime": 0
},
"CoinInfo": {
"Quantity": 0,
"OrigPrice": 0,
"ActualPrice": 0,
"Attach": ""
}
}

View File

@@ -0,0 +1,22 @@
{
"ToUserName": "",
"FromUserName": "",
"CreateTime": 0,
"MsgType": "event",
"Event": "xpay_goods_deliver_notify",
"OpenId": "",
"OutTradeNo": "",
"Env": 0,
"WeChatPayInfo": {
"MchOrderNo": "",
"TransactionId": "",
"PaidTime": 0
},
"GoodsInfo": {
"ProductId": "",
"Quantity": 0,
"OrigPrice": 0,
"ActualPrice": 0,
"Attach": ""
}
}

View File

@@ -0,0 +1,9 @@
{
"openid": "",
"env": 0,
"user_ip": "",
"pay_order_id": "",
"order_id": "",
"amount": 0,
"device_type": 0
}

View File

@@ -0,0 +1,5 @@
{
"errcode": 0,
"errmsg": "ok",
"order_id": ""
}

View File

@@ -0,0 +1,5 @@
{
"withdraw_no": "",
"withdraw_amount": "0",
"env": 0
}

View File

@@ -0,0 +1,6 @@
{
"errcode": 0,
"errmsg": "ok",
"withdraw_no": "",
"wx_withdraw_no": ""
}

View File

@@ -0,0 +1,10 @@
{
"openid": "",
"env": 0,
"user_ip": "",
"amount": 0,
"order_id": "",
"payitem": "",
"remark": "",
"device_type": 0
}

View File

@@ -0,0 +1,7 @@
{
"errcode": 0,
"errmsg": "ok",
"order_id": "",
"balance": 0,
"used_present_amount": 0
}

View File

@@ -0,0 +1,4 @@
{
"begin_ds": "20230801",
"end_ds": "20230810"
}

View File

@@ -0,0 +1,5 @@
{
"errcode": 0,
"errmsg": "ok",
"url": ""
}

View File

@@ -0,0 +1,5 @@
{
"order_id": "",
"wx_order_id": "",
"env": 0
}

View File

@@ -0,0 +1,7 @@
{
"openid": "",
"env": 0,
"order_id": "",
"amount": 0,
"device_type": 0
}

View File

@@ -0,0 +1,7 @@
{
"errcode": 0,
"errmsg": "ok",
"order_id": "",
"balance": 0,
"present_balance": 0
}

View File

@@ -0,0 +1,6 @@
{
"openid": "",
"env": 0,
"order_id": "",
"wx_order_id": ""
}

View File

@@ -0,0 +1,25 @@
{
"errcode": 0,
"errmsg": "ok",
"order": {
"order_id": "",
"create_time": 0,
"update_time": 0,
"status": 0,
"biz_type": 0,
"order_fee": 0,
"coupon_fee": 0,
"paid_fee": 0,
"order_type": 0,
"refund_fee": 0,
"paid_time": 0,
"provide_time": 0,
"biz_meta": "",
"env_type": 0,
"token": "",
"left_fee": 0,
"wx_order_id": "",
"channel_order_id": "",
"wxpay_order_id": ""
}
}

View File

@@ -0,0 +1,12 @@
{
"errcode": 0,
"errmsg": "ok",
"publish_item": [
{
"id": "",
"publish_status": 0,
"errmsg": ""
}
],
"status": 0
}

View File

@@ -0,0 +1,16 @@
{
"errcode": 0,
"errmsg": "ok",
"upload_item": [
{
"id": "",
"name": "",
"price": 0,
"remark": "",
"item_url": "",
"upload_status": 0,
"errmsg": ""
}
],
"status": 0
}

View File

@@ -0,0 +1,5 @@
{
"openid": "",
"env": 0,
"user_ip": ""
}

View File

@@ -0,0 +1,11 @@
{
"errcode": 0,
"errmsg": "ok",
"balance": 0,
"present_balance": 0,
"sum_save": 0,
"sum_present": 0,
"sum_balance": 0,
"sum_cost": 0,
"first_save_flag": 1
}

View File

@@ -0,0 +1,4 @@
{
"withdraw_no": "",
"env": 0
}

View File

@@ -0,0 +1,11 @@
{
"errcode": 0,
"errmsg": "ok",
"withdraw_no": "",
"status": 0,
"withdraw_amount": "0",
"wx_withdraw_no": "",
"withdraw_success_timestamp": 0,
"create_time": 0,
"fail_reason": ""
}

View File

@@ -0,0 +1,12 @@
{
"openid": "",
"order_id": "",
"wx_order_id": "",
"refund_order_id": "",
"left_fee": 0,
"refund_fee": 0,
"biz_meta": "",
"refund_reason": "",
"req_from": "",
"env": 0
}

View File

@@ -0,0 +1,8 @@
{
"errcode": 0,
"errmsg": "ok",
"refund_order_id": "",
"refund_wx_order_id": "",
"pay_order_id": "",
"pay_wx_order_id": ""
}

View File

@@ -0,0 +1,8 @@
{
"publish_item": [
{
"id": ""
}
],
"env": 0
}

View File

@@ -0,0 +1,12 @@
{
"upload_item": [
{
"id": "",
"name": "",
"price": 0,
"remark": "",
"item_url": ""
}
],
"env": 0
}

View File

@@ -25,7 +25,38 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
Assert.Equal("a93d8d6bae9a9483c1b1d4e8670e7f6226ec94cb", request.DeliverySignature, ignoreCase: true);
}
[Fact(DisplayName = "测试用例:米大师虚拟支付 1.0 请求签名")]
[Fact(DisplayName = "测试用例:虚拟支付请求签名")]
public async Task TestVirtualPaymentRequestSignature()
{
var mockClient = new WechatApiClient(new WechatApiClientOptions()
{
AppId = "wxtest",
AppSecret = "",
VirtualPaymentAppKey = "12345"
});
mockClient.Configure(settings =>
{
var jsonOptions = FlurlSystemTextJsonSerializer.GetDefaultSerializerOptions();
jsonOptions.DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull;
jsonOptions.NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.Strict;
jsonOptions.WriteIndented = false;
settings.JsonSerializer = new FlurlSystemTextJsonSerializer(jsonOptions);
});
var request = new Models.XPayQueryUserBalanceRequest()
{
OpenId = "xxx",
Environment = 0,
UserIp = "127.0.0.1",
SessionKey = "9hAb/NEYUlkaMBEsmFgzig=="
};
var response = await mockClient.ExecuteXPayQueryUserBalanceAsync(request); // 这里不关心响应结果,只为获得预处理请求
Assert.Equal("e690cc22b6378ca9d70fe61727fabf65f0273d436813447816951989867a134c", request.Signature, ignoreCase: true);
Assert.Equal("fb4703e6b7da545a7f43428f02f2a9fa42e895704c6319d01a0aa859cf63253c", request.PaySign, ignoreCase: true);
}
[Fact(DisplayName = "测试用例:米大师 1.0 请求签名")]
public async Task TestMidasRequestSignature()
{
var mockClient = new WechatApiClient(new WechatApiClientOptions()
@@ -48,8 +79,8 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
Assert.Equal("1ad64e8dcb2ec1dc486b7fdf01f4a15159fc623dc3422470e51cf6870734726b", request.Signature, ignoreCase: true);
}
[Fact(DisplayName = "测试用例:米大师虚拟支付 2.0 请求签名")]
public async Task TestMidasRequestSignatureV2()
[Fact(DisplayName = "测试用例:米大师 2.0 请求签名")]
public async Task TestMidasV2RequestSignature()
{
var mockClient = new WechatApiClient(new WechatApiClientOptions()
{