From c004c3e29a7073e9bc8e917b1d4f4e5533152c45 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Sat, 9 Oct 2021 16:57:16 +0800 Subject: [PATCH] =?UTF-8?q?feat(openai):=20=E6=96=B0=E5=A2=9E=E5=85=AC?= =?UTF-8?q?=E4=BC=97=E5=8F=B7=E3=80=81=E5=B0=8F=E7=A8=8B=E5=BA=8F=E3=80=81?= =?UTF-8?q?H5=20=E7=BB=91=E5=AE=9A=E7=9B=B8=E5=85=B3=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...nAIClientExecuteOpenApiLivingExtensions.cs | 2 +- ...tOpenAIClientExecuteOpenApiMpExtensions.cs | 131 ++++++++++++++++++ ...AIClientExecuteOpenApiThirdKfExtensions.cs | 9 ++ .../OpenApiLiving/OpenApiBatchReplyRequest.cs | 2 +- .../OpenApiBatchSetAutoReplyRequest.cs | 2 +- .../OpenApiGenerateReportRequest.cs | 2 +- .../OpenApiMp/OpenApiAssetsUploadRequest.cs | 37 +++++ .../OpenApiMp/OpenApiAssetsUploadResponse.cs | 25 ++++ .../OpenApiMp/OpenApiGetBindLinkRequest.cs | 19 +++ .../OpenApiMp/OpenApiGetBindLinkResponse.cs | 18 +++ .../OpenApiMp/OpenApiGetBindListRequest.cs | 14 ++ .../OpenApiMp/OpenApiGetBindListResponse.cs | 18 +++ .../OpenApiMp/OpenApiGetH5LinkRequest.cs | 19 +++ .../OpenApiMp/OpenApiGetH5LinkResponse.cs | 18 +++ .../OpenApiMp/OpenApiUnbindMpRequest.cs | 20 +++ .../OpenApiMp/OpenApiUnbindMpResponse.cs | 12 ++ .../OpenApiKefuStateChangeRequest.cs | 8 +- .../OpenApiKefuStateGetRequest.cs | 8 +- .../OpenApiSendMessageRequest.cs | 10 +- .../WechatOpenAIClient.cs | 10 +- .../WechatOpenAIRequest.cs | 16 +-- 21 files changed, 377 insertions(+), 23 deletions(-) create mode 100644 src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteOpenApiMpExtensions.cs create mode 100644 src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiMp/OpenApiAssetsUploadRequest.cs create mode 100644 src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiMp/OpenApiAssetsUploadResponse.cs create mode 100644 src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiMp/OpenApiGetBindLinkRequest.cs create mode 100644 src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiMp/OpenApiGetBindLinkResponse.cs create mode 100644 src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiMp/OpenApiGetBindListRequest.cs create mode 100644 src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiMp/OpenApiGetBindListResponse.cs create mode 100644 src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiMp/OpenApiGetH5LinkRequest.cs create mode 100644 src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiMp/OpenApiGetH5LinkResponse.cs create mode 100644 src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiMp/OpenApiUnbindMpRequest.cs create mode 100644 src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiMp/OpenApiUnbindMpResponse.cs diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteOpenApiLivingExtensions.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteOpenApiLivingExtensions.cs index 8f40ede9..7b2a30c0 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteOpenApiLivingExtensions.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteOpenApiLivingExtensions.cs @@ -16,7 +16,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI /// /// /// - public static async Task ExecuteOpenApiSendMessageAsync(this WechatOpenAIClient client, Models.OpenApiBatchReplyRequest request, CancellationToken cancellationToken = default) + public static async Task ExecuteOpenApiBatchReplyAsync(this WechatOpenAIClient client, Models.OpenApiBatchReplyRequest request, CancellationToken cancellationToken = default) { if (client is null) throw new ArgumentNullException(nameof(client)); if (request is null) throw new ArgumentNullException(nameof(request)); diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteOpenApiMpExtensions.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteOpenApiMpExtensions.cs new file mode 100644 index 00000000..c7b19d0a --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteOpenApiMpExtensions.cs @@ -0,0 +1,131 @@ +using System; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Web; +using Flurl.Http; + +namespace SKIT.FlurlHttpClient.Wechat.OpenAI +{ + public static class WechatOpenAIClientExecuteOpenApiMpExtensions + { + /// + /// 异步调用 [POST] /openapi/getbindlink/{TOKEN} 接口。 + /// REF: https://developers.weixin.qq.com/doc/aispeech/platform/mp/getbindlink.html + /// + /// + /// + /// + /// + public static async Task ExecuteOpenApiGetBindLinkAsync(this WechatOpenAIClient client, Models.OpenApiGetBindLinkRequest request, CancellationToken cancellationToken = default) + { + if (client is null) throw new ArgumentNullException(nameof(client)); + if (request is null) throw new ArgumentNullException(nameof(request)); + + IFlurlRequest flurlReq = client + .CreateRequest(request, HttpMethod.Post, "openapi", "getbindlink", client.Credentials.PushToken!); + + return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); + } + + /// + /// 异步调用 [POST] /openapi/getbindlist/{TOKEN} 接口。 + /// REF: https://developers.weixin.qq.com/doc/aispeech/platform/mp/getbindlist.html + /// + /// + /// + /// + /// + public static async Task ExecuteOpenApiGetBindListAsync(this WechatOpenAIClient client, Models.OpenApiGetBindListRequest request, CancellationToken cancellationToken = default) + { + if (client is null) throw new ArgumentNullException(nameof(client)); + if (request is null) throw new ArgumentNullException(nameof(request)); + + IFlurlRequest flurlReq = client + .CreateRequest(request, HttpMethod.Post, "openapi", "getbindlist", client.Credentials.PushToken!); + + return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); + } + + /// + /// 异步调用 [POST] /openapi/unbindmp/{TOKEN} 接口。 + /// REF: https://developers.weixin.qq.com/doc/aispeech/platform/mp/unbindmp.html + /// + /// + /// + /// + /// + public static async Task ExecuteOpenApiUnbindMpAsync(this WechatOpenAIClient client, Models.OpenApiUnbindMpRequest request, CancellationToken cancellationToken = default) + { + if (client is null) throw new ArgumentNullException(nameof(client)); + if (request is null) throw new ArgumentNullException(nameof(request)); + + IFlurlRequest flurlReq = client + .CreateRequest(request, HttpMethod.Post, "openapi", "unbindmp", client.Credentials.PushToken!); + + return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); + } + + /// + /// 异步调用 [POST] /openapi/geth5link/{TOKEN} 接口。 + /// REF: https://developers.weixin.qq.com/doc/aispeech/platform/mp/getbindlist.html + /// + /// + /// + /// + /// + public static async Task ExecuteOpenApiGetH5LinkAsync(this WechatOpenAIClient client, Models.OpenApiGetH5LinkRequest request, CancellationToken cancellationToken = default) + { + if (client is null) throw new ArgumentNullException(nameof(client)); + if (request is null) throw new ArgumentNullException(nameof(request)); + + IFlurlRequest flurlReq = client + .CreateRequest(request, HttpMethod.Post, "openapi", "geth5link", client.Credentials.PushToken!); + + return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); + } + + + /// + /// 异步调用 [POST] /openapi/assetsupload/{TOKEN} 接口。 + /// REF: https://developers.weixin.qq.com/doc/aispeech/platform/mp/assetsupload.html + /// + /// + /// + /// + /// + public static async Task ExecuteFileUploadAsync(this WechatOpenAIClient client, Models.FileUploadRequest request, CancellationToken cancellationToken = default) + { + if (client is null) throw new ArgumentNullException(nameof(client)); + if (request is null) throw new ArgumentNullException(nameof(request)); + + if (request.FileName == null) + request.FileName = Guid.NewGuid().ToString("N").ToLower() + ".csv"; + + if (request.FileContentType == null) + request.FileContentType = "text/csv"; + + IFlurlRequest flurlReq = client + .CreateRequest(request, HttpMethod.Post, "openapi", "assetsupload", client.Credentials.PushToken!); + + using var fileContent = new ByteArrayContent(request.FileBytes ?? new byte[0]); + using var paramContent = new StringContent( + Utilities.WxBizMsgCryptor.AESEncrypt( + plainText: Utilities.XmlUtility.Serialize(request), + encodingAESKey: client.Credentials.PushEncodingAESKey!, + appId: client.Credentials.AppId! + ), + Encoding.UTF8 + );; + using var httpContent = new MultipartFormDataContent(); + httpContent.Add(fileContent, "\"media\"", $"\"{HttpUtility.UrlEncode(request.FileName)}\""); + httpContent.Add(paramContent, "\"encrypt\""); + fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse(request.FileContentType); + fileContent.Headers.ContentLength = request.FileBytes?.Length; + + return await client.SendRequestAsync(flurlReq, httpContent: httpContent, cancellationToken: cancellationToken); + } + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteOpenApiThirdKfExtensions.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteOpenApiThirdKfExtensions.cs index be70b43b..a4f2bff3 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteOpenApiThirdKfExtensions.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteOpenApiThirdKfExtensions.cs @@ -21,6 +21,9 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI if (client is null) throw new ArgumentNullException(nameof(client)); if (request is null) throw new ArgumentNullException(nameof(request)); + if (request.AppId == null) + request.AppId = client.Credentials.AppId; + IFlurlRequest flurlReq = client .CreateRequest(request, HttpMethod.Post, "openapi", "sendmsg", client.Credentials.PushToken!); @@ -40,6 +43,9 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI if (client is null) throw new ArgumentNullException(nameof(client)); if (request is null) throw new ArgumentNullException(nameof(request)); + if (request.AppId == null) + request.AppId = client.Credentials.AppId; + IFlurlRequest flurlReq = client .CreateRequest(request, HttpMethod.Post, "openapi", "kefustate", "get", client.Credentials.PushToken!); @@ -59,6 +65,9 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI if (client is null) throw new ArgumentNullException(nameof(client)); if (request is null) throw new ArgumentNullException(nameof(request)); + if (request.AppId == null) + request.AppId = client.Credentials.AppId; + IFlurlRequest flurlReq = client .CreateRequest(request, HttpMethod.Post, "openapi", "kefustate", "change", client.Credentials.PushToken!); diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiLiving/OpenApiBatchReplyRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiLiving/OpenApiBatchReplyRequest.cs index ab508990..cd546439 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiLiving/OpenApiBatchReplyRequest.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiLiving/OpenApiBatchReplyRequest.cs @@ -8,7 +8,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models /// 表示 [POST] /openapi/batchreply/{TOKEN} 接口的请求。 /// [XmlRoot("xml")] - public class OpenApiBatchReplyRequest : WechatOpenAIRequestEncryptedXmlable + public class OpenApiBatchReplyRequest : WechatOpenAIRequest, WechatOpenAIRequest.Serialization.IEncryptedXmlable { /// /// 获取或设置直播 ID。 diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiLiving/OpenApiBatchSetAutoReplyRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiLiving/OpenApiBatchSetAutoReplyRequest.cs index 854aff99..b9118b64 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiLiving/OpenApiBatchSetAutoReplyRequest.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiLiving/OpenApiBatchSetAutoReplyRequest.cs @@ -8,7 +8,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models /// 表示 [POST] /openapi/setautoreply/{TOKEN} 接口的请求。 /// [XmlRoot("xml")] - public class OpenApiBatchSetAutoReplyRequest : WechatOpenAIRequestEncryptedXmlable + public class OpenApiBatchSetAutoReplyRequest : WechatOpenAIRequest, WechatOpenAIRequest.Serialization.IEncryptedXmlable { /// /// 获取或设置管理员 ID。 diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiLiving/OpenApiGenerateReportRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiLiving/OpenApiGenerateReportRequest.cs index e7f1002e..627b0ca4 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiLiving/OpenApiGenerateReportRequest.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiLiving/OpenApiGenerateReportRequest.cs @@ -8,7 +8,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models /// 表示 [POST] /openapi/generatereport/{TOKEN} 接口的请求。 /// [XmlRoot("xml")] - public class OpenApiGenerateReportRequest : WechatOpenAIRequestEncryptedXmlable + public class OpenApiGenerateReportRequest : WechatOpenAIRequest, WechatOpenAIRequest.Serialization.IEncryptedXmlable { /// /// 获取或设置直播 ID。 diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiMp/OpenApiAssetsUploadRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiMp/OpenApiAssetsUploadRequest.cs new file mode 100644 index 00000000..040acfc7 --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiMp/OpenApiAssetsUploadRequest.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Xml.Serialization; + +namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models +{ + /// + /// 表示 [POST] /openapi/assetsupload/{TOKEN} 接口的请求。 + /// + [XmlRoot("xml")] + public class OpenApiAssetsUploadRequest : WechatOpenAIRequest, WechatOpenAIRequest.Serialization.IEncryptedXmlable + { + /// + /// 获取或设置用户 ID。 + /// + [XmlElement("userid")] + public string UserId { get; set; } = string.Empty; + + /// + /// 获取或设置文件字节数组。 + /// + [XmlIgnore] + public byte[] FileBytes { get; set; } = new byte[0]; + + /// + /// 获取或设置文件名。如果不指定将由系统自动生成。 + /// + [XmlIgnore] + public string? FileName { get; set; } + + /// + /// 获取或设置文件 Conent-Type。如果不指定将由系统自动生成。 + /// + [XmlIgnore] + public string? FileContentType { get; set; } + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiMp/OpenApiAssetsUploadResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiMp/OpenApiAssetsUploadResponse.cs new file mode 100644 index 00000000..1109eeea --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiMp/OpenApiAssetsUploadResponse.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; + +namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models +{ + /// + /// 表示 [POST] /openapi/assetsupload/{TOKEN} 接口的响应。 + /// + public class OpenApiAssetsUploadResponse : WechatOpenAIResponse + { + /// + /// 获取或设置文件标识。 + /// + [Newtonsoft.Json.JsonProperty("filekey")] + [System.Text.Json.Serialization.JsonPropertyName("filekey")] + public string FileKey { get; set; } = default!; + + /// + /// 获取或设置文件 URL。 + /// + [Newtonsoft.Json.JsonProperty("url")] + [System.Text.Json.Serialization.JsonPropertyName("url")] + public string Url { get; set; } = default!; + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiMp/OpenApiGetBindLinkRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiMp/OpenApiGetBindLinkRequest.cs new file mode 100644 index 00000000..8972d0c3 --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiMp/OpenApiGetBindLinkRequest.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Xml.Serialization; + +namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models +{ + /// + /// 表示 [POST] /openapi/getbindlink/{TOKEN} 接口的请求。 + /// + [XmlRoot("xml")] + public class OpenApiGetBindLinkRequest : WechatOpenAIRequest, WechatOpenAIRequest.Serialization.IEncryptedXmlable + { + /// + /// 获取或设置直播 ID。 + /// + [XmlElement("redirectlink")] + public string RedirectLink { get; set; } = string.Empty; + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiMp/OpenApiGetBindLinkResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiMp/OpenApiGetBindLinkResponse.cs new file mode 100644 index 00000000..7d89e697 --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiMp/OpenApiGetBindLinkResponse.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; + +namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models +{ + /// + /// 表示 [POST] /openapi/getbindlink/{TOKEN} 接口的响应。 + /// + public class OpenApiGetBindLinkResponse : WechatOpenAIResponse + { + /// + /// 获取或设置绑定链接 URL。 + /// + [Newtonsoft.Json.JsonProperty("link")] + [System.Text.Json.Serialization.JsonPropertyName("link")] + public string Url { get; set; } = default!; + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiMp/OpenApiGetBindListRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiMp/OpenApiGetBindListRequest.cs new file mode 100644 index 00000000..6a9c5e4d --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiMp/OpenApiGetBindListRequest.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Xml.Serialization; + +namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models +{ + /// + /// 表示 [POST] /openapi/getbindlink/{TOKEN} 接口的请求。 + /// + [XmlRoot("xml")] + public class OpenApiGetBindListRequest : WechatOpenAIRequest, WechatOpenAIRequest.Serialization.IEncryptedXmlable + { + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiMp/OpenApiGetBindListResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiMp/OpenApiGetBindListResponse.cs new file mode 100644 index 00000000..fcd428b7 --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiMp/OpenApiGetBindListResponse.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; + +namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models +{ + /// + /// 表示 [POST] /openapi/getbindlink/{TOKEN} 接口的响应。 + /// + public class OpenApiGetBindListResponse : WechatOpenAIResponse + { + /// + /// 获取或设置绑定列表。 + /// + [Newtonsoft.Json.JsonProperty("bindlist")] + [System.Text.Json.Serialization.JsonPropertyName("bindlist")] + public object[] BindList { get; set; } = default!; + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiMp/OpenApiGetH5LinkRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiMp/OpenApiGetH5LinkRequest.cs new file mode 100644 index 00000000..c908692d --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiMp/OpenApiGetH5LinkRequest.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Xml.Serialization; + +namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models +{ + /// + /// 表示 [POST] /openapi/geth5link/{TOKEN} 接口的请求。 + /// + [XmlRoot("xml")] + public class OpenApiGetH5LinkRequest : WechatOpenAIRequest, WechatOpenAIRequest.Serialization.IEncryptedXmlable + { + /// + /// 获取或设置页面标题。 + /// + [XmlElement("title", IsNullable = true)] + public string? Title { get; set; } + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiMp/OpenApiGetH5LinkResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiMp/OpenApiGetH5LinkResponse.cs new file mode 100644 index 00000000..9d2af9e9 --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiMp/OpenApiGetH5LinkResponse.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; + +namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models +{ + /// + /// 表示 [POST] /openapi/geth5link/{TOKEN} 接口的响应。 + /// + public class OpenApiGetH5LinkResponse : WechatOpenAIResponse + { + /// + /// 获取或设置机器人链接 URL。 + /// + [Newtonsoft.Json.JsonProperty("link")] + [System.Text.Json.Serialization.JsonPropertyName("link")] + public string Url { get; set; } = default!; + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiMp/OpenApiUnbindMpRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiMp/OpenApiUnbindMpRequest.cs new file mode 100644 index 00000000..d3e7d41e --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiMp/OpenApiUnbindMpRequest.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Xml.Serialization; + +namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models +{ + /// + /// 表示 [POST] /openapi/unbindmp/{TOKEN} 接口的请求。 + /// + [XmlRoot("xml")] + public class OpenApiUnbindMpRequest : WechatOpenAIRequest, WechatOpenAIRequest.Serialization.IEncryptedXmlable + { + /// + /// 获取或设置微信 AppId。 + /// + [Newtonsoft.Json.JsonProperty("authorizer_appid")] + [System.Text.Json.Serialization.JsonPropertyName("authorizer_appid")] + public string AuthorizerAppId { get; set; } = string.Empty; + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiMp/OpenApiUnbindMpResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiMp/OpenApiUnbindMpResponse.cs new file mode 100644 index 00000000..f783b082 --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiMp/OpenApiUnbindMpResponse.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; + +namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models +{ + /// + /// 表示 [POST] /openapi/unbindmp/{TOKEN} 接口的响应。 + /// + public class OpenApiUnbindMpResponse : WechatOpenAIResponse + { + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiThirdKf/OpenApiKefuStateChangeRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiThirdKf/OpenApiKefuStateChangeRequest.cs index 2c61be57..3b883ef1 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiThirdKf/OpenApiKefuStateChangeRequest.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiThirdKf/OpenApiKefuStateChangeRequest.cs @@ -8,8 +8,14 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models /// 表示 [POST] /openapi/kefustate/change/{TOKEN} 接口的请求。 /// [XmlRoot("xml")] - public class OpenApiKefuStateChangeRequest : WechatOpenAIRequestEncryptedXmlable + public class OpenApiKefuStateChangeRequest : WechatOpenAIRequest, WechatOpenAIRequest.Serialization.IEncryptedXmlable { + /// + /// 获取或设置微信 AppId。如果不指定将使用构造 时的 参数。 + /// + [XmlElement("appid")] + public string? AppId { get; set; } + /// /// 获取或设置用户的 OpenId。 /// diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiThirdKf/OpenApiKefuStateGetRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiThirdKf/OpenApiKefuStateGetRequest.cs index 2c8f36e1..3fb3ead8 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiThirdKf/OpenApiKefuStateGetRequest.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiThirdKf/OpenApiKefuStateGetRequest.cs @@ -8,8 +8,14 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models /// 表示 [POST] /openapi/kefustate/get/{TOKEN} 接口的请求。 /// [XmlRoot("xml")] - public class OpenApiKefuStateGetRequest : WechatOpenAIRequestEncryptedXmlable + public class OpenApiKefuStateGetRequest : WechatOpenAIRequest, WechatOpenAIRequest.Serialization.IEncryptedXmlable { + /// + /// 获取或设置微信 AppId。如果不指定将使用构造 时的 参数。 + /// + [XmlElement("appid")] + public string? AppId { get; set; } + /// /// 获取或设置用户的 OpenId。 /// diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiThirdKf/OpenApiSendMessageRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiThirdKf/OpenApiSendMessageRequest.cs index 6b405c45..0e88e94b 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiThirdKf/OpenApiSendMessageRequest.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiThirdKf/OpenApiSendMessageRequest.cs @@ -8,8 +8,14 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models /// 表示 [POST] /openapi/sendmsg/{TOKEN} 接口的请求。 /// [XmlRoot("xml")] - public class OpenApiSendMessageRequest : WechatOpenAIRequestEncryptedXmlable - { + public class OpenApiSendMessageRequest : WechatOpenAIRequest, WechatOpenAIRequest.Serialization.IEncryptedXmlable + { + /// + /// 获取或设置微信 AppId。如果不指定将使用构造 时的 参数。 + /// + [XmlElement("appid")] + public string? AppId { get; set; } + /// /// 获取或设置用户的 OpenId。 /// diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIClient.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIClient.cs index 0f3bc68c..c272f94f 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIClient.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIClient.cs @@ -112,13 +112,11 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI { try { - if (data is WechatOpenAIRequestEncryptedXmlable xmlData) + if (data is WechatOpenAIRequest.Serialization.IEncryptedXmlable) { - if (xmlData.AppId == null) - xmlData.AppId = Credentials.AppId; - - string xml = Utilities.XmlUtility.Serialize(xmlData); - data = new { encrypt = Utilities.WxBizMsgCryptor.AESEncrypt(plainText: xml, encodingAESKey: Credentials.PushEncodingAESKey!, appId: xmlData.AppId!) }; + string plainXml = Utilities.XmlUtility.Serialize(data); + string encryptedXml = Utilities.WxBizMsgCryptor.AESEncrypt(plainText: plainXml, encodingAESKey: Credentials.PushEncodingAESKey!, appId: Credentials.AppId!); + data = new { encrypt = encryptedXml }; } using IFlurlResponse flurlResponse = await base.SendRequestWithJsonAsync(flurlRequest, data, cancellationToken).ConfigureAwait(false); diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIRequest.cs index 83f8fdca..1c90cbf0 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIRequest.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIRequest.cs @@ -7,6 +7,13 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI /// public abstract class WechatOpenAIRequest : IWechatRequest { + public static class Serialization + { + public interface IEncryptedXmlable + { + } + } + /// /// 获取或设置请求超时时间(单位:毫秒)。如果不指定将使用构造 时的 参数,这在需要指定特定耗时请求(比如上传或下载文件)的超时时间时很有用。 /// @@ -43,13 +50,4 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI [System.Xml.Serialization.SoapIgnore] public virtual string? AccessToken { get; set; } } - - public abstract class WechatOpenAIRequestEncryptedXmlable : WechatOpenAIRequest - { - /// - /// 获取或设置微信 AppId。如果不指定将使用构造 时的 参数。 - /// - [System.Xml.Serialization.XmlElement("appid")] - public string? AppId { get; set; } - } }