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; }
- }
}