From 183d1afa1e28a08ea7f091cf28350f0ccadbaa3c Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Mon, 3 Apr 2023 16:52:02 +0800 Subject: [PATCH] =?UTF-8?q?feat(tenpayv3):=20=E6=96=B0=E5=A2=9E=E5=BE=AE?= =?UTF-8?q?=E4=BF=A1=E7=82=B9=E9=A4=90=E8=AE=A2=E5=8D=95=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/WechatTenpayV3/Basic_ModelDefinition.md | 1 + ...atTenpayClientExecuteCateringExtensions.cs | 37 +++ .../SyncCateringOrderStatusRequest.cs | 231 ++++++++++++++++++ .../SyncCateringOrderStatusResponse.cs | 29 +++ .../SyncCateringOrderStatusRequest.json | 40 +++ 5 files changed, 338 insertions(+) create mode 100644 src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Extensions/WechatTenpayClientExecuteCateringExtensions.cs create mode 100644 src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Catering/SyncCateringOrderStatusRequest.cs create mode 100644 src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Catering/SyncCateringOrderStatusResponse.cs create mode 100644 test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/ModelSamples/Catering/SyncCateringOrderStatusRequest.json diff --git a/docs/WechatTenpayV3/Basic_ModelDefinition.md b/docs/WechatTenpayV3/Basic_ModelDefinition.md index 7108bdc7..eeeda2c8 100644 --- a/docs/WechatTenpayV3/Basic_ModelDefinition.md +++ b/docs/WechatTenpayV3/Basic_ModelDefinition.md @@ -48,6 +48,7 @@ | √ | 行业方案:智慧商圈 | 直连商户 & 服务商 | | | √ | 行业方案:微信支付分停车服务 | 直连商户 & 服务商 | | | √ | 行业方案:租用充电宝隔夜归还 | 直连商户 | | +| √ | 行业方案:微信点餐订单 | 服务商 | | | √ | 营销工具:代金券 | 直连商户 & 服务商 | | | √ | 营销工具:商家券 | 直连商户 & 服务商 | | | √ | 营销工具:委托营销 | 直连商户 & 服务商 | | diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Extensions/WechatTenpayClientExecuteCateringExtensions.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Extensions/WechatTenpayClientExecuteCateringExtensions.cs new file mode 100644 index 00000000..4e011813 --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Extensions/WechatTenpayClientExecuteCateringExtensions.cs @@ -0,0 +1,37 @@ +using System; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using Flurl; +using Flurl.Http; + +namespace SKIT.FlurlHttpClient.Wechat.TenpayV3 +{ + /// + /// 为 提供微信点餐订单相关的 API 扩展方法。 + /// + public static class WechatTenpayClientExecuteCateringExtensions + { + /// + /// 异步调用 [POST] /catering/orders/sync-status 接口。 + /// REF: https://pay.weixin.qq.com/wiki/doc/apiv3/catering.php?chapter=26_1 + /// + /// + /// + /// + /// + public static async Task ExecuteSyncCateringOrderStatusAsync(this WechatTenpayClient client, Models.SyncCateringOrderStatusRequest request, CancellationToken cancellationToken = default) + { + if (client is null) throw new ArgumentNullException(nameof(client)); + if (request is null) throw new ArgumentNullException(nameof(request)); + + if (request.MerchantId == null) + request.MerchantId = client.Credentials.MerchantId; + + IFlurlRequest flurlReq = client + .CreateRequest(request, HttpMethod.Post, "catering", "orders", "sync-status"); + + return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); + } + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Catering/SyncCateringOrderStatusRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Catering/SyncCateringOrderStatusRequest.cs new file mode 100644 index 00000000..c7b06842 --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Catering/SyncCateringOrderStatusRequest.cs @@ -0,0 +1,231 @@ +using System; +using System.Collections.Generic; + +namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models +{ + /// + /// 表示 [POST] /catering/orders/sync-status 接口的请求。 + /// + public class SyncCateringOrderStatusRequest : WechatTenpayRequest + { + public static class Types + { + public class Dish + { + /// + /// 获取或设置商户菜品 ID。 + /// + [Newtonsoft.Json.JsonProperty("out_dish_no")] + [System.Text.Json.Serialization.JsonPropertyName("out_dish_no")] + public string OutDishNumber { get; set; } = string.Empty; + + /// + /// 获取或设置菜品名称。 + /// + [Newtonsoft.Json.JsonProperty("name")] + [System.Text.Json.Serialization.JsonPropertyName("name")] + public string Name { get; set; } = string.Empty; + + /// + /// 获取或设置菜品单价(单位:分)。 + /// + [Newtonsoft.Json.JsonProperty("price")] + [System.Text.Json.Serialization.JsonPropertyName("price")] + public int Price { get; set; } + + /// + /// 获取或设置菜品单位。 + /// + [Newtonsoft.Json.JsonProperty("unit")] + [System.Text.Json.Serialization.JsonPropertyName("unit")] + public string Unit { get; set; } = string.Empty; + + /// + /// 获取或设置菜品数量。 + /// + [Newtonsoft.Json.JsonProperty("count")] + [System.Text.Json.Serialization.JsonPropertyName("count")] + public double Count { get; set; } + + /// + /// 获取或设置菜品折扣(单位:百分数)。 + /// + [Newtonsoft.Json.JsonProperty("discount")] + [System.Text.Json.Serialization.JsonPropertyName("discount")] + public int? DiscountRate { get; set; } + + /// + /// 获取或设置菜品分类。 + /// + [Newtonsoft.Json.JsonProperty("type")] + [System.Text.Json.Serialization.JsonPropertyName("type")] + public string? Type { get; set; } + + /// + /// 获取或设置菜品顺序。 + /// + [Newtonsoft.Json.JsonProperty("priority")] + [System.Text.Json.Serialization.JsonPropertyName("priority")] + public int? Priority { get; set; } + + /// + /// 获取或设置菜品属性字典。 + /// + [Newtonsoft.Json.JsonProperty("properties")] + [System.Text.Json.Serialization.JsonPropertyName("properties")] + public IDictionary? Properties { get; set; } + } + } + + /// + /// 获取或设置服务商商户号。如果不指定将使用构造 时的 参数。 + /// + [Newtonsoft.Json.JsonProperty("sp_mchid")] + [System.Text.Json.Serialization.JsonPropertyName("sp_mchid")] + public string? MerchantId { get; set; } + + /// + /// 获取或设置子商户号。 + /// + [Newtonsoft.Json.JsonProperty("sub_mchid")] + [System.Text.Json.Serialization.JsonPropertyName("sub_mchid")] + public string SubMerchantId { get; set; } = string.Empty; + + /// + /// 获取或设置服务商 AppId。 + /// + [Newtonsoft.Json.JsonProperty("sp_appid")] + [System.Text.Json.Serialization.JsonPropertyName("sp_appid")] + public string AppId { get; set; } = string.Empty; + + /// + /// 获取或设置子商户 AppId。 + /// + [Newtonsoft.Json.JsonProperty("sub_appid")] + [System.Text.Json.Serialization.JsonPropertyName("sub_appid")] + public string? SubAppId { get; set; } + + /// + /// 获取或设置商户旗下门店的唯一编号。 + /// + [Newtonsoft.Json.JsonProperty("out_shop_no")] + [System.Text.Json.Serialization.JsonPropertyName("out_shop_no")] + public string OutShopNumber { get; set; } = string.Empty; + + /// + /// 获取或设置用户唯一标识。 + /// + [Newtonsoft.Json.JsonProperty("openid")] + [System.Text.Json.Serialization.JsonPropertyName("openid")] + public string? OpenId { get; set; } + + /// + /// 获取或设置用户在子商户下的唯一标识。 + /// + [Newtonsoft.Json.JsonProperty("sub_openid")] + [System.Text.Json.Serialization.JsonPropertyName("sub_openid")] + public string? SubOpenId { get; set; } + + /// + /// 获取或设置登录凭证。 + /// + [Newtonsoft.Json.JsonProperty("login_token")] + [System.Text.Json.Serialization.JsonPropertyName("login_token")] + public string LoginToken { get; set; } = string.Empty; + + /// + /// 获取或设置点餐入口。 + /// + [Newtonsoft.Json.JsonProperty("order_entry")] + [System.Text.Json.Serialization.JsonPropertyName("order_entry")] + public string OrderEntryPath { get; set; } = string.Empty; + + /// + /// 获取或设置总价(单位:分)。 + /// + [Newtonsoft.Json.JsonProperty("total_amount")] + [System.Text.Json.Serialization.JsonPropertyName("total_amount")] + public int TotalAmount { get; set; } + + /// + /// 获取或设置优惠金额(单位:分)。 + /// + [Newtonsoft.Json.JsonProperty("discount_amount")] + [System.Text.Json.Serialization.JsonPropertyName("discount_amount")] + public int DiscountAmount { get; set; } + + /// + /// 获取或设置实际支付金额(单位:分)。 + /// + [Newtonsoft.Json.JsonProperty("user_amount")] + [System.Text.Json.Serialization.JsonPropertyName("user_amount")] + public int UserAmount { get; set; } + + /// + /// 获取或设置订单状态。 + /// + [Newtonsoft.Json.JsonProperty("status")] + [System.Text.Json.Serialization.JsonPropertyName("status")] + public string Status { get; set; } = string.Empty; + + /// + /// 获取或设置操作时间。 + /// + [Newtonsoft.Json.JsonProperty("action_time")] + [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RFC3339DateTimeOffsetConverter))] + [System.Text.Json.Serialization.JsonPropertyName("action_time")] + [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RFC3339DateTimeOffsetConverter))] + public DateTimeOffset ActionTime { get; set; } + + /// + /// 获取或设置支付时间。 + /// + [Newtonsoft.Json.JsonProperty("pay_time")] + [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RFC3339NullableDateTimeOffsetConverter))] + [System.Text.Json.Serialization.JsonPropertyName("pay_time")] + [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RFC3339NullableDateTimeOffsetConverter))] + public DateTimeOffset? PayTime { get; set; } + + /// + /// 获取或设置商户订单号。 + /// + [Newtonsoft.Json.JsonProperty("out_trade_no")] + [System.Text.Json.Serialization.JsonPropertyName("out_trade_no")] + public string? OutTradeNumber { get; set; } + + /// + /// 获取或设置微信支付单号。 + /// + [Newtonsoft.Json.JsonProperty("transaction_id")] + [System.Text.Json.Serialization.JsonPropertyName("transaction_id")] + public string? TransactionId { get; set; } + + /// + /// 获取或设置商户订单号。 + /// + [Newtonsoft.Json.JsonProperty("out_order_no")] + [System.Text.Json.Serialization.JsonPropertyName("out_order_no")] + public string OutOrderNumber { get; set; } = string.Empty; + + /// + /// 获取或设置商户桌台号。 + /// + [Newtonsoft.Json.JsonProperty("out_table_no")] + [System.Text.Json.Serialization.JsonPropertyName("out_table_no")] + public string? OutTableNumber { get; set; } + + /// + /// 获取或设置消费人数。 + /// + [Newtonsoft.Json.JsonProperty("people_count")] + [System.Text.Json.Serialization.JsonPropertyName("people_count")] + public int? PeopleCount { get; set; } + + /// + /// 获取或设置菜品列表。 + /// + [Newtonsoft.Json.JsonProperty("dish_list")] + [System.Text.Json.Serialization.JsonPropertyName("dish_list")] + public IList? DishList { get; set; } + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Catering/SyncCateringOrderStatusResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Catering/SyncCateringOrderStatusResponse.cs new file mode 100644 index 00000000..a1ecd2af --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/Catering/SyncCateringOrderStatusResponse.cs @@ -0,0 +1,29 @@ +namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models +{ + /// + /// 表示 [POST] /catering/orders/sync-status 接口的响应。 + /// + public class SyncCateringOrderStatusResponse : WechatTenpayResponse + { + /// + /// 获取或设置哈希类型。 + /// + [Newtonsoft.Json.JsonProperty("hash_type")] + [System.Text.Json.Serialization.JsonPropertyName("hash_type")] + public string HashType { get; set; } = default!; + + /// + /// 获取或设置哈希值。 + /// + [Newtonsoft.Json.JsonProperty("hash_value")] + [System.Text.Json.Serialization.JsonPropertyName("hash_value")] + public string HashValue { get; set; } = default!; + + /// + /// 获取或设置账单下载地址。 + /// + [Newtonsoft.Json.JsonProperty("download_url")] + [System.Text.Json.Serialization.JsonPropertyName("download_url")] + public string DownloadUrl { get; set; } = default!; + } +} diff --git a/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/ModelSamples/Catering/SyncCateringOrderStatusRequest.json b/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/ModelSamples/Catering/SyncCateringOrderStatusRequest.json new file mode 100644 index 00000000..c3aae3e2 --- /dev/null +++ b/test/SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests/ModelSamples/Catering/SyncCateringOrderStatusRequest.json @@ -0,0 +1,40 @@ +{ + "sp_mchid": "1900009231", + "sub_mchid": "1900000100", + "sp_appid": "wxab8acb865bb1637e", + "order_entry": "/index/order", + "sub_appid": "wx8888888888888888", + "out_shop_no": "32432", + "openid": "oHkLxt8uweSK05Xb8zGY3KzmUBn8", + "sub_openid": "oHkLxt8uweSK05Xb8zGY3KzmUBn8", + "login_token": "071oYFSN19sCH31AyNSN15QDSN1oYFSA", + "total_amount": 1000, + "discount_amount": 100, + "user_amount": 900, + "status": "CREATE_DEAL", + "action_time": "2018-06-08T10:34:56+08:00", + "pay_time": "2018-06-08T10:34:56+08:00", + "transaction_id": "1009660380201506130728806387", + "out_trade_no": "20150806125346", + "out_order_no": "20150806125346", + "dish_list": [ + { + "out_dish_no": "1", + "name": "小鸡炖蘑菇", + "price": 6000, + "unit": "BY_SHARE", + "count": 1, + "discount": 100, + "type": "FAST_FOOD", + "priority": 1, + "properties": { + "taste": "辣", + "cuisine": "炒", + "main_material": "猪肝", + "ingredients": "青椒 | 辣椒 | 葱 | 八角 ", + "others": "有机 | 农家" + } + } + ], + "people_count": 1 +}