diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Extensions/WechatTenpayClientExecuteMarketingBankExtensions.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Extensions/WechatTenpayClientExecuteMarketingBankExtensions.cs new file mode 100644 index 00000000..64158a24 --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Extensions/WechatTenpayClientExecuteMarketingBankExtensions.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Web; +using Flurl; +using Flurl.Http; + +namespace SKIT.FlurlHttpClient.Wechat.TenpayV3 +{ + /// + /// 为 提供银行定向促活相关的 API 扩展方法。 + /// + public static class WechatTenpayClientExecuteMarketingBankExtensions + { + /// + /// 异步调用 [POST] /marketing/bank/packages/{package_id}/tasks 接口。 + /// REF: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter9_8_1.shtml + /// REF: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter9_8_1.shtml + /// + /// + /// + /// + /// + public static async Task ExecuteUploadMarketingBankPackagesTasksAsync(this WechatTenpayClient client, Models.UploadMarketingBankPackagesTasksRequest request, CancellationToken cancellationToken = default) + { + if (client is null) throw new ArgumentNullException(nameof(client)); + if (request is null) throw new ArgumentNullException(nameof(request)); + + if (string.IsNullOrEmpty(request.FileName)) + request.FileName = Guid.NewGuid().ToString("N").ToLower() + ".txt"; + + if (string.IsNullOrEmpty(request.FileHash)) + request.FileHash = Security.SHA256Utility.Hash(request.FileBytes).ToLower(); + + if (string.IsNullOrEmpty(request.FileContentType)) + request.FileContentType = Utilities.FileNameToContentTypeMapper.GetContentTypeForImage(request.FileName!) ?? "text/plain"; + + IFlurlRequest flurlReq = client + .CreateRequest(request, HttpMethod.Post, "marketing", "bank", "packages", request.PackageId, "tasks"); + + string boundary = "--BOUNDARY--" + DateTimeOffset.Now.Ticks.ToString("x"); + using var fileContent = new ByteArrayContent(request.FileBytes); + using var metaContent = new ByteArrayContent(Encoding.UTF8.GetBytes(client.JsonSerializer.Serialize(request))); + using var httpContent = new MultipartFormDataContent(boundary); + httpContent.Add(metaContent, $"\"{Constants.FormDataFields.FORMDATA_META}\""); + httpContent.Add(fileContent, "\"file\"", $"\"{HttpUtility.UrlEncode(request.FileName)}\""); + httpContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data; boundary=" + boundary); + metaContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json"); + fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse(request.FileContentType); + + return await client.SendRequestAsync(flurlReq, httpContent: httpContent, cancellationToken: cancellationToken); + } + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/MarketingBank/UploadMarketingBankPackagesTasksRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/MarketingBank/UploadMarketingBankPackagesTasksRequest.cs new file mode 100644 index 00000000..f3258aeb --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/MarketingBank/UploadMarketingBankPackagesTasksRequest.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; + +namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models +{ + /// + /// 表示 [POST] /marketing/bank/packages/{package_id}/tasks 接口的请求。 + /// + public class UploadMarketingBankPackagesTasksRequest : WechatTenpayRequest + { + /// + /// 获取或设置号码包 ID。 + /// + [Newtonsoft.Json.JsonIgnore] + [System.Text.Json.Serialization.JsonIgnore] + public string PackageId { get; set; } = string.Empty; + + /// + /// 获取或设置任务上传字节数组。 + /// + [Newtonsoft.Json.JsonIgnore] + [System.Text.Json.Serialization.JsonIgnore] + public byte[] FileBytes { get; set; } = new byte[0]; + + /// + /// 获取或设置任务上传文件名。如果不指定将由系统自动生成。 + /// + [Newtonsoft.Json.JsonProperty("filename")] + [System.Text.Json.Serialization.JsonPropertyName("filename")] + public string? FileName { get; set; } + + /// + /// 获取或设置任务上传文件摘要。如果不指定将由系统自动生成。 + /// + [Newtonsoft.Json.JsonProperty("sha256")] + [System.Text.Json.Serialization.JsonPropertyName("sha256")] + public string? FileHash { get; set; } + + /// + /// 获取或设置任务上传文件 Conent-Type。如果不指定将由系统自动生成。 + /// + [Newtonsoft.Json.JsonIgnore] + [System.Text.Json.Serialization.JsonIgnore] + public string? FileContentType { get; set; } + + /// + /// 获取或设置银行类型。 + /// + [Newtonsoft.Json.JsonProperty("bank_type")] + [System.Text.Json.Serialization.JsonPropertyName("bank_type")] + public string? BankType { get; set; } + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/MarketingBank/UploadMarketingBankPackagesTasksResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/MarketingBank/UploadMarketingBankPackagesTasksResponse.cs new file mode 100644 index 00000000..09e6c1e8 --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/MarketingBank/UploadMarketingBankPackagesTasksResponse.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; + +namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models +{ + /// + /// 表示 [POST] /marketing/bank/packages/{package_id}/tasks 接口的响应。 + /// + public class UploadMarketingBankPackagesTasksResponse : WechatTenpayResponse + { + /// + /// 获取或设置任务上传的文件名。 + /// + [Newtonsoft.Json.JsonProperty("filename")] + [System.Text.Json.Serialization.JsonPropertyName("filename")] + public string FileName { get; set; } = default!; + + /// + /// 获取或设置上传任务 ID。 + /// + [Newtonsoft.Json.JsonProperty("task_id")] + [System.Text.Json.Serialization.JsonPropertyName("task_id")] + public string TaskId { get; set; } = default!; + + /// + /// 获取或设置号码包 ID。 + /// + [Newtonsoft.Json.JsonProperty("package_id")] + [System.Text.Json.Serialization.JsonPropertyName("package_id")] + public string PackageId { get; set; } = default!; + + /// + /// 获取或设置任务状态。 + /// + [Newtonsoft.Json.JsonProperty("status")] + [System.Text.Json.Serialization.JsonPropertyName("status")] + public string? Status { get; set; } + + /// + /// 获取或设置银行类型。 + /// + [Newtonsoft.Json.JsonProperty("bank_type")] + [System.Text.Json.Serialization.JsonPropertyName("bank_type")] + public string? BankType { get; set; } + + /// + /// 获取或设置匹配成功的协议号数。 + /// + [Newtonsoft.Json.JsonProperty("success_count")] + [System.Text.Json.Serialization.JsonPropertyName("success_count")] + public int? SuccessCount { get; set; } + + /// + /// 获取或设置匹配失败的协议号数。 + /// + [Newtonsoft.Json.JsonProperty("fail_count")] + [System.Text.Json.Serialization.JsonPropertyName("fail_count")] + public int? FailCount { get; set; } + + /// + /// 获取或设置匹配成功的微信用户数。 + /// + [Newtonsoft.Json.JsonProperty("success_user_count")] + [System.Text.Json.Serialization.JsonPropertyName("success_user_count")] + public int? SuccessUserCount { get; set; } + + /// + /// 获取或设置银行类型。 + /// + [Newtonsoft.Json.JsonProperty("create_time")] + [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RFC3339DateTimeOffsetConverter))] + [System.Text.Json.Serialization.JsonPropertyName("create_time")] + [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RFC3339DateTimeOffsetConverter))] + public DateTimeOffset CreateTime { get; set; } + + /// + /// 获取或设置银行类型。 + /// + [Newtonsoft.Json.JsonProperty("update_time")] + [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RFC3339NullableDateTimeOffsetConverter))] + [System.Text.Json.Serialization.JsonPropertyName("update_time")] + [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RFC3339NullableDateTimeOffsetConverter))] + public DateTimeOffset? UpdateTime { get; set; } + } +}