From 3d432ceb85821979ada2cc5e274501bb448bf43f Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Sat, 9 Oct 2021 15:17:35 +0800 Subject: [PATCH] =?UTF-8?q?feat(openai):=20=E6=96=B0=E5=A2=9E=E7=AC=AC?= =?UTF-8?q?=E4=B8=89=E6=96=B9=E5=AE=A2=E6=9C=8D=E6=8E=A5=E5=85=A5=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Events/ThirdKf/UserEnterEvent.cs | 60 ++++++++++++++++ .../Events/ThirdKf/UserQuitEvent.cs | 13 ++++ .../WechatOpenAIClientEventExtensions.cs | 13 +--- ...AIClientExecuteOpenApiThirdKfExtensions.cs | 72 +++++++++++++++++++ .../OpenApiKefuStateChangeRequest.cs | 32 +++++++++ .../OpenApiKefuStateChangeResponse.cs | 12 ++++ .../OpenApiKefuStateGetRequest.cs | 19 +++++ .../OpenApiKefuStateGetResponse.cs | 18 +++++ .../OpenApiSendMessageRequest.cs | 49 +++++++++++++ .../OpenApiSendMessageResponse.cs | 12 ++++ .../Utilities/Internal/XmlUtility.cs | 37 ++++++++++ .../WechatOpenAIClient.cs | 9 +++ .../WechatOpenAIRequest.cs | 17 +++++ .../WechatOpenAIResponse.cs | 28 ++++++-- .../IWechatRequest.cs | 4 +- .../IWechatResponse.cs | 9 +-- .../EventSamples/ThirdKf/UserEnterEvent.xml | 13 ++++ .../EventSamples/ThirdKf/UserQuitEvent.xml | 10 +++ ...lHttpClient.Wechat.OpenAI.UnitTests.csproj | 1 + 19 files changed, 398 insertions(+), 30 deletions(-) create mode 100644 src/SKIT.FlurlHttpClient.Wechat.OpenAI/Events/ThirdKf/UserEnterEvent.cs create mode 100644 src/SKIT.FlurlHttpClient.Wechat.OpenAI/Events/ThirdKf/UserQuitEvent.cs create mode 100644 src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteOpenApiThirdKfExtensions.cs create mode 100644 src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiThirdKf/OpenApiKefuStateChangeRequest.cs create mode 100644 src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiThirdKf/OpenApiKefuStateChangeResponse.cs create mode 100644 src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiThirdKf/OpenApiKefuStateGetRequest.cs create mode 100644 src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiThirdKf/OpenApiKefuStateGetResponse.cs create mode 100644 src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiThirdKf/OpenApiSendMessageRequest.cs create mode 100644 src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiThirdKf/OpenApiSendMessageResponse.cs create mode 100644 src/SKIT.FlurlHttpClient.Wechat.OpenAI/Utilities/Internal/XmlUtility.cs create mode 100644 test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/EventSamples/ThirdKf/UserEnterEvent.xml create mode 100644 test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/EventSamples/ThirdKf/UserQuitEvent.xml diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Events/ThirdKf/UserEnterEvent.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Events/ThirdKf/UserEnterEvent.cs new file mode 100644 index 00000000..522eb3ba --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Events/ThirdKf/UserEnterEvent.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; + +namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Events +{ + /// + /// 表示 userEnter 事件的数据。 + /// REF: https://developers.weixin.qq.com/doc/aispeech/platform/thirdkefu/recivemsg.html + /// + public class UserEnterEvent : WechatOpenAIEvent, WechatOpenAIEvent.Serialization.IXmlSerializable + { + public static class Types + { + public class Content + { + /// + /// 获取或设置消息。 + /// + [System.Xml.Serialization.XmlElement("msg")] + public string Message { get; set; } = default!; + } + } + + /// + /// 获取或设置用户 ID。 + /// + [System.Xml.Serialization.XmlElement("userid")] + public string UserId { get; set; } = default!; + + /// + /// 获取或设置对话来源。 + /// + [System.Xml.Serialization.XmlElement("from")] + public string From { get; set; } = default!; + + /// + /// 获取或设置消息内容。 + /// + [System.Xml.Serialization.XmlElement("content")] + public Types.Content? Content { get; set; } + + /// + /// 获取或设置客服接入状态。 + /// + [System.Xml.Serialization.XmlElement("status")] + public int Status { get; set; } + + /// + /// 获取或设置渠道。 + /// + [System.Xml.Serialization.XmlElement("channel", IsNullable = true)] + public string? Channel { get; set; } + + /// + /// 获取或设置用户评价。 + /// + [System.Xml.Serialization.XmlElement("assessment", IsNullable = true)] + public int? Assessment { get; set; } + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Events/ThirdKf/UserQuitEvent.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Events/ThirdKf/UserQuitEvent.cs new file mode 100644 index 00000000..ae2bb8d1 --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Events/ThirdKf/UserQuitEvent.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; + +namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Events +{ + /// + /// 表示 userQuit 事件的数据。 + /// REF: https://developers.weixin.qq.com/doc/aispeech/platform/thirdkefu/recivemsg.html + /// + public class UserQuitEvent : UserEnterEvent + { + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientEventExtensions.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientEventExtensions.cs index 82694c5b..b0cb77ed 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientEventExtensions.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientEventExtensions.cs @@ -98,18 +98,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI try { - using var stream = new MemoryStream(); - using var writer = new System.Xml.XmlTextWriter(stream, Encoding.UTF8); - writer.Formatting = System.Xml.Formatting.None; - - XmlSerializer xmlSerializer = new XmlSerializer(typeof(TEvent), new XmlRootAttribute("xml")); - XmlSerializerNamespaces xmlNamespace = new XmlSerializerNamespaces(); - xmlNamespace.Add(string.Empty, string.Empty); - xmlSerializer.Serialize(writer, callbackModel, xmlNamespace); - writer.Flush(); - xml = Encoding.UTF8.GetString(stream.ToArray()); - xml = Regex.Replace(xml, "\\s+<\\w+ (xsi|d2p1):nil=\"true\"[^>]*/>", string.Empty, RegexOptions.IgnoreCase); - xml = Regex.Replace(xml, "<\\?xml[^>]*\\?>", string.Empty, RegexOptions.IgnoreCase); + xml = Utilities.XmlUtility.Serialize(callbackModel); } catch (Exception ex) { diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteOpenApiThirdKfExtensions.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteOpenApiThirdKfExtensions.cs new file mode 100644 index 00000000..ffd9dbb8 --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteOpenApiThirdKfExtensions.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Flurl; +using Flurl.Http; + +namespace SKIT.FlurlHttpClient.Wechat.OpenAI +{ + public static class WechatOpenAIClientExecuteOpenApiThirdKfExtensions + { + /// + /// 异步调用 [POST] /openapi/sendmsg/{TOKEN} 接口。 + /// REF: https://developers.weixin.qq.com/doc/aispeech/platform/thirdkefu/sendmsg.html + /// + /// + /// + /// + /// + public static async Task ExecuteOpenApiSendMessageAsync(this WechatOpenAIClient client, Models.OpenApiSendMessageRequest 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", "sendmsg", client.Credentials.PushToken!); + + return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); + } + + /// + /// 异步调用 [POST] /openapi/kefustate/get/{TOKEN} 接口。 + /// REF: https://developers.weixin.qq.com/doc/aispeech/platform/thirdkefu/getstate.html + /// + /// + /// + /// + /// + public static async Task ExecuteOpenApiKefuStateGetAsync(this WechatOpenAIClient client, Models.OpenApiKefuStateGetRequest 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", "kefustate", "get", client.Credentials.PushToken!); + + return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); + } + + /// + /// 异步调用 [POST] /openapi/kefustate/change/{TOKEN} 接口。 + /// REF: https://developers.weixin.qq.com/doc/aispeech/platform/thirdkefu/getstate.html + /// + /// + /// + /// + /// + public static async Task ExecuteOpenApiKefuStateChangeAsync(this WechatOpenAIClient client, Models.OpenApiKefuStateChangeRequest 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", "kefustate", "change", client.Credentials.PushToken!); + + return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); + } + + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiThirdKf/OpenApiKefuStateChangeRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiThirdKf/OpenApiKefuStateChangeRequest.cs new file mode 100644 index 00000000..2c61be57 --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiThirdKf/OpenApiKefuStateChangeRequest.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Xml.Serialization; + +namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models +{ + /// + /// 表示 [POST] /openapi/kefustate/change/{TOKEN} 接口的请求。 + /// + [XmlRoot("xml")] + public class OpenApiKefuStateChangeRequest : WechatOpenAIRequestEncryptedXmlable + { + /// + /// 获取或设置用户的 OpenId。 + /// + [XmlElement("openid")] + public string OpenId { get; set; } = string.Empty; + + /// + /// 获取或设置客服接入状态。 + /// + [XmlElement("kefustate")] + public string State { get; set; } = string.Empty; + + /// + /// 获取或设置有效期(单位:秒)。 + /// 默认值:1800 + /// + [XmlElement("expires")] + public int ExpiresIn { get; set; } = 1800; + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiThirdKf/OpenApiKefuStateChangeResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiThirdKf/OpenApiKefuStateChangeResponse.cs new file mode 100644 index 00000000..8315485f --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiThirdKf/OpenApiKefuStateChangeResponse.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; + +namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models +{ + /// + /// 表示 [POST] /openapi/kefustate/change/{TOKEN} 接口的响应。 + /// + public class OpenApiKefuStateChangeResponse : WechatOpenAIResponse + { + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiThirdKf/OpenApiKefuStateGetRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiThirdKf/OpenApiKefuStateGetRequest.cs new file mode 100644 index 00000000..2c8f36e1 --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiThirdKf/OpenApiKefuStateGetRequest.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Xml.Serialization; + +namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models +{ + /// + /// 表示 [POST] /openapi/kefustate/get/{TOKEN} 接口的请求。 + /// + [XmlRoot("xml")] + public class OpenApiKefuStateGetRequest : WechatOpenAIRequestEncryptedXmlable + { + /// + /// 获取或设置用户的 OpenId。 + /// + [XmlElement("openid")] + public string OpenId { get; set; } = string.Empty; + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiThirdKf/OpenApiKefuStateGetResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiThirdKf/OpenApiKefuStateGetResponse.cs new file mode 100644 index 00000000..071316dc --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiThirdKf/OpenApiKefuStateGetResponse.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; + +namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models +{ + /// + /// 表示 [POST] /openapi/kefustate/get/{TOKEN} 接口的响应。 + /// + public class OpenApiKefuStateGetResponse : WechatOpenAIResponse + { + /// + /// 获取或设置客户接入状态。 + /// + [Newtonsoft.Json.JsonProperty("kefustate")] + [System.Text.Json.Serialization.JsonPropertyName("kefustate")] + public string State { get; set; } = default!; + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiThirdKf/OpenApiSendMessageRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiThirdKf/OpenApiSendMessageRequest.cs new file mode 100644 index 00000000..f80e0a3b --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiThirdKf/OpenApiSendMessageRequest.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Xml.Serialization; + +namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models +{ + /// + /// 表示 [POST] /openapi/sendmsg/{TOKEN} 接口的请求。 + /// + [XmlRoot("xml")] + public class OpenApiSendMessageRequest : WechatOpenAIRequestEncryptedXmlable + { + /// + /// 获取或设置用户的 OpenId。 + /// + [XmlElement("openid")] + public string OpenId { get; set; } = string.Empty; + + /// + /// 获取或设置消息内容。 + /// + [XmlElement("msg")] + public string Message { get; set; } = string.Empty; + + /// + /// 获取或设置渠道。 + /// + [XmlElement("channel")] + public int Channel { get; set; } + + /// + /// 获取或设置事件。 + /// + [XmlElement("event")] + public string? Event { get; set; } + + /// + /// 获取或设置客服人员的昵称。 + /// + [XmlElement("kefuname")] + public string? KfName { get; set; } + + /// + /// 获取或设置客服人员的头像 URL。 + /// + [XmlElement("kefuavatar")] + public string? KfAvatarUrl { get; set; } + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiThirdKf/OpenApiSendMessageResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiThirdKf/OpenApiSendMessageResponse.cs new file mode 100644 index 00000000..7f3eef19 --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiThirdKf/OpenApiSendMessageResponse.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; + +namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models +{ + /// + /// 表示 [POST] /openapi/sendmsg/{TOKEN} 接口的响应。 + /// + public class OpenApiSendMessageResponse : WechatOpenAIResponse + { + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Utilities/Internal/XmlUtility.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Utilities/Internal/XmlUtility.cs new file mode 100644 index 00000000..13e4c775 --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Utilities/Internal/XmlUtility.cs @@ -0,0 +1,37 @@ +using System; +using System.IO; +using System.Text; +using System.Text.RegularExpressions; +using System.Xml.Serialization; + +namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Utilities +{ + internal static class XmlUtility + { + public static string Serialize(Type type, object obj) + { + string xml; + + using var stream = new MemoryStream(); + using var writer = new System.Xml.XmlTextWriter(stream, Encoding.UTF8); + writer.Formatting = System.Xml.Formatting.None; + + XmlSerializer xmlSerializer = new XmlSerializer(type, new XmlRootAttribute("xml")); + XmlSerializerNamespaces xmlNamespace = new XmlSerializerNamespaces(); + xmlNamespace.Add(string.Empty, string.Empty); + xmlSerializer.Serialize(writer, obj, xmlNamespace); + writer.Flush(); + xml = Encoding.UTF8.GetString(stream.ToArray()); + xml = Regex.Replace(xml, "\\s+<\\w+ (xsi|d2p1):nil=\"true\"[^>]*/>", string.Empty, RegexOptions.IgnoreCase); + xml = Regex.Replace(xml, "<\\?xml[^>]*\\?>", string.Empty, RegexOptions.IgnoreCase); + + return xml; + } + + public static string Serialize(T obj) + where T : class + { + return Serialize(typeof(T), obj); + } + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIClient.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIClient.cs index a049c8f1..0f3bc68c 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIClient.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIClient.cs @@ -112,6 +112,15 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI { try { + if (data is WechatOpenAIRequestEncryptedXmlable xmlData) + { + 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!) }; + } + using IFlurlResponse flurlResponse = await base.SendRequestWithJsonAsync(flurlRequest, data, cancellationToken).ConfigureAwait(false); return await GetResposneAsync(flurlResponse).ConfigureAwait(false); } diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIRequest.cs index be9c5937..83f8fdca 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIRequest.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIRequest.cs @@ -12,6 +12,8 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI /// [Newtonsoft.Json.JsonIgnore] [System.Text.Json.Serialization.JsonIgnore] + [System.Xml.Serialization.XmlIgnore] + [System.Xml.Serialization.SoapIgnore] public virtual int? Timeout { get; set; } /// @@ -19,6 +21,8 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI /// [Newtonsoft.Json.JsonIgnore] [System.Text.Json.Serialization.JsonIgnore] + [System.Xml.Serialization.XmlIgnore] + [System.Xml.Serialization.SoapIgnore] public virtual string? RequestId { get; set; } /// @@ -26,6 +30,8 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI /// [Newtonsoft.Json.JsonIgnore] [System.Text.Json.Serialization.JsonIgnore] + [System.Xml.Serialization.XmlIgnore] + [System.Xml.Serialization.SoapIgnore] public virtual string? BotId { get; set; } /// @@ -33,6 +39,17 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI /// [Newtonsoft.Json.JsonIgnore] [System.Text.Json.Serialization.JsonIgnore] + [System.Xml.Serialization.XmlIgnore] + [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; } + } } diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIResponse.cs index 0ed93ffd..4ea44e08 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIResponse.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIResponse.cs @@ -32,16 +32,30 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI /// /// 获取微信智能对话 API 返回的错误码。 /// - [Newtonsoft.Json.JsonProperty("code")] - [System.Text.Json.Serialization.JsonPropertyName("code")] - public virtual int ErrorCode { get; set; } + [Newtonsoft.Json.JsonProperty("errcode")] + [System.Text.Json.Serialization.JsonPropertyName("errcode")] + public virtual int? ErrorCode { get; set; } /// - /// 获取微信智能对话 API 返回的错误描述。 + /// 获取微信智能对话 API 返回的错误信息。 + /// + [Newtonsoft.Json.JsonProperty("errmsg")] + [System.Text.Json.Serialization.JsonPropertyName("errmsg")] + public virtual string? ErrorMessage { get; set; } + + /// + /// 获取微信智能对话 API 返回的状态码。 + /// + [Newtonsoft.Json.JsonProperty("code")] + [System.Text.Json.Serialization.JsonPropertyName("code")] + public virtual int? Code { get; set; } + + /// + /// 获取微信智能对话 API 返回的调用信息。 /// [Newtonsoft.Json.JsonProperty("msg")] [System.Text.Json.Serialization.JsonPropertyName("msg")] - public virtual string? ErrorMessage { get; set; } + public virtual string? Message { get; set; } /// /// 获取微信智能对话 API 返回的请求唯一标识。 @@ -51,12 +65,12 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI public virtual string? RequestId { get; set; } /// - /// 获取一个值,该值指示调用微信 API 是否成功(即 HTTP 状态码为 200、且 errcode 值为 0)。 + /// 获取一个值,该值指示调用微信 API 是否成功(即 HTTP 状态码为 200、且 code 和 errcode 值都为 0)。 /// /// public virtual bool IsSuccessful() { - return RawStatus == 200 && ErrorCode == 0; + return RawStatus == 200 && ErrorCode.GetValueOrDefault() == 0 && Code.GetValueOrDefault() == 0; } } diff --git a/src/SKIT.FlurlHttpClient.Wechat/IWechatRequest.cs b/src/SKIT.FlurlHttpClient.Wechat/IWechatRequest.cs index f983df0a..de02e4c2 100644 --- a/src/SKIT.FlurlHttpClient.Wechat/IWechatRequest.cs +++ b/src/SKIT.FlurlHttpClient.Wechat/IWechatRequest.cs @@ -1,6 +1,4 @@ -using System; - -namespace SKIT.FlurlHttpClient.Wechat +namespace SKIT.FlurlHttpClient.Wechat { /// /// SKIT.FlurlHttpClient.Wechat 请求接口。 diff --git a/src/SKIT.FlurlHttpClient.Wechat/IWechatResponse.cs b/src/SKIT.FlurlHttpClient.Wechat/IWechatResponse.cs index 97f3b97b..40a883e3 100644 --- a/src/SKIT.FlurlHttpClient.Wechat/IWechatResponse.cs +++ b/src/SKIT.FlurlHttpClient.Wechat/IWechatResponse.cs @@ -1,16 +1,9 @@ -using System; -using System.Collections.Generic; - -namespace SKIT.FlurlHttpClient.Wechat +namespace SKIT.FlurlHttpClient.Wechat { /// /// SKIT.FlurlHttpClient.Wechat 响应接口。 /// public interface IWechatResponse : ICommonResponse { - /// - /// 获取微信 API 返回的错误描述。 - /// - string? ErrorMessage { get; set; } } } diff --git a/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/EventSamples/ThirdKf/UserEnterEvent.xml b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/EventSamples/ThirdKf/UserEnterEvent.xml new file mode 100644 index 00000000..4c39b906 --- /dev/null +++ b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/EventSamples/ThirdKf/UserEnterEvent.xml @@ -0,0 +1,13 @@ + + 用户的唯一ID,(通常为用户在微信的openid) + 应用的appid + + 机器人或用户的的内容 + + userEnter + 0 + 0 + 渠0 + 0 + 1234567890 + \ No newline at end of file diff --git a/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/EventSamples/ThirdKf/UserQuitEvent.xml b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/EventSamples/ThirdKf/UserQuitEvent.xml new file mode 100644 index 00000000..4bfbb88b --- /dev/null +++ b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/EventSamples/ThirdKf/UserQuitEvent.xml @@ -0,0 +1,10 @@ + + 用户的唯一ID,(通常为用户在微信的openid) + 应用的appid + userQuit + 0 + 0 + 渠0 + 0 + 1234567890 + \ No newline at end of file diff --git a/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests.csproj b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests.csproj index 1338fd3c..72d255b9 100644 --- a/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests.csproj +++ b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests.csproj @@ -11,6 +11,7 @@ PreserveNewest +