diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/AssemblyInfo.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/AssemblyInfo.cs new file mode 100644 index 00000000..813c0f46 --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests")] \ No newline at end of file diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientEventExtensions.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientEventExtensions.cs index b0cb77ed..3ceab8c0 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientEventExtensions.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientEventExtensions.cs @@ -43,7 +43,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI if (!Utilities.WxBizMsgCryptor.TryParseXml(callbackXml, out string? encryptedXml)) throw new Exceptions.WechatOpenAIEventSerializationException("Encrypt event failed, because of empty encrypted data."); - callbackXml = Utilities.WxBizMsgCryptor.AESDecrypt(cipherText: encryptedXml!, encodingAESKey: client.Credentials.PushEncodingAESKey!, out _); + callbackXml = Utilities.WxBizMsgCryptor.AESDecrypt(cipherText: encryptedXml!, encodingAESKey: client.Credentials.EncodingAESKey!, out _); using var reader = new StringReader(callbackXml); @@ -106,20 +106,20 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI } - if (string.IsNullOrEmpty(client.Credentials.PushEncodingAESKey)) + if (string.IsNullOrEmpty(client.Credentials.EncodingAESKey)) throw new Exceptions.WechatOpenAIEventSerializationException("Encrypt event failed, because there is no encoding AES key."); - if (string.IsNullOrEmpty(client.Credentials.PushToken)) + if (string.IsNullOrEmpty(client.Credentials.Token)) throw new Exceptions.WechatOpenAIEventSerializationException("Encrypt event failed, because there is no token."); try { string cipher = Utilities.WxBizMsgCryptor.AESEncrypt( plainText: xml, - encodingAESKey: client.Credentials.PushEncodingAESKey!, + encodingAESKey: client.Credentials.EncodingAESKey!, appId: client.Credentials.AppId! ); - xml = Utilities.WxBizMsgCryptor.WrapXml(sToken: client.Credentials.PushToken!, sMsgEncrypt: cipher); + xml = Utilities.WxBizMsgCryptor.WrapXml(sToken: client.Credentials.Token!, sMsgEncrypt: cipher); } catch (Exception ex) { diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteOpenApiBotExtensions.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteOpenApiBotExtensions.cs index d4d765fc..088d4505 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteOpenApiBotExtensions.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteOpenApiBotExtensions.cs @@ -22,7 +22,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI if (request is null) throw new ArgumentNullException(nameof(request)); IFlurlRequest flurlReq = client - .CreateRequest(request, HttpMethod.Post, "openapi", "batchimportskill", client.Credentials.PushToken!); + .CreateRequest(request, HttpMethod.Post, "openapi", "batchimportskill", client.Credentials.Token!); return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); } @@ -41,7 +41,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI if (request is null) throw new ArgumentNullException(nameof(request)); IFlurlRequest flurlReq = client - .CreateRequest(request, HttpMethod.Post, "openapi", "publish", client.Credentials.PushToken!); + .CreateRequest(request, HttpMethod.Post, "openapi", "publish", client.Credentials.Token!); return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); } @@ -60,7 +60,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI if (request is null) throw new ArgumentNullException(nameof(request)); IFlurlRequest flurlReq = client - .CreateRequest(request, HttpMethod.Post, "openapi", "publish_progress", client.Credentials.PushToken!); + .CreateRequest(request, HttpMethod.Post, "openapi", "publish_progress", client.Credentials.Token!); return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); } @@ -80,7 +80,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI if (request is null) throw new ArgumentNullException(nameof(request)); IFlurlRequest flurlReq = client - .CreateRequest(request, HttpMethod.Post, "openapi", "setautoreply", client.Credentials.PushToken!); + .CreateRequest(request, HttpMethod.Post, "openapi", "setautoreply", client.Credentials.Token!); return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); } @@ -99,7 +99,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI if (request is null) throw new ArgumentNullException(nameof(request)); IFlurlRequest flurlReq = client - .CreateRequest(request, HttpMethod.Post, "openapi", "label", "batchset", client.Credentials.PushToken!); + .CreateRequest(request, HttpMethod.Post, "openapi", "label", "batchset", client.Credentials.Token!); return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); } diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteOpenApiLivingExtensions.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteOpenApiLivingExtensions.cs index fbdd392b..71673692 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteOpenApiLivingExtensions.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteOpenApiLivingExtensions.cs @@ -22,7 +22,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI if (request is null) throw new ArgumentNullException(nameof(request)); IFlurlRequest flurlReq = client - .CreateRequest(request, HttpMethod.Post, "openapi", "batchreply", client.Credentials.PushToken!); + .CreateRequest(request, HttpMethod.Post, "openapi", "batchreply", client.Credentials.Token!); return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); } @@ -41,7 +41,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI if (request is null) throw new ArgumentNullException(nameof(request)); IFlurlRequest flurlReq = client - .CreateRequest(request, HttpMethod.Post, "openapi", "generatereport", client.Credentials.PushToken!); + .CreateRequest(request, HttpMethod.Post, "openapi", "generatereport", client.Credentials.Token!); return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); } diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteOpenApiMpExtensions.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteOpenApiMpExtensions.cs index 7d457155..40d499be 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteOpenApiMpExtensions.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteOpenApiMpExtensions.cs @@ -25,7 +25,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI if (request is null) throw new ArgumentNullException(nameof(request)); IFlurlRequest flurlReq = client - .CreateRequest(request, HttpMethod.Post, "openapi", "getbindlink", client.Credentials.PushToken!); + .CreateRequest(request, HttpMethod.Post, "openapi", "getbindlink", client.Credentials.Token!); return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); } @@ -44,7 +44,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI if (request is null) throw new ArgumentNullException(nameof(request)); IFlurlRequest flurlReq = client - .CreateRequest(request, HttpMethod.Post, "openapi", "getbindlist", client.Credentials.PushToken!); + .CreateRequest(request, HttpMethod.Post, "openapi", "getbindlist", client.Credentials.Token!); return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); } @@ -63,7 +63,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI if (request is null) throw new ArgumentNullException(nameof(request)); IFlurlRequest flurlReq = client - .CreateRequest(request, HttpMethod.Post, "openapi", "unbindmp", client.Credentials.PushToken!); + .CreateRequest(request, HttpMethod.Post, "openapi", "unbindmp", client.Credentials.Token!); return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); } @@ -82,7 +82,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI if (request is null) throw new ArgumentNullException(nameof(request)); IFlurlRequest flurlReq = client - .CreateRequest(request, HttpMethod.Post, "openapi", "geth5link", client.Credentials.PushToken!); + .CreateRequest(request, HttpMethod.Post, "openapi", "geth5link", client.Credentials.Token!); return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); } @@ -108,13 +108,13 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI request.FileContentType = "image/jpeg"; IFlurlRequest flurlReq = client - .CreateRequest(request, HttpMethod.Post, "openapi", "assetsupload", client.Credentials.PushToken!); + .CreateRequest(request, HttpMethod.Post, "openapi", "assetsupload", client.Credentials.Token!); 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!, + encodingAESKey: client.Credentials.EncodingAESKey!, appId: client.Credentials.AppId! ), Encoding.UTF8 diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteOpenApiNLPExtensions.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteOpenApiNLPExtensions.cs new file mode 100644 index 00000000..86ccb530 --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteOpenApiNLPExtensions.cs @@ -0,0 +1,106 @@ +using System; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using Flurl.Http; + +namespace SKIT.FlurlHttpClient.Wechat.OpenAI +{ + public static class WechatOpenAIClientExecuteOpenApiNLPExtensions + { + /// + /// 异步调用 [POST] /openapi/nlp/tokenize/{TOKEN} 接口。 + /// REF: https://developers.weixin.qq.com/doc/aispeech/platform/nlp/tokenize.html + /// + /// + /// + /// + /// + public static async Task ExecuteOpenApiNLPTokenizeAsync(this WechatOpenAIClient client, Models.OpenApiNLPTokenizeRequest 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", "nlp", "tokenize", client.Credentials.Token!); + + return await client.SendRequestWithUrlEncodedAsync(flurlReq, data: request, cancellationToken: cancellationToken); + } + + /// + /// 异步调用 [POST] /openapi/nlp/ner/{TOKEN} 接口。 + /// REF: https://developers.weixin.qq.com/doc/aispeech/platform/nlp/ner.html + /// + /// + /// + /// + /// + public static async Task ExecuteOpenApiNLPNERAsync(this WechatOpenAIClient client, Models.OpenApiNLPNERRequest 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", "nlp", "ner", client.Credentials.Token!); + + return await client.SendRequestWithUrlEncodedAsync(flurlReq, data: request, cancellationToken: cancellationToken); + } + + /// + /// 异步调用 [POST] /openapi/nlp/sentiment/{TOKEN} 接口。 + /// REF: https://developers.weixin.qq.com/doc/aispeech/platform/nlp/sentiment.html + /// + /// + /// + /// + /// + public static async Task ExecuteOpenApiNLPSentimentAsync(this WechatOpenAIClient client, Models.OpenApiNLPSentimentRequest 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", "nlp", "sentiment", client.Credentials.Token!); + + return await client.SendRequestWithUrlEncodedAsync(flurlReq, data: request, cancellationToken: cancellationToken); + } + + /// + /// 异步调用 [POST] /openapi/nlp/ner-product/{TOKEN} 接口。 + /// REF: https://developers.weixin.qq.com/doc/aispeech/platform/nlp/nerproduct.html + /// + /// + /// + /// + /// + public static async Task ExecuteOpenApiNLPNERProductAsync(this WechatOpenAIClient client, Models.OpenApiNLPNERProductRequest 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", "nlp", "ner-product", client.Credentials.Token!); + + return await client.SendRequestWithUrlEncodedAsync(flurlReq, data: request, cancellationToken: cancellationToken); + } + + /// + /// 异步调用 [POST] /openapi/nlp/sensitive/{TOKEN} 接口。 + /// REF: https://developers.weixin.qq.com/doc/aispeech/platform/nlp/sensitive.html + /// + /// + /// + /// + /// + public static async Task ExecuteOpenApiNLPSensitiveAsync(this WechatOpenAIClient client, Models.OpenApiNLPSensitiveRequest 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", "nlp", "sensitive", client.Credentials.Token!); + + return await client.SendRequestWithUrlEncodedAsync(flurlReq, data: request, cancellationToken: cancellationToken); + } + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteOpenApiQueryExtensions.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteOpenApiQueryExtensions.cs index d6fa05d4..ddca8097 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteOpenApiQueryExtensions.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteOpenApiQueryExtensions.cs @@ -22,7 +22,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI if (request is null) throw new ArgumentNullException(nameof(request)); IFlurlRequest flurlReq = client - .CreateRequest(request, HttpMethod.Post, "openapi", "sign", client.Credentials.PushToken!); + .CreateRequest(request, HttpMethod.Post, "openapi", "sign", client.Credentials.Token!); return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); } @@ -41,7 +41,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI if (request is null) throw new ArgumentNullException(nameof(request)); IFlurlRequest flurlReq = client - .CreateRequest(request, HttpMethod.Post, "openapi", "aibot", client.Credentials.PushToken!); + .CreateRequest(request, HttpMethod.Post, "openapi", "aibot", client.Credentials.Token!); return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); } @@ -60,7 +60,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI if (request is null) throw new ArgumentNullException(nameof(request)); IFlurlRequest flurlReq = client - .CreateRequest(request, HttpMethod.Post, "openapi", "gethotquerylist", client.Credentials.PushToken!); + .CreateRequest(request, HttpMethod.Post, "openapi", "gethotquerylist", client.Credentials.Token!); return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); } diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteOpenApiThirdKfExtensions.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteOpenApiThirdKfExtensions.cs index d9091e93..91d65dfc 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteOpenApiThirdKfExtensions.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Extensions/WechatOpenAIClientExecuteOpenApiThirdKfExtensions.cs @@ -26,7 +26,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI request.AppId = client.Credentials.AppId; IFlurlRequest flurlReq = client - .CreateRequest(request, HttpMethod.Post, "openapi", "sendmsg", client.Credentials.PushToken!); + .CreateRequest(request, HttpMethod.Post, "openapi", "sendmsg", client.Credentials.Token!); return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); } @@ -48,7 +48,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI request.AppId = client.Credentials.AppId; IFlurlRequest flurlReq = client - .CreateRequest(request, HttpMethod.Post, "openapi", "kefustate", "get", client.Credentials.PushToken!); + .CreateRequest(request, HttpMethod.Post, "openapi", "kefustate", "get", client.Credentials.Token!); return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); } @@ -70,7 +70,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI request.AppId = client.Credentials.AppId; IFlurlRequest flurlReq = client - .CreateRequest(request, HttpMethod.Post, "openapi", "kefustate", "change", client.Credentials.PushToken!); + .CreateRequest(request, HttpMethod.Post, "openapi", "kefustate", "change", client.Credentials.Token!); return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken); } diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiNLP/OpenApiNLPNERProductRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiNLP/OpenApiNLPNERProductRequest.cs new file mode 100644 index 00000000..78220388 --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiNLP/OpenApiNLPNERProductRequest.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; + +namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models +{ + /// + /// 表示 [POST] /openapi/nlp/ner-product/{TOKEN} 接口的请求。 + /// + public class OpenApiNLPNERProductRequest : WechatOpenAIRequest, WechatOpenAIRequest.Serialization.IEncryptedUrlEncodedFormData + { + public static class Types + { + public class Data + { + /// + /// 获取或设置输入文本。 + /// + [Newtonsoft.Json.JsonProperty("q")] + [System.Text.Json.Serialization.JsonPropertyName("q")] + public string QueryString { get; set; } = string.Empty; + } + } + + /// + /// 获取或设置用户 ID。 + /// + [Newtonsoft.Json.JsonProperty("uid")] + [System.Text.Json.Serialization.JsonPropertyName("uid")] + public string UserId { get; set; } = string.Empty; + + /// + /// 获取或设置请求数据。 + /// + [Newtonsoft.Json.JsonProperty("data")] + [System.Text.Json.Serialization.JsonPropertyName("data")] + public Types.Data Data { get; set; } = new Types.Data(); +} +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiNLP/OpenApiNLPNERProductResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiNLP/OpenApiNLPNERProductResponse.cs new file mode 100644 index 00000000..1c0060f4 --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiNLP/OpenApiNLPNERProductResponse.cs @@ -0,0 +1,264 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +/* @codestyle-disable no-instantiated-property-in-response */ +namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models +{ + /// + /// 表示 [POST] /openapi/nlp/ner-product/{TOKEN} 接口的响应。 + /// + public class OpenApiNLPNERProductResponse : WechatOpenAIResponse + { + public static class Types + { + public class Data + { + public static class Types + { + public class Result + { + public static class Types + { + public class ProductProperty + { + /// + /// 获取或设置商品属性名。 + /// + [Newtonsoft.Json.JsonIgnore] + [System.Text.Json.Serialization.JsonIgnore] + public string Name { get; set; } = default!; + + /// + /// 获取或设置商品属性值。 + /// + [Newtonsoft.Json.JsonIgnore] + [System.Text.Json.Serialization.JsonIgnore] + public string Value { get; set; } = default!; + + /// + /// 获取或设置起始字符位置。 + /// + [Newtonsoft.Json.JsonIgnore] + [System.Text.Json.Serialization.JsonIgnore] + public int StartIndex { get; set; } + + /// + /// 获取或设置结束字符位置。 + /// + [Newtonsoft.Json.JsonIgnore] + [System.Text.Json.Serialization.JsonIgnore] + public int EndIndex { get; set; } + } + } + + /// + /// 获取或设置结果。 + /// + [Newtonsoft.Json.JsonProperty("product")] + [Newtonsoft.Json.JsonConverter(typeof(Converters.NewtonsoftJsonProductPropertyArrayConverter))] + [System.Text.Json.Serialization.JsonPropertyName("product")] + [System.Text.Json.Serialization.JsonConverter(typeof(Converters.SystemTextJsonProductPropertyArrayConverter))] + public Types.ProductProperty[] ProductPropertyList { get; set; } = default!; + } + } + + /// + /// 获取或设置预处理后的文本。 + /// + [Newtonsoft.Json.JsonProperty("preprocessed_text")] + [System.Text.Json.Serialization.JsonPropertyName("preprocessed_text")] + public string PreprocessedText { get; set; } = default!; + + /// + /// 获取或设置抽取结果信息。 + /// + [Newtonsoft.Json.JsonProperty("entities")] + [Newtonsoft.Json.JsonConverter(typeof(Converters.NewtonsoftJsonProductPropertyArrayConverter))] + [System.Text.Json.Serialization.JsonPropertyName("entities")] + [System.Text.Json.Serialization.JsonConverter(typeof(Converters.SystemTextJsonProductPropertyArrayConverter))] + public Types.Result Result { get; set; } = default!; + } + } + + internal static class Converters + { + internal class NewtonsoftJsonProductPropertyArrayConverter : Newtonsoft.Json.JsonConverter + { + public override bool CanRead + { + get { return true; } + } + + public override bool CanWrite + { + get { return true; } + } + + public override Types.Data.Types.Result.Types.ProductProperty[]? ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, Types.Data.Types.Result.Types.ProductProperty[]? existingValue, bool hasExistingValue, Newtonsoft.Json.JsonSerializer serializer) + { + if (reader.TokenType == Newtonsoft.Json.JsonToken.Null) + { + return existingValue; + } + else if (reader.TokenType == Newtonsoft.Json.JsonToken.StartArray) + { + reader.Read(); + + var tmpList = new List(); + + while (reader.TokenType != Newtonsoft.Json.JsonToken.EndArray) + { + if (reader.TokenType == Newtonsoft.Json.JsonToken.StartArray) + { + reader.Read(); + + int offset = 0; + var tmpItem = new Types.Data.Types.Result.Types.ProductProperty(); + + while (reader.TokenType != Newtonsoft.Json.JsonToken.EndArray) + { + if (offset == 0) + { + tmpItem.Value = serializer.Deserialize(reader)!; + } + else if (offset == 1) + { + tmpItem.Name = serializer.Deserialize(reader)!; + } + else if (offset == 2) + { + tmpItem.StartIndex = serializer.Deserialize(reader); + } + else if (offset == 3) + { + tmpItem.EndIndex = serializer.Deserialize(reader); + } + + offset++; + reader.Read(); + } + + tmpList.Add(tmpItem); + } + + reader.Read(); + } + + return tmpList.ToArray(); + } + + throw new Newtonsoft.Json.JsonReaderException(); + } + + public override void WriteJson(Newtonsoft.Json.JsonWriter writer, Types.Data.Types.Result.Types.ProductProperty[]? value, Newtonsoft.Json.JsonSerializer serializer) + { + if (value != null) + { + writer.WriteStartArray(); + + foreach (var item in value) + { + writer.WriteStartArray(); + writer.WriteValue(item.Value); + writer.WriteValue(item.Name); + writer.WriteValue(item.StartIndex); + writer.WriteValue(item.EndIndex); + writer.WriteEndArray(); + } + + writer.WriteEndArray(); + } + else + { + writer.WriteNull(); + } + } + } + + internal class SystemTextJsonProductPropertyArrayConverter : System.Text.Json.Serialization.JsonConverter + { + public override Types.Data.Types.Result.Types.ProductProperty[]? Read(ref System.Text.Json.Utf8JsonReader reader, Type typeToConvert, System.Text.Json.JsonSerializerOptions options) + { + if (reader.TokenType == System.Text.Json.JsonTokenType.Null) + { + return null; + } + else if (reader.TokenType == System.Text.Json.JsonTokenType.StartArray) + { + reader.Read(); + + var tmpList = new List(); + var tmpOptions = new System.Text.Json.JsonSerializerOptions(options); + + while (reader.TokenType != System.Text.Json.JsonTokenType.EndArray) + { + if (reader.TokenType == System.Text.Json.JsonTokenType.StartArray) + { + reader.Read(); + + int offset = 0; + var tmpItem = new Types.Data.Types.Result.Types.ProductProperty(); + + while (reader.TokenType != System.Text.Json.JsonTokenType.EndArray) + { + if (offset == 0) + { + tmpItem.Value = System.Text.Json.JsonSerializer.Deserialize(ref reader, tmpOptions)!; + } + else if (offset == 1) + { + tmpItem.Name = System.Text.Json.JsonSerializer.Deserialize(ref reader, tmpOptions)!; + } + else if (offset == 2) + { + tmpItem.StartIndex = System.Text.Json.JsonSerializer.Deserialize(ref reader, tmpOptions); + } + else if (offset == 3) + { + tmpItem.EndIndex = System.Text.Json.JsonSerializer.Deserialize(ref reader, tmpOptions); + } + + offset++; + reader.Read(); + } + + tmpList.Add(tmpItem); + } + + reader.Read(); + } + + return tmpList.ToArray(); + } + + throw new System.Text.Json.JsonException(); + } + + public override void Write(System.Text.Json.Utf8JsonWriter writer, Types.Data.Types.Result.Types.ProductProperty[]? value, System.Text.Json.JsonSerializerOptions options) + { + if (value != null) + { + writer.WriteStartArray(); + + foreach (var item in value) + { + writer.WriteStartArray(); + writer.WriteStringValue(item.Value); + writer.WriteStringValue(item.Name); + writer.WriteNumberValue(item.StartIndex); + writer.WriteNumberValue(item.EndIndex); + writer.WriteEndArray(); + } + + writer.WriteEndArray(); + } + else + { + writer.WriteNullValue(); + } + } + } + } + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiNLP/OpenApiNLPNERRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiNLP/OpenApiNLPNERRequest.cs new file mode 100644 index 00000000..e67ec1be --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiNLP/OpenApiNLPNERRequest.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; + +namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models +{ + /// + /// 表示 [POST] /openapi/nlp/ner/{TOKEN} 接口的请求。 + /// + public class OpenApiNLPNERRequest : WechatOpenAIRequest, WechatOpenAIRequest.Serialization.IEncryptedUrlEncodedFormData + { + public static class Types + { + public class Data + { + /// + /// 获取或设置输入文本。 + /// + [Newtonsoft.Json.JsonProperty("q")] + [System.Text.Json.Serialization.JsonPropertyName("q")] + public string QueryString { get; set; } = string.Empty; + } + } + + /// + /// 获取或设置用户 ID。 + /// + [Newtonsoft.Json.JsonProperty("uid")] + [System.Text.Json.Serialization.JsonPropertyName("uid")] + public string UserId { get; set; } = string.Empty; + + /// + /// 获取或设置请求数据。 + /// + [Newtonsoft.Json.JsonProperty("data")] + [System.Text.Json.Serialization.JsonPropertyName("data")] + public Types.Data Data { get; set; } = new Types.Data(); +} +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiNLP/OpenApiNLPNERResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiNLP/OpenApiNLPNERResponse.cs new file mode 100644 index 00000000..2de002c4 --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiNLP/OpenApiNLPNERResponse.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; + +namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models +{ + /// + /// 表示 [POST] /openapi/nlp/ner/{TOKEN} 接口的响应。 + /// + public class OpenApiNLPNERResponse : WechatOpenAIResponse + { + public static class Types + { + public class Result + { + /// + /// 获取或设置结果类型。 + /// + [Newtonsoft.Json.JsonProperty("type")] + [System.Text.Json.Serialization.JsonPropertyName("type")] + public string Type { get; set; } = default!; + + /// + /// 获取或设置范围列表。 + /// + [Newtonsoft.Json.JsonProperty("span")] + [System.Text.Json.Serialization.JsonPropertyName("span")] + public int[] SpanList { get; set; } = default!; + + /// + /// 获取或设置文本。 + /// + [Newtonsoft.Json.JsonProperty("text")] + [System.Text.Json.Serialization.JsonPropertyName("text")] + public string Text { get; set; } = default!; + + /// + /// 获取或设置范数。 + /// + [Newtonsoft.Json.JsonProperty("norm")] + [System.Text.Json.Serialization.JsonPropertyName("norm")] + public object Norm { get; set; } = default!; + } + } + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiNLP/OpenApiNLPSensitiveRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiNLP/OpenApiNLPSensitiveRequest.cs new file mode 100644 index 00000000..b78df8b6 --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiNLP/OpenApiNLPSensitiveRequest.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; + +namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models +{ + /// + /// 表示 [POST] /openapi/nlp/sensitive/{TOKEN} 接口的请求。 + /// + public class OpenApiNLPSensitiveRequest : WechatOpenAIRequest, WechatOpenAIRequest.Serialization.IEncryptedUrlEncodedFormData + { + public static class Types + { + public class Data + { + /// + /// 获取或设置输入文本。 + /// + [Newtonsoft.Json.JsonProperty("q")] + [System.Text.Json.Serialization.JsonPropertyName("q")] + public string QueryString { get; set; } = string.Empty; + + /// + /// 获取或设置模型。 + /// + [Newtonsoft.Json.JsonProperty("model")] + [System.Text.Json.Serialization.JsonPropertyName("model")] + public string? Model { get; set; } + } + } + + /// + /// 获取或设置用户 ID。 + /// + [Newtonsoft.Json.JsonProperty("uid")] + [System.Text.Json.Serialization.JsonPropertyName("uid")] + public string UserId { get; set; } = string.Empty; + + /// + /// 获取或设置请求数据。 + /// + [Newtonsoft.Json.JsonProperty("data")] + [System.Text.Json.Serialization.JsonPropertyName("data")] + public Types.Data Data { get; set; } = new Types.Data(); +} +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiNLP/OpenApiNLPSensitiveResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiNLP/OpenApiNLPSensitiveResponse.cs new file mode 100644 index 00000000..35ca91e6 --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiNLP/OpenApiNLPSensitiveResponse.cs @@ -0,0 +1,208 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +/* @codestyle-disable no-instantiated-property-in-response */ +namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models +{ + /// + /// 表示 [POST] /openapi/nlp/sensitive/{TOKEN} 接口的响应。 + /// + public class OpenApiNLPSensitiveResponse : WechatOpenAIResponse + { + public static class Types + { + public class Data + { + public static class Types + { + public class Result + { + /// + /// 获取或设置敏感信息项。 + /// + [Newtonsoft.Json.JsonIgnore] + [System.Text.Json.Serialization.JsonIgnore] + public string Sensitive { get; set; } = default!; + + /// + /// 获取或设置分值(范围:0~1)。 + /// + [Newtonsoft.Json.JsonIgnore] + [System.Text.Json.Serialization.JsonIgnore] + public double Score { get; set; } + } + } + + /// + /// 获取或设置结果。 + /// + [Newtonsoft.Json.JsonProperty("result")] + [Newtonsoft.Json.JsonConverter(typeof(Converters.NewtonsoftJsonResultArrayConverter))] + [System.Text.Json.Serialization.JsonPropertyName("result")] + [System.Text.Json.Serialization.JsonConverter(typeof(Converters.SystemTextJsonResultArrayConverter))] + public Types.Result[] ResultList { get; set; } = default!; + } + } + + internal static class Converters + { + internal class NewtonsoftJsonResultArrayConverter : Newtonsoft.Json.JsonConverter + { + public override bool CanRead + { + get { return true; } + } + + public override bool CanWrite + { + get { return true; } + } + + public override Types.Data.Types.Result[]? ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, Types.Data.Types.Result[]? existingValue, bool hasExistingValue, Newtonsoft.Json.JsonSerializer serializer) + { + if (reader.TokenType == Newtonsoft.Json.JsonToken.Null) + { + return existingValue; + } + else if (reader.TokenType == Newtonsoft.Json.JsonToken.StartArray) + { + reader.Read(); + + var tmpList = new List(); + + while (reader.TokenType != Newtonsoft.Json.JsonToken.EndArray) + { + if (reader.TokenType == Newtonsoft.Json.JsonToken.StartArray) + { + reader.Read(); + + int offset = 0; + var tmpItem = new Types.Data.Types.Result(); + + while (reader.TokenType != Newtonsoft.Json.JsonToken.EndArray) + { + if (offset == 0) + { + tmpItem.Sensitive = serializer.Deserialize(reader)!; + } + else if (offset == 1) + { + tmpItem.Score = serializer.Deserialize(reader); + } + + offset++; + reader.Read(); + } + + tmpList.Add(tmpItem); + } + + reader.Read(); + } + + return tmpList.ToArray(); + } + + throw new Newtonsoft.Json.JsonReaderException(); + } + + public override void WriteJson(Newtonsoft.Json.JsonWriter writer, Types.Data.Types.Result[]? value, Newtonsoft.Json.JsonSerializer serializer) + { + if (value != null) + { + writer.WriteStartArray(); + + foreach (var item in value) + { + writer.WriteStartArray(); + writer.WriteValue(item.Sensitive); + writer.WriteValue(item.Score); + writer.WriteEndArray(); + } + + writer.WriteEndArray(); + } + else + { + writer.WriteNull(); + } + } + } + + internal class SystemTextJsonResultArrayConverter : System.Text.Json.Serialization.JsonConverter + { + public override Types.Data.Types.Result[]? Read(ref System.Text.Json.Utf8JsonReader reader, Type typeToConvert, System.Text.Json.JsonSerializerOptions options) + { + if (reader.TokenType == System.Text.Json.JsonTokenType.Null) + { + return null; + } + else if (reader.TokenType == System.Text.Json.JsonTokenType.StartArray) + { + reader.Read(); + + var tmpList = new List(); + var tmpOptions = new System.Text.Json.JsonSerializerOptions(options); + + while (reader.TokenType != System.Text.Json.JsonTokenType.EndArray) + { + if (reader.TokenType == System.Text.Json.JsonTokenType.StartArray) + { + reader.Read(); + + int offset = 0; + var tmpItem = new Types.Data.Types.Result(); + + while (reader.TokenType != System.Text.Json.JsonTokenType.EndArray) + { + if (offset == 0) + { + tmpItem.Sensitive = System.Text.Json.JsonSerializer.Deserialize(ref reader, tmpOptions)!; + } + else if (offset == 1) + { + tmpItem.Score = System.Text.Json.JsonSerializer.Deserialize(ref reader, tmpOptions); + } + + offset++; + reader.Read(); + } + + tmpList.Add(tmpItem); + } + + reader.Read(); + } + + return tmpList.ToArray(); + } + + throw new System.Text.Json.JsonException(); + } + + public override void Write(System.Text.Json.Utf8JsonWriter writer, Types.Data.Types.Result[]? value, System.Text.Json.JsonSerializerOptions options) + { + if (value != null) + { + writer.WriteStartArray(); + + foreach (var item in value) + { + writer.WriteStartArray(); + writer.WriteStringValue(item.Sensitive); + writer.WriteNumberValue(item.Score); + writer.WriteEndArray(); + } + + writer.WriteEndArray(); + } + else + { + writer.WriteNullValue(); + } + } + } + } + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiNLP/OpenApiNLPSentimentRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiNLP/OpenApiNLPSentimentRequest.cs new file mode 100644 index 00000000..9e86a573 --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiNLP/OpenApiNLPSentimentRequest.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; + +namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models +{ + /// + /// 表示 [POST] /openapi/nlp/sentiment/{TOKEN} 接口的请求。 + /// + public class OpenApiNLPSentimentRequest : WechatOpenAIRequest, WechatOpenAIRequest.Serialization.IEncryptedUrlEncodedFormData + { + public static class Types + { + public class Data + { + /// + /// 获取或设置输入文本。 + /// + [Newtonsoft.Json.JsonProperty("q")] + [System.Text.Json.Serialization.JsonPropertyName("q")] + public string QueryString { get; set; } = string.Empty; + + /// + /// 获取或设置模式。 + /// + [Newtonsoft.Json.JsonProperty("mode")] + [System.Text.Json.Serialization.JsonPropertyName("mode")] + public string? Mode { get; set; } + } + } + + /// + /// 获取或设置用户 ID。 + /// + [Newtonsoft.Json.JsonProperty("uid")] + [System.Text.Json.Serialization.JsonPropertyName("uid")] + public string UserId { get; set; } = string.Empty; + + /// + /// 获取或设置请求数据。 + /// + [Newtonsoft.Json.JsonProperty("data")] + [System.Text.Json.Serialization.JsonPropertyName("data")] + public Types.Data Data { get; set; } = new Types.Data(); +} +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiNLP/OpenApiNLPSentimentResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiNLP/OpenApiNLPSentimentResponse.cs new file mode 100644 index 00000000..86ec5a67 --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiNLP/OpenApiNLPSentimentResponse.cs @@ -0,0 +1,208 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +/* @codestyle-disable no-instantiated-property-in-response */ +namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models +{ + /// + /// 表示 [POST] /openapi/nlp/sentiment/{TOKEN} 接口的响应。 + /// + public class OpenApiNLPSentimentResponse : WechatOpenAIResponse + { + public static class Types + { + public class Data + { + public static class Types + { + public class Result + { + /// + /// 获取或设置情感信息项。 + /// + [Newtonsoft.Json.JsonIgnore] + [System.Text.Json.Serialization.JsonIgnore] + public string Sentiment { get; set; } = default!; + + /// + /// 获取或设置分值(范围:0~1)。 + /// + [Newtonsoft.Json.JsonIgnore] + [System.Text.Json.Serialization.JsonIgnore] + public double Score { get; set; } + } + } + + /// + /// 获取或设置结果。 + /// + [Newtonsoft.Json.JsonProperty("result")] + [Newtonsoft.Json.JsonConverter(typeof(Converters.NewtonsoftJsonResultArrayConverter))] + [System.Text.Json.Serialization.JsonPropertyName("result")] + [System.Text.Json.Serialization.JsonConverter(typeof(Converters.SystemTextJsonResultArrayConverter))] + public Types.Result[] ResultList { get; set; } = default!; + } + } + + internal static class Converters + { + internal class NewtonsoftJsonResultArrayConverter : Newtonsoft.Json.JsonConverter + { + public override bool CanRead + { + get { return true; } + } + + public override bool CanWrite + { + get { return true; } + } + + public override Types.Data.Types.Result[]? ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, Types.Data.Types.Result[]? existingValue, bool hasExistingValue, Newtonsoft.Json.JsonSerializer serializer) + { + if (reader.TokenType == Newtonsoft.Json.JsonToken.Null) + { + return existingValue; + } + else if (reader.TokenType == Newtonsoft.Json.JsonToken.StartArray) + { + reader.Read(); + + var tmpList = new List(); + + while (reader.TokenType != Newtonsoft.Json.JsonToken.EndArray) + { + if (reader.TokenType == Newtonsoft.Json.JsonToken.StartArray) + { + reader.Read(); + + int offset = 0; + var tmpItem = new Types.Data.Types.Result(); + + while (reader.TokenType != Newtonsoft.Json.JsonToken.EndArray) + { + if (offset == 0) + { + tmpItem.Sentiment = serializer.Deserialize(reader)!; + } + else if (offset == 1) + { + tmpItem.Score = serializer.Deserialize(reader); + } + + offset++; + reader.Read(); + } + + tmpList.Add(tmpItem); + } + + reader.Read(); + } + + return tmpList.ToArray(); + } + + throw new Newtonsoft.Json.JsonReaderException(); + } + + public override void WriteJson(Newtonsoft.Json.JsonWriter writer, Types.Data.Types.Result[]? value, Newtonsoft.Json.JsonSerializer serializer) + { + if (value != null) + { + writer.WriteStartArray(); + + foreach (var item in value) + { + writer.WriteStartArray(); + writer.WriteValue(item.Sentiment); + writer.WriteValue(item.Score); + writer.WriteEndArray(); + } + + writer.WriteEndArray(); + } + else + { + writer.WriteNull(); + } + } + } + + internal class SystemTextJsonResultArrayConverter : System.Text.Json.Serialization.JsonConverter + { + public override Types.Data.Types.Result[]? Read(ref System.Text.Json.Utf8JsonReader reader, Type typeToConvert, System.Text.Json.JsonSerializerOptions options) + { + if (reader.TokenType == System.Text.Json.JsonTokenType.Null) + { + return null; + } + else if (reader.TokenType == System.Text.Json.JsonTokenType.StartArray) + { + reader.Read(); + + var tmpList = new List(); + var tmpOptions = new System.Text.Json.JsonSerializerOptions(options); + + while (reader.TokenType != System.Text.Json.JsonTokenType.EndArray) + { + if (reader.TokenType == System.Text.Json.JsonTokenType.StartArray) + { + reader.Read(); + + int offset = 0; + var tmpItem = new Types.Data.Types.Result(); + + while (reader.TokenType != System.Text.Json.JsonTokenType.EndArray) + { + if (offset == 0) + { + tmpItem.Sentiment = System.Text.Json.JsonSerializer.Deserialize(ref reader, tmpOptions)!; + } + else if (offset == 1) + { + tmpItem.Score = System.Text.Json.JsonSerializer.Deserialize(ref reader, tmpOptions); + } + + offset++; + reader.Read(); + } + + tmpList.Add(tmpItem); + } + + reader.Read(); + } + + return tmpList.ToArray(); + } + + throw new System.Text.Json.JsonException(); + } + + public override void Write(System.Text.Json.Utf8JsonWriter writer, Types.Data.Types.Result[]? value, System.Text.Json.JsonSerializerOptions options) + { + if (value != null) + { + writer.WriteStartArray(); + + foreach (var item in value) + { + writer.WriteStartArray(); + writer.WriteStringValue(item.Sentiment); + writer.WriteNumberValue(item.Score); + writer.WriteEndArray(); + } + + writer.WriteEndArray(); + } + else + { + writer.WriteNullValue(); + } + } + } + } + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiNLP/OpenApiNLPTokenizeRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiNLP/OpenApiNLPTokenizeRequest.cs new file mode 100644 index 00000000..dba17a43 --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiNLP/OpenApiNLPTokenizeRequest.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; + +namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models +{ + /// + /// 表示 [POST] /openapi/nlp/tokenize/{TOKEN} 接口的请求。 + /// + public class OpenApiNLPTokenizeRequest : WechatOpenAIRequest, WechatOpenAIRequest.Serialization.IEncryptedUrlEncodedFormData + { + public static class Types + { + public class Data + { + /// + /// 获取或设置输入文本。 + /// + [Newtonsoft.Json.JsonProperty("q")] + [System.Text.Json.Serialization.JsonPropertyName("q")] + public string QueryString { get; set; } = string.Empty; + } + } + + /// + /// 获取或设置用户 ID。 + /// + [Newtonsoft.Json.JsonProperty("uid")] + [System.Text.Json.Serialization.JsonPropertyName("uid")] + public string UserId { get; set; } = string.Empty; + + /// + /// 获取或设置请求数据。 + /// + [Newtonsoft.Json.JsonProperty("data")] + [System.Text.Json.Serialization.JsonPropertyName("data")] + public Types.Data Data { get; set; } = new Types.Data(); +} +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiNLP/OpenApiNLPTokenizeResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiNLP/OpenApiNLPTokenizeResponse.cs new file mode 100644 index 00000000..6cde2686 --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/OpenApiNLP/OpenApiNLPTokenizeResponse.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; + +namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models +{ + /// + /// 表示 [POST] /openapi/nlp/tokenize/{TOKEN} 接口的响应。 + /// + public class OpenApiNLPTokenizeResponse : WechatOpenAIResponse + { + public static class Types + { + public class Data + { + /// + /// 获取或设置常规粒度分词结果列表。 + /// + [Newtonsoft.Json.JsonProperty("words")] + [System.Text.Json.Serialization.JsonPropertyName("words")] + public string[] WordList { get; set; } = default!; + + /// + /// 获取或设置常规粒度词性标签列表。 + /// + [Newtonsoft.Json.JsonProperty("POSs")] + [System.Text.Json.Serialization.JsonPropertyName("POSs")] + public int[] POSList { get; set; } = default!; + + /// + /// 获取或设置混合粒度分词结果列表。 + /// + [Newtonsoft.Json.JsonProperty("words_mix")] + [System.Text.Json.Serialization.JsonPropertyName("words_mix")] + public string[] WordMixList { get; set; } = default!; + + /// + /// 获取或设置混合粒度词性标签列表。 + /// + [Newtonsoft.Json.JsonProperty("POSs_mix")] + [System.Text.Json.Serialization.JsonPropertyName("POSs_mix")] + public int[] POSMixList { get; set; } = default!; + + /// + /// 获取或设置短语提取结果列表。 + /// + [Newtonsoft.Json.JsonProperty("entities")] + [System.Text.Json.Serialization.JsonPropertyName("entities")] + public string[] EntityList { get; set; } = default!; + + /// + /// 获取或设置短语类型标签列表。 + /// + [Newtonsoft.Json.JsonProperty("entity_types")] + [System.Text.Json.Serialization.JsonPropertyName("entity_types")] + public int[] EntityTypeList { get; set; } = default!; + } + } + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/User/UserRegisterRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/User/UserRegisterRequest.cs index b51e9d34..8c51d080 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/User/UserRegisterRequest.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/User/UserRegisterRequest.cs @@ -9,7 +9,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models public class UserRegisterRequest : WechatOpenAIRequest { /// - /// 获取或设置平台自定义用户名。 + /// 获取或设置用户 ID。 /// [Newtonsoft.Json.JsonProperty("uid")] [System.Text.Json.Serialization.JsonPropertyName("uid")] 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 c8fe0e36..92f57248 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/SKIT.FlurlHttpClient.Wechat.OpenAI.csproj +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/SKIT.FlurlHttpClient.Wechat.OpenAI.csproj @@ -27,6 +27,7 @@ + diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Settings/Credentials.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Settings/Credentials.cs index 800dea03..70fc9ddb 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Settings/Credentials.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Settings/Credentials.cs @@ -24,14 +24,14 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Settings public string? AppId { get; } /// - /// 初始化客户端时 的副本。 + /// 初始化客户端时 的副本。 /// - public string? PushToken { get; } + public string? Token { get; } /// - /// 初始化客户端时 的副本。 + /// 初始化客户端时 的副本。 /// - public string? PushEncodingAESKey { get; } + public string? EncodingAESKey { get; } internal Credentials(WechatOpenAIClientOptions options) { @@ -40,8 +40,8 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Settings ClientId = options.ClientId; ClientKey = options.ClientKey; AppId = options.AppId; - PushToken = options.PushToken; - PushEncodingAESKey = options.PushEncodingAESKey; + Token = options.Token; + EncodingAESKey = options.EncodingAESKey; } } } diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Utilities/Internal/JWTUtility.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Utilities/Internal/JWTUtility.cs new file mode 100644 index 00000000..a518e4f1 --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Utilities/Internal/JWTUtility.cs @@ -0,0 +1,25 @@ +using System; +using JWT; +using JWT.Algorithms; +using JWT.Serializers; +using Newtonsoft.Json; + +namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Utilities +{ + internal static class JWTUtility + { + private static readonly Lazy _encoder = new Lazy(() => + { + IJwtAlgorithm algorithm = new HMACSHA256Algorithm(); + IJsonSerializer serializer = new JsonNetSerializer(new JsonSerializer() { NullValueHandling = NullValueHandling.Ignore }); + IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder(); + IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder); + return encoder; + }, isThreadSafe: true); + + public static string EncodeWithHS256(object payload, string secret) + { + return _encoder.Value.Encode(payload, secret); + } + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIClient.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIClient.cs index c272f94f..c992ac51 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIClient.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIClient.cs @@ -115,7 +115,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI if (data is WechatOpenAIRequest.Serialization.IEncryptedXmlable) { string plainXml = Utilities.XmlUtility.Serialize(data); - string encryptedXml = Utilities.WxBizMsgCryptor.AESEncrypt(plainText: plainXml, encodingAESKey: Credentials.PushEncodingAESKey!, appId: Credentials.AppId!); + string encryptedXml = Utilities.WxBizMsgCryptor.AESEncrypt(plainText: plainXml, encodingAESKey: Credentials.EncodingAESKey!, appId: Credentials.AppId!); data = new { encrypt = encryptedXml }; } @@ -128,6 +128,38 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI } } + /// + /// 异步发起请求。 + /// + /// + /// + /// + /// + /// + public async Task SendRequestWithUrlEncodedAsync(IFlurlRequest flurlRequest, object? data = null, CancellationToken cancellationToken = default) + where T : WechatOpenAIResponse, new() + { + try + { + if (data is WechatOpenAIRequest.Serialization.IEncryptedUrlEncodedFormData) + { + string jwt = Utilities.JWTUtility.EncodeWithHS256(payload: data, secret: Credentials.EncodingAESKey!); + data = new { query = jwt }; + } + + using IFlurlResponse flurlResponse = await flurlRequest + .WithClient(FlurlClient) + .AllowAnyHttpStatus() + .SendUrlEncodedAsync(flurlRequest.Verb, data, cancellationToken) + .ConfigureAwait(false); + return await GetResposneAsync(flurlResponse).ConfigureAwait(false); + } + catch (FlurlHttpException ex) + { + throw new WechatOpenAIException(ex.Message, ex); + } + } + private async Task GetResposneAsync(IFlurlResponse flurlResponse) where T : WechatOpenAIResponse, new() { diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIClientOptions.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIClientOptions.cs index 58f2f8ad..21ec7ba2 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIClientOptions.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIClientOptions.cs @@ -33,13 +33,13 @@ public string? AppId { get; set; } /// - /// 获取或设置微信智能对话服务器推送的 EncodingAESKey。仅限平台接入时使用。 + /// 获取或设置微信智能对话 Token。仅限平台接入时使用。 /// - public string? PushEncodingAESKey { get; set; } + public string? Token { get; set; } /// - /// 获取或设置微信智能对话服务器推送的 Token。仅限平台接入时使用。 + /// 获取或设置微信智能对话 EncodingAESKey。仅限平台接入时使用。 /// - public string? PushToken { get; set; } + public string? EncodingAESKey { get; set; } } } diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIRequest.cs index 1c90cbf0..4f89e938 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIRequest.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/WechatOpenAIRequest.cs @@ -12,6 +12,10 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI public interface IEncryptedXmlable { } + + public interface IEncryptedUrlEncodedFormData + { + } } /// diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/MarketingPartnerships/QueryMarketingPartnershipsRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/MarketingPartnerships/QueryMarketingPartnershipsRequest.cs index 872759a5..0e859b2a 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/MarketingPartnerships/QueryMarketingPartnershipsRequest.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV3/Models/MarketingPartnerships/QueryMarketingPartnershipsRequest.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -/* @codestyle-disable no-jsonable-property-in-get */ +/* @codestyle-disable no-jsonable-property-in-request-get */ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models { /// diff --git a/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/ModelSamples/OpenApiNLP/OpenApiNLPNERRequest.json b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/ModelSamples/OpenApiNLP/OpenApiNLPNERRequest.json new file mode 100644 index 00000000..b68faae7 --- /dev/null +++ b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/ModelSamples/OpenApiNLP/OpenApiNLPNERRequest.json @@ -0,0 +1,6 @@ +{ + "uid": "xjlsj33lasfaf", + "data": { + "q": "帮我订两张后天上午的火车票" + } +} \ No newline at end of file diff --git a/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/ModelSamples/OpenApiNLP/OpenApiNLPNERResponse.json b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/ModelSamples/OpenApiNLP/OpenApiNLPNERResponse.json new file mode 100644 index 00000000..59da846f --- /dev/null +++ b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/ModelSamples/OpenApiNLP/OpenApiNLPNERResponse.json @@ -0,0 +1,22 @@ +{ + "data": [ + { + "type": "number", + "span": [ + 3, + 4 + ], + "text": "两", + "norm": "2" + }, + { + "type": "datetime_interval", + "span": [ + 5, + 9 + ], + "text": "后天上午", + "norm": "2019-10-30 08:00:00~2019-10-30 11:59:59" + } + ] +} \ No newline at end of file diff --git a/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/ModelSamples/OpenApiNLP/OpenApiNLPSensitiveRequest.json b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/ModelSamples/OpenApiNLP/OpenApiNLPSensitiveRequest.json new file mode 100644 index 00000000..f9168b8c --- /dev/null +++ b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/ModelSamples/OpenApiNLP/OpenApiNLPSensitiveRequest.json @@ -0,0 +1,7 @@ +{ + "uid": "xjlsj33lasfaf", + "data": { + "q": "楼主真垃圾,祝你早日死全家", + "model": "cnnn" + } +} \ No newline at end of file diff --git a/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/ModelSamples/OpenApiNLP/OpenApiNLPSensitiveResponse.json b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/ModelSamples/OpenApiNLP/OpenApiNLPSensitiveResponse.json new file mode 100644 index 00000000..c83a7176 --- /dev/null +++ b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/ModelSamples/OpenApiNLP/OpenApiNLPSensitiveResponse.json @@ -0,0 +1,22 @@ +{ + "data": { + "result": [ + [ + "dirty_curse", + 0.9999999900000001 + ], + [ + "other", + 9.9999999E-9 + ], + [ + "dirty_politics", + 0.0 + ], + [ + "dirty_porno", + 0.0 + ] + ] + } +} \ No newline at end of file diff --git a/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/ModelSamples/OpenApiNLP/OpenApiNLPSentimentRequest.json b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/ModelSamples/OpenApiNLP/OpenApiNLPSentimentRequest.json new file mode 100644 index 00000000..0ae861d6 --- /dev/null +++ b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/ModelSamples/OpenApiNLP/OpenApiNLPSentimentRequest.json @@ -0,0 +1,7 @@ +{ + "uid": "xjlsj33lasfaf", + "data": { + "q": "恭喜小张脱单成功", + "mode": "3class" + } +} \ No newline at end of file diff --git a/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/ModelSamples/OpenApiNLP/OpenApiNLPSentimentResponse.json b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/ModelSamples/OpenApiNLP/OpenApiNLPSentimentResponse.json new file mode 100644 index 00000000..14331036 --- /dev/null +++ b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/ModelSamples/OpenApiNLP/OpenApiNLPSentimentResponse.json @@ -0,0 +1,18 @@ +{ + "data": { + "result": [ + [ + "正面", + 0.9593541622161865 + ], + [ + "无情感", + 0.0400625541806221 + ], + [ + "负面", + 0.000583284127060324 + ] + ] + } +} \ No newline at end of file diff --git a/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/ModelSamples/OpenApiNLP/OpenApiNLPTokenizeRequest.json b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/ModelSamples/OpenApiNLP/OpenApiNLPTokenizeRequest.json new file mode 100644 index 00000000..63ce3ba7 --- /dev/null +++ b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/ModelSamples/OpenApiNLP/OpenApiNLPTokenizeRequest.json @@ -0,0 +1,6 @@ +{ + "uid": "xjlsj33lasfaf", + "data": { + "q": "在微信智言与微信智聆两大技术的支持下,微信AI团队推出了“微信对话开放平台”和“腾讯小微”智能硬件两大核心产品。微信支付团队最新发布的“微信青蛙Pro”在现场设置了体验区,让大家感受AI认脸的本事。" + } +} \ No newline at end of file diff --git a/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/ModelSamples/OpenApiNLP/OpenApiNLPTokenizeResponse.json b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/ModelSamples/OpenApiNLP/OpenApiNLPTokenizeResponse.json new file mode 100644 index 00000000..d05a9679 --- /dev/null +++ b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/ModelSamples/OpenApiNLP/OpenApiNLPTokenizeResponse.json @@ -0,0 +1,284 @@ +{ + "data": { + "words": [ + "在", + "微信", + "智", + "言", + "与", + "微信", + "智", + "聆", + "两", + "大", + "技术", + "的", + "支持", + "下", + ",", + "微信", + "ai", + "团队", + "推出", + "了", + "“", + "微信", + "对话", + "开放", + "平台", + "”", + "和", + "“", + "腾讯", + "小", + "微", + "”", + "智能", + "硬件", + "两", + "大", + "核心", + "产品", + "。", + "微信", + "支付", + "团队", + "最新", + "发布", + "的", + "“", + "微信", + "青蛙", + "pro", + "”", + "在", + "现场", + "设置", + "了", + "体验", + "区", + ",", + "让", + "大家", + "感受", + "ai", + "认", + "脸", + "的", + "本事", + "。" + ], + "POSs": [ + 25, + 16, + 16, + 46, + 25, + 16, + 16, + 46, + 15, + 1, + 16, + 30, + 33, + 8, + 34, + 31, + 23, + 16, + 31, + 36, + 34, + 16, + 33, + 33, + 16, + 34, + 5, + 34, + 6, + 1, + 38, + 34, + 16, + 16, + 15, + 1, + 16, + 16, + 34, + 6, + 31, + 16, + 1, + 31, + 30, + 34, + 31, + 16, + 23, + 34, + 25, + 28, + 31, + 30, + 33, + 16, + 34, + 31, + 27, + 31, + 23, + 31, + 16, + 30, + 16, + 34 + ], + "words_mix": [ + "在", + "微信", + "智", + "言", + "与", + "微信", + "智", + "聆", + "两", + "大", + "技术", + "的", + "支持", + "下", + ",", + "微信", + "ai", + "团队", + "推出", + "了", + "“", + "微信", + "对话", + "开放", + "平台", + "”", + "和", + "“", + "腾讯", + "小微", + "”", + "智能", + "硬件", + "两", + "大", + "核心", + "产品", + "。", + "微信", + "支付", + "团队", + "最新", + "发布", + "的", + "“", + "微信", + "青蛙", + "pro", + "”", + "在", + "现场", + "设置", + "了", + "体验", + "区", + ",", + "让", + "大家", + "感受", + "ai", + "认", + "脸", + "的", + "本事", + "。" + ], + "POSs_mix": [ + 25, + 16, + 16, + 46, + 25, + 16, + 16, + 46, + 15, + 1, + 16, + 30, + 33, + 8, + 34, + 31, + 23, + 16, + 31, + 36, + 34, + 16, + 33, + 33, + 16, + 34, + 5, + 34, + 6, + 16, + 34, + 16, + 16, + 15, + 1, + 16, + 16, + 34, + 6, + 31, + 16, + 1, + 31, + 30, + 34, + 31, + 16, + 23, + 34, + 25, + 28, + 31, + 30, + 33, + 16, + 34, + 31, + 27, + 31, + 23, + 31, + 16, + 30, + 16, + 34 + ], + "entities": [ + "腾讯", + "小微", + "最新发布" + ], + "entity_types": [ + 100000013, + 0, + 0 + ] + } +} diff --git a/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/TestClients.cs b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/TestClients.cs index 1aad1387..40ae97c8 100644 --- a/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/TestClients.cs +++ b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/TestClients.cs @@ -9,7 +9,10 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests Instance = new WechatOpenAIClient(new WechatOpenAIClientOptions() { ClientId = TestConfigs.WechatClientId, - ClientKey = TestConfigs.WechatClientKey + ClientKey = TestConfigs.WechatClientKey, + AppId = TestConfigs.WechatAppId, + Token = TestConfigs.WechatToken, + EncodingAESKey = TestConfigs.WechatEncodingAESKey }); } diff --git a/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/TestConfigs.cs b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/TestConfigs.cs index 077a5ab6..b2c18206 100644 --- a/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/TestConfigs.cs +++ b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/TestConfigs.cs @@ -17,6 +17,9 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests var config = json.RootElement.GetProperty("WechatConfig"); WechatClientId = config.GetProperty("ClientId").GetString(); WechatClientKey = config.GetProperty("ClientKey").GetString(); + WechatAppId = config.GetProperty("AppId").GetString(); + WechatToken = config.GetProperty("Token").GetString(); + WechatEncodingAESKey = config.GetProperty("EncodingAESKey").GetString(); WechatAccessToken = config.GetProperty("AccessToken").GetString(); ProjectSourceDirectory = json.RootElement.GetProperty("ProjectSourceDirectory").GetString(); @@ -25,6 +28,9 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests public static readonly string WechatClientId; public static readonly string WechatClientKey; + public static readonly string WechatAppId; + public static readonly string WechatToken; + public static readonly string WechatEncodingAESKey; public static readonly string WechatAccessToken; public static readonly string ProjectSourceDirectory; diff --git a/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/WechatOpenAIJWTTests.cs b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/WechatOpenAIJWTTests.cs new file mode 100644 index 00000000..2b05e0ea --- /dev/null +++ b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/WechatOpenAIJWTTests.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests +{ + public class WechatOpenAIJWTTests + { + [Fact(DisplayName = "JWT 编码(HS256)")] + public void JWTEncodeWithHS256Test() + { + object payload = new + { + uid = "xjlsj33lasfaf", + data = new + { + q = "在微信智言与微信智聆两大技术的支持下,微信AI团队推出了“微信对话开放平台”和“腾讯小微”智能硬件两大核心产品。微信支付团队最新发布的“微信青蛙Pro”在现场设置了体验区,让大家感受AI认脸的本事。" + } + }; + string secret = "jWmYm7qr5nMoAUwZRjGtBxmz3KA1tkAj3ykkR6q2B2C"; + + string actualJwt = Utilities.JWTUtility.EncodeWithHS256(payload: payload, secret: secret); + string expectdJwt = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1aWQiOiJ4amxzajMzbGFzZmFmIiwiZGF0YSI6eyJxIjoi5Zyo5b6u5L-h5pm66KiA5LiO5b6u5L-h5pm66IGG5Lik5aSn5oqA5pyv55qE5pSv5oyB5LiL77yM5b6u5L-hQUnlm6LpmJ_mjqjlh7rkuobigJzlvq7kv6Hlr7nor53lvIDmlL7lubPlj7DigJ3lkozigJzohb7orq_lsI_lvq7igJ3mmbrog73noazku7bkuKTlpKfmoLjlv4Pkuqflk4HjgILlvq7kv6HmlK_ku5jlm6LpmJ_mnIDmlrDlj5HluIPnmoTigJzlvq7kv6HpnZLom5lQcm_igJ3lnKjnjrDlnLrorr7nva7kuobkvZPpqozljLrvvIzorqnlpKflrrbmhJ_lj5dBSeiupOiEuOeahOacrOS6i-OAgiJ9fQ.8FeSvxKlIrbI6MCAaWGekB4sHGA8DeUxgVXiHa8ulJk"; + + Assert.Equal(expectdJwt, actualJwt, ignoreCase: true); + } + } +} diff --git a/test/SKIT.FlurlHttpClient.Wechat.TestTools/CodeStyleUtil.cs b/test/SKIT.FlurlHttpClient.Wechat.TestTools/CodeStyleUtil.cs index bc024e3c..3c0c9459 100644 --- a/test/SKIT.FlurlHttpClient.Wechat.TestTools/CodeStyleUtil.cs +++ b/test/SKIT.FlurlHttpClient.Wechat.TestTools/CodeStyleUtil.cs @@ -497,7 +497,7 @@ namespace SKIT.FlurlHttpClient.Wechat // 如果是 GET 请求,检查是否包含 JSON 序列化字段 if ("GET".Equals(expectedRequestMethod, StringComparison.OrdinalIgnoreCase)) { - if (!(reqCodeSourceCode.Contains("/* @codestyle-disable") && reqCodeSourceCode.Contains("no-jsonable-property-in-get"))) + if (!(reqCodeSourceCode.Contains("/* @codestyle-disable") && reqCodeSourceCode.Contains("no-jsonable-property-in-request-get"))) { if (new Regex("\\[Newtonsoft.Json.JsonProperty\\(\"[a-zA-Z0-9_]*\"\\)\\]").IsMatch(reqCodeSourceCode)) { @@ -560,10 +560,13 @@ namespace SKIT.FlurlHttpClient.Wechat } // 检验是否包含 `new class()` 的赋值 - if (new Regex("=\\s*new\\s[a-zA-Z0-9.]*\\(\\)").IsMatch(resCodeSourceCode)) + if (!(resCodeSourceCode.Contains("/* @codestyle-disable") && resCodeSourceCode.Contains("no-instantiated-property-in-response"))) { - lstError.Add(new Exception($"源代码 \"{resCodeFileName}\" 下代码有误,请求模型不应包含 `= new class()` 赋值。")); - return false; + if (new Regex("=\\s*new\\s[a-zA-Z0-9.]*\\(\\)").IsMatch(resCodeSourceCode)) + { + lstError.Add(new Exception($"源代码 \"{resCodeFileName}\" 下代码有误,响应模型不应包含 `= new class()` 赋值。")); + return false; + } } // 检验是否包含列表类型字段