diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Events/ThirdKf/UserEnterEvent.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Events/ThirdKf/UserEnterEvent.cs index baee00b8..596c528f 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Events/ThirdKf/UserEnterEvent.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Events/ThirdKf/UserEnterEvent.cs @@ -4,7 +4,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Events /// 表示 userEnter 事件的数据。 /// REF: https://developers.weixin.qq.com/doc/aispeech/confapi/thirdkefu/recivemsg.html /// - public class UserEnterEvent : WechatOpenAIEvent, WechatOpenAIEvent.Serialization.IXmlSerializable + public class UserEnterEvent : WechatOpenAIEvent { public static class Types { diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Exceptions/WechatOpenAIEventSerializationException.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Exceptions/WechatOpenAIEventSerializationException.cs deleted file mode 100644 index c85e61ca..00000000 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Exceptions/WechatOpenAIEventSerializationException.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; - -namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Exceptions -{ - public class WechatOpenAIEventSerializationException : WechatOpenAIException - { - /// - internal WechatOpenAIEventSerializationException() - { - } - - /// - internal WechatOpenAIEventSerializationException(string message) - : base(message) - { - } - - /// - internal WechatOpenAIEventSerializationException(string message, Exception innerException) - : base(message, innerException) - { - } - } -} diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Exceptions/WechatOpenAIRequestTimeoutException.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Exceptions/WechatOpenAIRequestTimeoutException.cs deleted file mode 100644 index 7676e2be..00000000 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Exceptions/WechatOpenAIRequestTimeoutException.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; - -namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Exceptions -{ - public class WechatOpenAIRequestTimeoutException : WechatOpenAIException - { - /// - internal WechatOpenAIRequestTimeoutException() - { - } - - /// - internal WechatOpenAIRequestTimeoutException(string message) - : base(message) - { - } - - /// - internal WechatOpenAIRequestTimeoutException(string message, Exception innerException) - : base(message, innerException) - { - } - } -} diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientEventExtensions.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientEventExtensions.cs index 0bc54236..10ea60ef 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientEventExtensions.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientEventExtensions.cs @@ -7,19 +7,19 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI /// public static class WechatOpenAIClientEventExtensions { - private static TEvent InnerDeserializeEventFromXml(this WechatOpenAIClient client, string callbackXml) + private static TEvent InnerDeserializeEventFromXml(this WechatOpenAIClient client, string webhookXml) where TEvent : WechatOpenAIEvent { - if (client == null) throw new ArgumentNullException(nameof(client)); - if (callbackXml == null) throw new ArgumentNullException(callbackXml); + if (client is null) throw new ArgumentNullException(nameof(client)); + if (webhookXml is null) throw new ArgumentNullException(webhookXml); try { - if (!Utilities.WxMsgCryptor.TryParseXml(callbackXml, out string? encryptedXml)) - throw new Exceptions.WechatOpenAIEventSerializationException("Failed to encrypt event data, because of empty encrypted data."); + if (!Utilities.WxMsgCryptor.TryParseXml(webhookXml, out string? encryptedXml)) + throw new WechatOpenAIException("Failed to decrypt event data, because of the encrypted data is empty."); - callbackXml = Utilities.WxMsgCryptor.AESDecrypt(cipherText: encryptedXml!, encodingAESKey: client.Credentials.EncodingAESKey!, out _); - return Utilities.XmlUtility.Deserialize(callbackXml); + webhookXml = Utilities.WxMsgCryptor.AESDecrypt(cipherText: encryptedXml!, encodingAESKey: client.Credentials.EncodingAESKey!, out _); + return Utilities.XmlHelper.Deserialize(webhookXml); } catch (WechatOpenAIException) { @@ -27,7 +27,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI } catch (Exception ex) { - throw new Exceptions.WechatOpenAIEventSerializationException("Failed to deserialize event data. Please see the inner exception for more details.", ex); + throw new WechatOpenAIException("Failed to deserialize event data. Please see the inner exception for more details.", ex); } } @@ -36,23 +36,23 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI /// /// /// - /// + /// /// - public static TEvent DeserializeEventFromXml(this WechatOpenAIClient client, string callbackXml) - where TEvent : WechatOpenAIEvent, WechatOpenAIEvent.Serialization.IXmlSerializable, new() + public static TEvent DeserializeEventFromXml(this WechatOpenAIClient client, string webhookXml) + where TEvent : WechatOpenAIEvent, new() { - return InnerDeserializeEventFromXml(client, callbackXml); + return InnerDeserializeEventFromXml(client, webhookXml); } /// /// 从 XML 反序列化得到 对象。 /// /// - /// + /// /// - public static WechatOpenAIEvent DeserializeEventFromXml(this WechatOpenAIClient client, string callbackXml) + public static WechatOpenAIEvent DeserializeEventFromXml(this WechatOpenAIClient client, string webhookXml) { - return InnerDeserializeEventFromXml(client, callbackXml); + return InnerDeserializeEventFromXml(client, webhookXml); } /// @@ -60,26 +60,26 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI /// /// /// - /// + /// /// - public static string SerializeEventToXml(this WechatOpenAIClient client, TEvent callbackModel) - where TEvent : WechatOpenAIEvent, WechatOpenAIEvent.Serialization.IXmlSerializable, new() + public static string SerializeEventToXml(this WechatOpenAIClient client, TEvent webhookEvent) + where TEvent : WechatOpenAIEvent, new() { string xml; try { - xml = Utilities.XmlUtility.Serialize(callbackModel); + xml = Utilities.XmlHelper.Serialize(webhookEvent); } catch (Exception ex) { - throw new Exceptions.WechatOpenAIEventSerializationException("Failed to serialize event data. Please see the inner exception for more details.", ex); + throw new WechatOpenAIException("Failed to serialize event data. Please see the inner exception for more details.", ex); } if (string.IsNullOrEmpty(client.Credentials.EncodingAESKey)) - throw new Exceptions.WechatOpenAIEventSerializationException("Failed to encrypt event data, because there is no encoding AES key."); + throw new WechatOpenAIException("Failed to encrypt event data, because the push encoding AES key is not set."); if (string.IsNullOrEmpty(client.Credentials.Token)) - throw new Exceptions.WechatOpenAIEventSerializationException("Failed to encrypt event data, because there is no token."); + throw new WechatOpenAIException("Failed to encrypt event data, because the push token is not set."); try { @@ -93,7 +93,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI } catch (Exception ex) { - throw new Exceptions.WechatOpenAIEventSerializationException("Failed to encrypt event data. Please see the inner exception for more details.", ex); + throw new WechatOpenAIException("Failed to encrypt event data. Please see the inner exception for more details.", ex); } return xml; diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteBotExtensions.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteBotExtensions.cs index 9be7d324..ccb984e2 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteBotExtensions.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteBotExtensions.cs @@ -22,9 +22,9 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI if (request is null) throw new ArgumentNullException(nameof(request)); IFlurlRequest flurlReq = client - .CreateRequest(request, HttpMethod.Post, "batchimportskill", client.Credentials.Token!); + .CreateFlurlRequest(request, HttpMethod.Post, "batchimportskill", client.Credentials.Token!); - return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); + return await client.SendFlurlRequestAsJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); } /// @@ -41,9 +41,9 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI if (request is null) throw new ArgumentNullException(nameof(request)); IFlurlRequest flurlReq = client - .CreateRequest(request, HttpMethod.Post, "publish", client.Credentials.Token!); + .CreateFlurlRequest(request, HttpMethod.Post, "publish", client.Credentials.Token!); - return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); + return await client.SendFlurlRequestAsJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); } /// @@ -60,9 +60,9 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI if (request is null) throw new ArgumentNullException(nameof(request)); IFlurlRequest flurlReq = client - .CreateRequest(request, HttpMethod.Post, "publish_progress", client.Credentials.Token!); + .CreateFlurlRequest(request, HttpMethod.Post, "publish_progress", client.Credentials.Token!); - return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); + return await client.SendFlurlRequestAsJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); } /// @@ -79,9 +79,9 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI if (request is null) throw new ArgumentNullException(nameof(request)); IFlurlRequest flurlReq = client - .CreateRequest(request, HttpMethod.Post, "setautoreply", client.Credentials.Token!); + .CreateFlurlRequest(request, HttpMethod.Post, "setautoreply", client.Credentials.Token!); - return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); + return await client.SendFlurlRequestAsJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); } /// @@ -98,9 +98,9 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI if (request is null) throw new ArgumentNullException(nameof(request)); IFlurlRequest flurlReq = client - .CreateRequest(request, HttpMethod.Post, "label", "batchset", client.Credentials.Token!); + .CreateFlurlRequest(request, HttpMethod.Post, "label", "batchset", client.Credentials.Token!); - return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); + return await client.SendFlurlRequestAsJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); } } } diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteDialogExtensions.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteDialogExtensions.cs index 1c675373..9a59b137 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteDialogExtensions.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteDialogExtensions.cs @@ -22,9 +22,9 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI if (request is null) throw new ArgumentNullException(nameof(request)); IFlurlRequest flurlReq = client - .CreateRequest(request, HttpMethod.Post, "sign", client.Credentials.Token!); + .CreateFlurlRequest(request, HttpMethod.Post, "sign", client.Credentials.Token!); - return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); + return await client.SendFlurlRequestAsJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); } /// @@ -41,9 +41,9 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI if (request is null) throw new ArgumentNullException(nameof(request)); IFlurlRequest flurlReq = client - .CreateRequest(request, HttpMethod.Post, "aibot", client.Credentials.Token!); + .CreateFlurlRequest(request, HttpMethod.Post, "aibot", client.Credentials.Token!); - return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); + return await client.SendFlurlRequestAsJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); } /// @@ -60,9 +60,9 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI if (request is null) throw new ArgumentNullException(nameof(request)); IFlurlRequest flurlReq = client - .CreateRequest(request, HttpMethod.Post, "feedback", client.Credentials.Token!); + .CreateFlurlRequest(request, HttpMethod.Post, "feedback", client.Credentials.Token!); - return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); + return await client.SendFlurlRequestAsJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); } /// @@ -79,9 +79,9 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI if (request is null) throw new ArgumentNullException(nameof(request)); IFlurlRequest flurlReq = client - .CreateRequest(request, HttpMethod.Post, "gethotquerylist", client.Credentials.Token!); + .CreateFlurlRequest(request, HttpMethod.Post, "gethotquerylist", client.Credentials.Token!); - return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); + return await client.SendFlurlRequestAsJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); } /// @@ -98,9 +98,9 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI if (request is null) throw new ArgumentNullException(nameof(request)); IFlurlRequest flurlReq = client - .CreateRequest(request, HttpMethod.Post, "gethotquerydetail", client.Credentials.Token!); + .CreateFlurlRequest(request, HttpMethod.Post, "gethotquerydetail", client.Credentials.Token!); - return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); + return await client.SendFlurlRequestAsJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); } } } diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteMpExtensions.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteMpExtensions.cs index 7c1a83d9..f7a1c587 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteMpExtensions.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteMpExtensions.cs @@ -25,9 +25,9 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI if (request is null) throw new ArgumentNullException(nameof(request)); IFlurlRequest flurlReq = client - .CreateRequest(request, HttpMethod.Post, "getbindlink", client.Credentials.Token!); + .CreateFlurlRequest(request, HttpMethod.Post, "getbindlink", client.Credentials.Token!); - return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); + return await client.SendFlurlRequestAsJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); } /// @@ -44,9 +44,9 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI if (request is null) throw new ArgumentNullException(nameof(request)); IFlurlRequest flurlReq = client - .CreateRequest(request, HttpMethod.Post, "getbindlist", client.Credentials.Token!); + .CreateFlurlRequest(request, HttpMethod.Post, "getbindlist", client.Credentials.Token!); - return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); + return await client.SendFlurlRequestAsJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); } /// @@ -63,9 +63,9 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI if (request is null) throw new ArgumentNullException(nameof(request)); IFlurlRequest flurlReq = client - .CreateRequest(request, HttpMethod.Post, "unbindmp", client.Credentials.Token!); + .CreateFlurlRequest(request, HttpMethod.Post, "unbindmp", client.Credentials.Token!); - return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); + return await client.SendFlurlRequestAsJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); } /// @@ -82,9 +82,9 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI if (request is null) throw new ArgumentNullException(nameof(request)); IFlurlRequest flurlReq = client - .CreateRequest(request, HttpMethod.Post, "geth5link", client.Credentials.Token!); + .CreateFlurlRequest(request, HttpMethod.Post, "geth5link", client.Credentials.Token!); - return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); + return await client.SendFlurlRequestAsJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); } /// @@ -100,19 +100,19 @@ 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.FileName == null) + if (request.FileName is null) request.FileName = Guid.NewGuid().ToString("N").ToLower() + ".jpg"; - if (request.FileContentType == null) + if (request.FileContentType is null) request.FileContentType = "image/jpeg"; IFlurlRequest flurlReq = client - .CreateRequest(request, HttpMethod.Post, "assetsupload", client.Credentials.Token!); + .CreateFlurlRequest(request, HttpMethod.Post, "assetsupload", client.Credentials.Token!); using var fileContent = new ByteArrayContent(request.FileBytes ?? Array.Empty()); using var paramContent = new StringContent( Utilities.WxMsgCryptor.AESEncrypt( - plainText: Utilities.XmlUtility.ConvertFromJson(client.JsonSerializer.Serialize(request)), + plainText: Utilities.XmlHelper.ConvertFromJson(client.JsonSerializer.Serialize(request)), encodingAESKey: client.Credentials.EncodingAESKey!, appId: client.Credentials.AppId! ), @@ -124,7 +124,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse(request.FileContentType); fileContent.Headers.ContentLength = request.FileBytes?.Length; - return await client.SendRequestAsync(flurlReq, httpContent: httpContent, cancellationToken: cancellationToken); + return await client.SendFlurlRequestAsync(flurlReq, httpContent: httpContent, cancellationToken: cancellationToken); } } } diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteThirdKefuExtensions.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteThirdKefuExtensions.cs index 213f4bfe..879d6c00 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteThirdKefuExtensions.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteThirdKefuExtensions.cs @@ -21,13 +21,13 @@ 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) + if (request.AppId is null) request.AppId = client.Credentials.AppId; IFlurlRequest flurlReq = client - .CreateRequest(request, HttpMethod.Post, "sendmsg", client.Credentials.Token!); + .CreateFlurlRequest(request, HttpMethod.Post, "sendmsg", client.Credentials.Token!); - return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); + return await client.SendFlurlRequestAsJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); } /// @@ -43,13 +43,13 @@ 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) + if (request.AppId is null) request.AppId = client.Credentials.AppId; IFlurlRequest flurlReq = client - .CreateRequest(request, HttpMethod.Post, "kefustate", "get", client.Credentials.Token!); + .CreateFlurlRequest(request, HttpMethod.Post, "kefustate", "get", client.Credentials.Token!); - return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); + return await client.SendFlurlRequestAsJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); } /// @@ -65,13 +65,13 @@ 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) + if (request.AppId is null) request.AppId = client.Credentials.AppId; IFlurlRequest flurlReq = client - .CreateRequest(request, HttpMethod.Post, "kefustate", "change", client.Credentials.Token!); + .CreateFlurlRequest(request, HttpMethod.Post, "kefustate", "change", client.Credentials.Token!); - return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); + return await client.SendFlurlRequestAsJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); } } } diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/Dialog/AIBotResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/Dialog/AIBotResponse.cs index 916773f1..3d042ea5 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/Dialog/AIBotResponse.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/Dialog/AIBotResponse.cs @@ -55,7 +55,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models /// [Newtonsoft.Json.JsonProperty("confidence")] [System.Text.Json.Serialization.JsonPropertyName("confidence")] - public float Confidence { get; set; } = default!; + public decimal Confidence { get; set; } = default!; /// /// 获取或设置消息类型。 @@ -156,7 +156,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models /// [Newtonsoft.Json.JsonProperty("confidence")] [System.Text.Json.Serialization.JsonPropertyName("confidence")] - public double Confidence { get; set; } + public decimal Confidence { get; set; } } public class Slot @@ -274,7 +274,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models /// [Newtonsoft.Json.JsonProperty("confidence")] [System.Text.Json.Serialization.JsonPropertyName("confidence")] - public double Confidence { get; set; } + public decimal Confidence { get; set; } /// /// 获取或设置发起查询的用户 ID。 diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/Dialog/GetHotQueryDetailResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/Dialog/GetHotQueryDetailResponse.cs index f99a6c13..c7ecd5ce 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/Dialog/GetHotQueryDetailResponse.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/Dialog/GetHotQueryDetailResponse.cs @@ -46,7 +46,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models /// [Newtonsoft.Json.JsonProperty("score")] [System.Text.Json.Serialization.JsonPropertyName("score")] - public double Score { get; set; } + public decimal Score { get; set; } } } diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/Dialog/GetHotQueryListResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/Dialog/GetHotQueryListResponse.cs index d7420f07..20f29d6b 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/Dialog/GetHotQueryListResponse.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/Dialog/GetHotQueryListResponse.cs @@ -29,7 +29,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models /// [Newtonsoft.Json.JsonProperty("score")] [System.Text.Json.Serialization.JsonPropertyName("score")] - public double Score { get; set; } + public decimal Score { get; set; } } } diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/Mp/GetBindListResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/Mp/GetBindListResponse.cs index 8f07733c..702aa629 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/Mp/GetBindListResponse.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/Mp/GetBindListResponse.cs @@ -46,45 +46,45 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models /// 获取或设置是否开通微信门店功能。 /// [Newtonsoft.Json.JsonProperty("open_store")] - [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.NumericalBooleanConverter))] + [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.Common.NumericalBooleanConverter))] [System.Text.Json.Serialization.JsonPropertyName("open_store")] - [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.NumericalBooleanConverter))] + [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.Common.NumericalBooleanConverter))] public bool IsOpenStore { get; set; } /// /// 获取或设置是否开通微信扫商品功能。 /// [Newtonsoft.Json.JsonProperty("open_scan")] - [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.NumericalBooleanConverter))] + [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.Common.NumericalBooleanConverter))] [System.Text.Json.Serialization.JsonPropertyName("open_scan")] - [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.NumericalBooleanConverter))] + [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.Common.NumericalBooleanConverter))] public bool IsOpenScan { get; set; } /// /// 获取或设置是否开通微信支付功能。 /// [Newtonsoft.Json.JsonProperty("open_pay")] - [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.NumericalBooleanConverter))] + [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.Common.NumericalBooleanConverter))] [System.Text.Json.Serialization.JsonPropertyName("open_pay")] - [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.NumericalBooleanConverter))] + [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.Common.NumericalBooleanConverter))] public bool IsOpenPay { get; set; } /// /// 获取或设置是否开通微信卡券功能。 /// [Newtonsoft.Json.JsonProperty("open_card")] - [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.NumericalBooleanConverter))] + [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.Common.NumericalBooleanConverter))] [System.Text.Json.Serialization.JsonPropertyName("open_card")] - [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.NumericalBooleanConverter))] + [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.Common.NumericalBooleanConverter))] public bool IsOpenCard { get; set; } /// /// 获取或设置是否开通微信摇一摇功能。 /// [Newtonsoft.Json.JsonProperty("open_shake")] - [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.NumericalBooleanConverter))] + [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.Common.NumericalBooleanConverter))] [System.Text.Json.Serialization.JsonPropertyName("open_shake")] - [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.NumericalBooleanConverter))] + [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.Common.NumericalBooleanConverter))] public bool IsOpenShake { get; set; } } diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/SKIT.FlurlHttpClient.Wechat.OpenAI.csproj b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/SKIT.FlurlHttpClient.Wechat.OpenAI.csproj index 02b558ab..7443d07e 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/SKIT.FlurlHttpClient.Wechat.OpenAI.csproj +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/SKIT.FlurlHttpClient.Wechat.OpenAI.csproj @@ -2,7 +2,7 @@ net461; netstandard2.0; net6.0 - 8.0 + 10.0 enable true @@ -14,7 +14,7 @@ MIT https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat Flurl.Http Wechat Weixin MicroMessage WechatAI WechatOpenAI WexinAI WeixinOpenAI 微信 微信智能对话 微信对话开放平台 微信智能对话开放平台 智能对话平台 - 2.0.1 + 3.0.0-preview.1 基于 Flurl.Http 的微信对话开放平台(微信智能对话) API 客户端,支持智能对话接口、第三方客服接入、机器人配置、公众号/小程序/H5 绑定等功能。 Fu Diwei git @@ -40,7 +40,7 @@ - + diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Settings/Credentials.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Settings/Credentials.cs index a9578e4a..27d8e2af 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Settings/Credentials.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Settings/Credentials.cs @@ -21,7 +21,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Settings internal Credentials(WechatOpenAIClientOptions options) { - if (options == null) throw new ArgumentNullException(nameof(options)); + if (options is null) throw new ArgumentNullException(nameof(options)); AppId = options.AppId; Token = options.Token; diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Utilities/Internal/XmlUtility.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Utilities/Internal/XmlUtility.cs deleted file mode 100644 index 8b67022c..00000000 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Utilities/Internal/XmlUtility.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System; -using System.Collections; -using System.IO; -using System.Text; -using System.Text.RegularExpressions; -using System.Xml; -using System.Xml.Serialization; -using Newtonsoft.Json; - -namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Utilities -{ - internal static class XmlUtility - { - // REF: https://docs.microsoft.com/zh-cn/dotnet/api/system.xml.serialization.xmlserializer#dynamically-generated-assemblies - private static readonly Hashtable _xmlSerializers = new Hashtable(); - private static readonly XmlRootAttribute _xmlRoot = new XmlRootAttribute("xml"); - - private static XmlSerializer GetTypedSerializer(Type type) - { - if (type == null) throw new ArgumentNullException(nameof(type)); - - string skey = type.AssemblyQualifiedName ?? type.GetHashCode().ToString(); - XmlSerializer? xmlSerializer = (XmlSerializer?)_xmlSerializers[skey]; - if (xmlSerializer == null) - { - xmlSerializer = new XmlSerializer(type, _xmlRoot); - _xmlSerializers[skey] = xmlSerializer; - } - - return xmlSerializer; - } - - public static string Serialize(Type type, object obj) - { - string xml; - - var settings = new XmlWriterSettings(); - settings.Encoding = Encoding.UTF8; - settings.Indent = false; - settings.OmitXmlDeclaration = true; - settings.WriteEndDocumentOnClose = false; - settings.NamespaceHandling = NamespaceHandling.OmitDuplicates; - - using var stream = new MemoryStream(); - using var writer = XmlWriter.Create(stream, settings); - XmlSerializer serializer = GetTypedSerializer(type); - XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); - ns.Add(string.Empty, string.Empty); - serializer.Serialize(writer, obj, ns); - writer.Flush(); - xml = Encoding.UTF8.GetString(stream.ToArray()); - xml = Regex.Replace(xml, "\\s*<\\w+ ([a-zA-Z0-9]+):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); - } - - public static object Deserialize(Type type, string xml) - { - using var reader = new StringReader(xml); - XmlSerializer serializer = GetTypedSerializer(type); - return serializer.Deserialize(reader)!; - } - - public static T Deserialize(string xml) - where T : class - { - return (T)Deserialize(typeof(T), xml); - } - - public static string ConvertFromJson(string json) - { - XmlDocument xmlDocument = JsonConvert.DeserializeXmlNode(json, "xml")!; - string xml = xmlDocument.InnerXml; - return xml; - } - } -} diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Utilities/SHA1Utility.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Utilities/SHA1Utility.cs index e5d8dcbf..1071af0a 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Utilities/SHA1Utility.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Utilities/SHA1Utility.cs @@ -16,7 +16,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Utilities /// 信息摘要字节数组。 public static byte[] Hash(byte[] bytes) { - if (bytes == null) throw new ArgumentNullException(nameof(bytes)); + if (bytes is null) throw new ArgumentNullException(nameof(bytes)); using SHA1 sha = SHA1.Create(); return sha.ComputeHash(bytes); @@ -29,7 +29,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Utilities /// 信息摘要。 public static string Hash(string message) { - if (message == null) throw new ArgumentNullException(nameof(message)); + if (message is null) throw new ArgumentNullException(nameof(message)); byte[] msgBytes = Encoding.UTF8.GetBytes(message); byte[] hashBytes = Hash(msgBytes); diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Utilities/Internal/WxMsgCryptor.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Utilities/__Internal/WxMsgCryptor.cs similarity index 88% rename from src/SKIT.FlurlHttpClient.Wechat.OpenAI/Utilities/Internal/WxMsgCryptor.cs rename to src/SKIT.FlurlHttpClient.Wechat.OpenAI/Utilities/__Internal/WxMsgCryptor.cs index 6287e11b..3daa2249 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Utilities/Internal/WxMsgCryptor.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Utilities/__Internal/WxMsgCryptor.cs @@ -60,7 +60,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Utilities private static byte[] Decode2(byte[] decryptedBytes) { - if (decryptedBytes == null) throw new ArgumentNullException(nameof(decryptedBytes)); + if (decryptedBytes is null) throw new ArgumentNullException(nameof(decryptedBytes)); int pad = (int)decryptedBytes[decryptedBytes.Length - 1]; if (pad < 1 || pad > 32) @@ -75,9 +75,9 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Utilities private static byte[] AESDecrypt(byte[] keyBytes, byte[] ivBytes, byte[] ciperBytes) { - if (keyBytes == null) throw new ArgumentNullException(nameof(keyBytes)); - if (ivBytes == null) throw new ArgumentNullException(nameof(ivBytes)); - if (ciperBytes == null) throw new ArgumentNullException(nameof(ciperBytes)); + if (keyBytes is null) throw new ArgumentNullException(nameof(keyBytes)); + if (ivBytes is null) throw new ArgumentNullException(nameof(ivBytes)); + if (ciperBytes is null) throw new ArgumentNullException(nameof(ciperBytes)); using var aes = Aes.Create(); aes.KeySize = 256; @@ -103,9 +103,9 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Utilities private static string AESEncrypt(byte[] keyBytes, byte[] ivBytes, byte[] plainBytes) { - if (keyBytes == null) throw new ArgumentNullException(nameof(keyBytes)); - if (ivBytes == null) throw new ArgumentNullException(nameof(ivBytes)); - if (plainBytes == null) throw new ArgumentNullException(nameof(plainBytes)); + if (keyBytes is null) throw new ArgumentNullException(nameof(keyBytes)); + if (ivBytes is null) throw new ArgumentNullException(nameof(ivBytes)); + if (plainBytes is null) throw new ArgumentNullException(nameof(plainBytes)); using var aes = Aes.Create(); aes.KeySize = AES_KEY_SIZE; @@ -140,8 +140,8 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Utilities /// 解密后的文本内容。 public static string AESDecrypt(string cipherText, string encodingAESKey, out string appId) { - if (cipherText == null) throw new ArgumentNullException(nameof(cipherText)); - if (encodingAESKey == null) throw new ArgumentNullException(nameof(encodingAESKey)); + if (cipherText is null) throw new ArgumentNullException(nameof(cipherText)); + if (encodingAESKey is null) throw new ArgumentNullException(nameof(encodingAESKey)); byte[] cipherBytes = Convert.FromBase64String(cipherText); byte[] keyBytes = Convert.FromBase64String(encodingAESKey + "="); @@ -170,9 +170,9 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Utilities /// 加密后的文本内容。 public static string AESEncrypt(string plainText, string encodingAESKey, string appId) { - if (plainText == null) throw new ArgumentNullException(nameof(plainText)); - if (encodingAESKey == null) throw new ArgumentNullException(nameof(encodingAESKey)); - if (appId == null) throw new ArgumentNullException(nameof(appId)); + if (plainText is null) throw new ArgumentNullException(nameof(plainText)); + if (encodingAESKey is null) throw new ArgumentNullException(nameof(encodingAESKey)); + if (appId is null) throw new ArgumentNullException(nameof(appId)); byte[] keyBytes = Convert.FromBase64String(encodingAESKey + "="); byte[] ivBytes = new byte[16]; @@ -204,11 +204,11 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Utilities /// 验证结果。 public static bool VerifySignature(string sToken, string sTimestamp, string sNonce, string sMsgEncrypt, string sMsgSign) { - if (sToken == null) throw new ArgumentNullException(nameof(sToken)); - if (sTimestamp == null) throw new ArgumentNullException(nameof(sTimestamp)); - if (sNonce == null) throw new ArgumentNullException(nameof(sNonce)); - if (sMsgEncrypt == null) throw new ArgumentNullException(nameof(sMsgEncrypt)); - if (sMsgSign == null) throw new ArgumentNullException(nameof(sMsgSign)); + if (sToken is null) throw new ArgumentNullException(nameof(sToken)); + if (sTimestamp is null) throw new ArgumentNullException(nameof(sTimestamp)); + if (sNonce is null) throw new ArgumentNullException(nameof(sNonce)); + if (sMsgEncrypt is null) throw new ArgumentNullException(nameof(sMsgEncrypt)); + if (sMsgSign is null) throw new ArgumentNullException(nameof(sMsgSign)); string expectedSign = GenerateSignature(sToken, sTimestamp, sNonce, sMsgEncrypt); return string.Equals(expectedSign, sMsgSign, StringComparison.OrdinalIgnoreCase); @@ -224,10 +224,10 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Utilities /// 签名。 public static string GenerateSignature(string sToken, string sTimestamp, string sNonce, string sMsgEncrypt) { - if (sToken == null) throw new ArgumentNullException(nameof(sToken)); - if (sTimestamp == null) throw new ArgumentNullException(nameof(sTimestamp)); - if (sNonce == null) throw new ArgumentNullException(nameof(sNonce)); - if (sMsgEncrypt == null) throw new ArgumentNullException(nameof(sMsgEncrypt)); + if (sToken is null) throw new ArgumentNullException(nameof(sToken)); + if (sTimestamp is null) throw new ArgumentNullException(nameof(sTimestamp)); + if (sNonce is null) throw new ArgumentNullException(nameof(sNonce)); + if (sMsgEncrypt is null) throw new ArgumentNullException(nameof(sMsgEncrypt)); List tmp = new List(capacity: 4) { sToken, sTimestamp, sNonce, sMsgEncrypt }; tmp.Sort(StringComparer.Ordinal); @@ -257,7 +257,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Utilities /// 指示是否是有效的 XML 内容。 public static bool TryParseXml(string xml, out string? encryptedMsg, out string? toUserName) { - if (xml == null) throw new ArgumentNullException(nameof(xml)); + if (xml is null) throw new ArgumentNullException(nameof(xml)); encryptedMsg = null; toUserName = null; @@ -269,7 +269,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Utilities xmlDoc.LoadXml(xml); XmlNode? xmlRoot = xmlDoc.FirstChild; - if (xmlRoot == null) + if (xmlRoot is null) return false; encryptedMsg = xmlRoot["Encrypt"]?.InnerText?.ToString(); @@ -291,8 +291,8 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Utilities /// public static string WrapXml(string sToken, string sMsgEncrypt) { - if (sToken == null) throw new ArgumentNullException(nameof(sToken)); - if (sMsgEncrypt == null) throw new ArgumentNullException(nameof(sMsgEncrypt)); + if (sToken is null) throw new ArgumentNullException(nameof(sToken)); + if (sMsgEncrypt is null) throw new ArgumentNullException(nameof(sMsgEncrypt)); string sTimestamp = DateTimeOffset.Now.ToLocalTime().ToUnixTimeSeconds().ToString(); string sNonce = DateTimeOffset.Now.Ticks.ToString("x"); @@ -310,10 +310,10 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Utilities /// public static string WrapXml(string sTimestamp, string sNonce, string sMsgEncrypt, string sMsgSign) { - if (sTimestamp == null) throw new ArgumentNullException(nameof(sTimestamp)); - if (sNonce == null) throw new ArgumentNullException(nameof(sNonce)); - if (sMsgEncrypt == null) throw new ArgumentNullException(nameof(sMsgEncrypt)); - if (sMsgSign == null) throw new ArgumentNullException(nameof(sMsgSign)); + if (sTimestamp is null) throw new ArgumentNullException(nameof(sTimestamp)); + if (sNonce is null) throw new ArgumentNullException(nameof(sNonce)); + if (sMsgEncrypt is null) throw new ArgumentNullException(nameof(sMsgEncrypt)); + if (sMsgSign is null) throw new ArgumentNullException(nameof(sMsgSign)); StringBuilder builder = new StringBuilder(); builder.AppendFormat(""); diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Utilities/__Internal/XmlHelper.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Utilities/__Internal/XmlHelper.cs new file mode 100644 index 00000000..4e882df6 --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Utilities/__Internal/XmlHelper.cs @@ -0,0 +1,40 @@ +using System; +using System.Xml; +using Newtonsoft.Json; + +namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Utilities +{ + using SKIT.FlurlHttpClient.Internal; + + internal static class XmlHelper + { + public static string Serialize(object obj, Type type) + { + return _XmlSimpleSerializer.Serialize(obj, type); + } + + public static string Serialize(T obj) + where T : class + { + return Serialize(obj, typeof(T)); + } + + public static object Deserialize(string xml, Type type) + { + return _XmlSimpleSerializer.Deserialize(xml, type); + } + + public static T Deserialize(string xml) + where T : class + { + return (T)Deserialize(xml, typeof(T)); + } + + public static string ConvertFromJson(string json) + { + XmlDocument xmlDocument = JsonConvert.DeserializeXmlNode(json, "xml")!; + string xml = xmlDocument.InnerXml; + return xml; + } + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIClient.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIClient.cs index b341a84b..6c610450 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIClient.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIClient.cs @@ -21,42 +21,37 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI /// /// 配置项。 public WechatOpenAIClient(WechatOpenAIClientOptions options) - : base() + : this(options, null) { - if (options == null) throw new ArgumentNullException(nameof(options)); + } + + /// + /// + /// + /// + /// + /// + internal protected WechatOpenAIClient(WechatOpenAIClientOptions options, HttpClient? httpClient, bool disposeClient = true) + : base(httpClient, disposeClient) + { + if (options is null) throw new ArgumentNullException(nameof(options)); Credentials = new Settings.Credentials(options); FlurlClient.BaseUrl = options.Endpoint ?? WechatOpenAIEndpoints.DEFAULT; - FlurlClient.WithTimeout(TimeSpan.FromMilliseconds(options.Timeout)); - } - - /// - /// 用指定的微信智能对话 AppId、Token、EncodingAESKey 初始化 类的新实例。 - /// - /// 微信智能对话 AppId。 - /// 微信智能对话 Token。 - /// 微信智能对话 EncodingAESKey。 - public WechatOpenAIClient(string appId, string token, string encodingAESKey) - : this(new WechatOpenAIClientOptions() { AppId = appId, Token = token, EncodingAESKey = encodingAESKey }) - { + FlurlClient.WithTimeout(options.Timeout <= 0 ? Timeout.InfiniteTimeSpan : TimeSpan.FromMilliseconds(options.Timeout)); } /// /// 使用当前客户端生成一个新的 对象。 /// /// - /// + /// /// /// - public IFlurlRequest CreateRequest(WechatOpenAIRequest request, HttpMethod method, params object[] urlSegments) + public IFlurlRequest CreateFlurlRequest(WechatOpenAIRequest request, HttpMethod httpMethod, params object[] urlSegments) { - IFlurlRequest flurlRequest = FlurlClient.Request(urlSegments).WithVerb(method); - - if (request.Timeout != null) - { - flurlRequest.WithTimeout(TimeSpan.FromMilliseconds(request.Timeout.Value)); - } + IFlurlRequest flurlRequest = base.CreateFlurlRequest(request, httpMethod, urlSegments); return flurlRequest; } @@ -69,20 +64,13 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI /// /// /// - public async Task SendRequestAsync(IFlurlRequest flurlRequest, HttpContent? httpContent = null, CancellationToken cancellationToken = default) + public async Task SendFlurlRequestAsync(IFlurlRequest flurlRequest, HttpContent? httpContent = null, CancellationToken cancellationToken = default) where T : WechatOpenAIResponse, new() { - if (flurlRequest == null) throw new ArgumentNullException(nameof(flurlRequest)); + if (flurlRequest is null) throw new ArgumentNullException(nameof(flurlRequest)); - try - { - using IFlurlResponse flurlResponse = await base.SendRequestAsync(flurlRequest, httpContent, cancellationToken); - return await WrapResponseWithJsonAsync(flurlResponse, cancellationToken); - } - catch (FlurlHttpException ex) - { - throw new WechatOpenAIException(ex.Message, ex); - } + using IFlurlResponse flurlResponse = await base.SendFlurlRequestAsync(flurlRequest, httpContent, cancellationToken); + return await WrapFlurlResponseAsJsonAsync(flurlResponse, cancellationToken); } /// @@ -93,37 +81,26 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI /// /// /// - public async Task SendRequestWithJsonAsync(IFlurlRequest flurlRequest, object? data = null, CancellationToken cancellationToken = default) + public async Task SendFlurlRequestAsJsonAsync(IFlurlRequest flurlRequest, object? data = null, CancellationToken cancellationToken = default) where T : WechatOpenAIResponse, new() { - if (flurlRequest == null) throw new ArgumentNullException(nameof(flurlRequest)); + if (flurlRequest is null) throw new ArgumentNullException(nameof(flurlRequest)); - try + if (data is WechatOpenAIRequest.Serialization.IEncryptedXmlable) { - if (data is WechatOpenAIRequest.Serialization.IEncryptedXmlable) - { - string plainXml = Utilities.XmlUtility.ConvertFromJson(JsonSerializer.Serialize(data)); - string encryptedXml = Utilities.WxMsgCryptor.AESEncrypt(plainText: plainXml, encodingAESKey: Credentials.EncodingAESKey!, appId: Credentials.AppId!); - data = new { encrypt = encryptedXml }; - } + string plainXml = Utilities.XmlHelper.ConvertFromJson(JsonSerializer.Serialize(data)); + string encryptedXml = Utilities.WxMsgCryptor.AESEncrypt(plainText: plainXml, encodingAESKey: Credentials.EncodingAESKey!, appId: Credentials.AppId!); + data = new { encrypt = encryptedXml }; + } - bool isSimpleRequest = data == null || - flurlRequest.Verb == HttpMethod.Get || - flurlRequest.Verb == HttpMethod.Head || - flurlRequest.Verb == HttpMethod.Options; - using IFlurlResponse flurlResponse = isSimpleRequest ? - await base.SendRequestAsync(flurlRequest, null, cancellationToken) : - await base.SendRequestWithJsonAsync(flurlRequest, data, cancellationToken); - return await WrapResponseWithJsonAsync(flurlResponse, cancellationToken); - } - catch (FlurlHttpTimeoutException ex) - { - throw new Exceptions.WechatOpenAIRequestTimeoutException(ex.Message, ex); - } - catch (FlurlHttpException ex) - { - throw new WechatOpenAIException(ex.Message, ex); - } + bool isSimpleRequest = data is null || + flurlRequest.Verb == HttpMethod.Get || + flurlRequest.Verb == HttpMethod.Head || + flurlRequest.Verb == HttpMethod.Options; + using IFlurlResponse flurlResponse = isSimpleRequest ? + await base.SendFlurlRequestAsync(flurlRequest, null, cancellationToken) : + await base.SendFlurlRequestAsJsonAsync(flurlRequest, data, cancellationToken); + return await WrapFlurlResponseAsJsonAsync(flurlResponse, cancellationToken); } } } diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIEvent.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIEvent.cs index 37fee6f0..bd66cbf5 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIEvent.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIEvent.cs @@ -1,38 +1,27 @@ -using System; -using System.Xml.Serialization; - namespace SKIT.FlurlHttpClient.Wechat.OpenAI { /// /// 表示微信智能对话 API 回调通知事件的基类。 /// - [Serializable] - public class WechatOpenAIEvent + [System.Xml.Serialization.XmlRoot("xml")] + public class WechatOpenAIEvent : ICommonWebhookEvent { - public static class Serialization - { - [XmlRoot("xml")] - public interface IXmlSerializable - { - } - } - /// /// 获取或设置 AppId。 /// - [XmlElement("appid", IsNullable = true)] + [System.Xml.Serialization.XmlElement("appid", IsNullable = true)] public string? AppId { get; set; } /// /// 获取或设置事件类型。 /// - [XmlElement("event", IsNullable = true)] + [System.Xml.Serialization.XmlElement("event", IsNullable = true)] public string? Event { get; set; } /// /// 获取或设置消息创建时间戳。 /// - [XmlElement("createtime", IsNullable = true)] + [System.Xml.Serialization.XmlElement("createtime", IsNullable = true)] public long? CreateTimestamp { get; set; } } } diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIException.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIException.cs index b914bb9d..58ce6382 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIException.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIException.cs @@ -1,11 +1,11 @@ -using System; +using System; namespace SKIT.FlurlHttpClient.Wechat.OpenAI { /// /// 当调用微信智能对话 API 出错时引发的异常。 /// - public class WechatOpenAIException : CommonExceptionBase + public class WechatOpenAIException : CommonException { /// public WechatOpenAIException() diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIRequest.cs index ed3342cb..0564272e 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIRequest.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIRequest.cs @@ -3,7 +3,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI /// /// 表示微信智能对话 API 请求的基类。 /// - public abstract class WechatOpenAIRequest : ICommonRequest + public abstract class WechatOpenAIRequest : CommonRequestBase, ICommonRequest { public static class Serialization { @@ -11,14 +11,5 @@ 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; } } } diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIResponse.cs index 80441585..98940077 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIResponse.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIResponse.cs @@ -1,60 +1,10 @@ -using System.Collections.Generic; - namespace SKIT.FlurlHttpClient.Wechat.OpenAI { /// /// 表示微信智能对话 API 响应的基类。 /// - public abstract class WechatOpenAIResponse : ICommonResponse + public abstract class WechatOpenAIResponse : CommonResponseBase, ICommonResponse { - /// - /// - /// - int ICommonResponse.RawStatus { get; set; } - - /// - /// - /// - IDictionary ICommonResponse.RawHeaders { get; set; } = default!; - - /// - /// - /// - byte[] ICommonResponse.RawBytes { get; set; } = default!; - - /// - /// 获取原始的 HTTP 响应状态码。 - /// - [Newtonsoft.Json.JsonIgnore] - [System.Text.Json.Serialization.JsonIgnore] - public int RawStatus - { - get { return ((ICommonResponse)this).RawStatus; } - internal set { ((ICommonResponse)this).RawStatus = value; } - } - - /// - /// 获取原始的 HTTP 响应表头集合。 - /// - [Newtonsoft.Json.JsonIgnore] - [System.Text.Json.Serialization.JsonIgnore] - public IDictionary RawHeaders - { - get { return ((ICommonResponse)this).RawHeaders; } - internal set { ((ICommonResponse)this).RawHeaders = value; } - } - - /// - /// 获取原始的 HTTP 响应正文。 - /// - [Newtonsoft.Json.JsonIgnore] - [System.Text.Json.Serialization.JsonIgnore] - public byte[] RawBytes - { - get { return ((ICommonResponse)this).RawBytes; } - internal set { ((ICommonResponse)this).RawBytes = value; } - } - /// /// 获取微信智能对话 API 返回的错误码。 /// @@ -84,12 +34,15 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI public virtual string? ReturnError { get; set; } /// - /// 获取一个值,该值指示调用微信 API 是否成功(即 HTTP 状态码为 200、且 errcode/ret 值都为 0)。 + /// 获取一个值,该值指示调用微信 API 是否成功。 + /// + /// (即 HTTP 状态码为 200,且 值都为 0) + /// /// /// - public virtual bool IsSuccessful() + public override bool IsSuccessful() { - return RawStatus == 200 && ErrorCode.GetValueOrDefault() == 0 && ReturnCode.GetValueOrDefault() == 0 && string.IsNullOrEmpty(ReturnError); + return GetRawStatus() == 200 && ErrorCode.GetValueOrDefault() == 0 && ReturnCode.GetValueOrDefault() == 0 && string.IsNullOrEmpty(ReturnError); } } diff --git a/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/IMPORTANT_CodeAnalyzeTests.cs b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/IMPORTANT_CodeAnalyzeTests.cs new file mode 100644 index 00000000..b7cc38d4 --- /dev/null +++ b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/IMPORTANT_CodeAnalyzeTests.cs @@ -0,0 +1,56 @@ +using System; +using System.IO; +using System.Reflection; +using SKIT.FlurlHttpClient.Tools.CodeAnalyzer; +using Xunit; + +namespace SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests +{ + public class CodeAnalyzeTests + { + [Fact(DisplayName = "代码质量分析")] + public void CodeAnalyze() + { + Assert.Null(Record.Exception(() => + { + var options = new TypeDeclarationAnalyzerOptions() + { + SdkAssembly = Assembly.GetAssembly(typeof(WechatOpenAIClient))!, + SdkRequestModelDeclarationNamespace = "SKIT.FlurlHttpClient.Wechat.OpenAI.Models", + SdkResponseModelDeclarationNamespace = "SKIT.FlurlHttpClient.Wechat.OpenAI.Models", + SdkExecutingExtensionDeclarationNamespace = "SKIT.FlurlHttpClient.Wechat.OpenAI", + SdkWebhookEventDeclarationNamespace = "SKIT.FlurlHttpClient.Wechat.OpenAI.Events", + ThrowOnNotFoundRequestModelTypes = true, + ThrowOnNotFoundResponseModelTypes = true, + ThrowOnNotFoundExecutingExtensionTypes = true, + ThrowOnNotFoundWebhookEventTypes = true + }; + new TypeDeclarationAnalyzer(options).AssertNoIssues(); + })); + + Assert.Null(Record.Exception(() => + { + string workdir = Environment.CurrentDirectory; + string projdir = Path.Combine(workdir, "../../../../../"); + + var options = new SourceFileAnalyzerOptions() + { + SdkAssembly = Assembly.GetAssembly(typeof(WechatOpenAIClient))!, + SdkRequestModelDeclarationNamespace = "SKIT.FlurlHttpClient.Wechat.OpenAI.Models", + SdkResponseModelDeclarationNamespace = "SKIT.FlurlHttpClient.Wechat.OpenAI.Models", + SdkWebhookEventDeclarationNamespace = "SKIT.FlurlHttpClient.Wechat.OpenAI.Events", + ProjectSourceRootDirectory = Path.Combine(projdir, "./src/SKIT.FlurlHttpClient.Wechat.OpenAI/"), + ProjectTestRootDirectory = Path.Combine(projdir, "./test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/"), + ThrowOnNotFoundRequestModelClassCodeFiles = true, + ThrowOnNotFoundResponseModelClassCodeFiles = true, + ThrowOnNotFoundExecutingExtensionClassCodeFiles = true, + ThrowOnNotFoundWebhookEventClassCodeFiles = true, + ThrowOnNotFoundRequestModelSerializationSampleFiles = true, + ThrowOnNotFoundResponseModelSerializationSampleFiles = true, + ThrowOnNotFoundWebhookEventSerializationSampleFiles = true + }; + new SourceFileAnalyzer(options).AssertNoIssues(); + })); + } + } +} 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 30f87576..7d19f9ca 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 @@ -10,23 +10,23 @@ - - Never - Never - - - PreserveNewest - PreserveNewest - + + PreserveNewest + PreserveNewest + + + Always + Always + - - - - + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/TestCase_CodeReview.cs b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/TestCase_CodeReview.cs deleted file mode 100644 index dacdbaf6..00000000 --- a/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/TestCase_CodeReview.cs +++ /dev/null @@ -1,28 +0,0 @@ -using SKIT.FlurlHttpClient.Tools.CodeAnalyzer; -using Xunit; - -namespace SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests -{ - public class TestCase_CodeReview - { - [Fact(DisplayName = "测试用例:代码质量分析")] - public void TestCodeAnalyzer() - { - Assert.Null(Record.Exception(() => - { - CodeAnalyzerOptions options = new CodeAnalyzerOptions() - { - AssemblyName = "SKIT.FlurlHttpClient.Wechat.OpenAI", - WorkDirectoryForSourceCode = TestConfigs.WorkDirectoryForSdk, - WorkDirectoryForTestSample = TestConfigs.WorkDirectoryForTest, - AllowNotFoundEventTypes = true, - AllowNotFoundEventSamples = true - }; - CodeAnalyzer analyzer = new CodeAnalyzer(options); - analyzer.Start(); - analyzer.Assert(); - analyzer.Flush(); - })); - } - } -} diff --git a/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/TestConfigs.cs b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/TestConfigs.cs index d76f743c..38a7d407 100644 --- a/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/TestConfigs.cs +++ b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/TestConfigs.cs @@ -17,14 +17,11 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests using var stream = File.OpenRead("appsettings.local.json"); using var jdoc = JsonDocument.Parse(stream); - var config = jdoc.RootElement.GetProperty("TestConfig"); + var config = jdoc.RootElement.GetProperty("TestConfigs"); WechatAppId = config.GetProperty("AppId").GetString()!; WechatToken = config.GetProperty("Token").GetString()!; WechatEncodingAESKey = config.GetProperty("EncodingAESKey").GetString()!; WechatAccessToken = config.GetProperty("AccessToken").GetString()!; - - WorkDirectoryForSdk = jdoc.RootElement.GetProperty("WorkDirectoryForSdk").GetString()!; - WorkDirectoryForTest = jdoc.RootElement.GetProperty("WorkDirectoryForTest").GetString()!; } catch (Exception ex) { @@ -36,8 +33,5 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests public static readonly string WechatToken; public static readonly string WechatEncodingAESKey; public static readonly string WechatAccessToken; - - public static readonly string WorkDirectoryForSdk; - public static readonly string WorkDirectoryForTest; } } diff --git a/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/appsettings.json b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/appsettings.json index 74552efd..d8543ba0 100644 --- a/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/appsettings.json +++ b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/appsettings.json @@ -1,10 +1,8 @@ { - "TestConfig": { + "TestConfigs": { "AppId": "请在此填写用于测试的微信智能对话 AppId", "Token": "请在此填写用于测试的微信智能对话 Token", "EncodingAESKey": "请在此填写用于测试的微信智能对话 EncodingAESKey", "AccessToken": "请在此填写用于测试的微信智能对话 AccessToken" - }, - "WorkDirectoryForSdk": "请输入当前 SDK 项目所在的目录完整路径,如 C:\\Project\\src\\SKIT.FlurlHttpClient.Wechat.OpenAI\\", - "WorkDirectoryForTest": "请输入当前测试项目所在的目录完整路径,如 C:\\Project\\test\\SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests\\" + } }