diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/Platform_NLP/NLPNERProductResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/Platform_NLP/NLPNERProductResponse.cs index 11b9f49c..3c70679c 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/Platform_NLP/NLPNERProductResponse.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/Platform_NLP/NLPNERProductResponse.cs @@ -52,16 +52,16 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models.Platform /// 获取或设置结果。 /// [Newtonsoft.Json.JsonProperty("product")] - [Newtonsoft.Json.JsonConverter(typeof(Converters.NewtonsoftJsonProductPropertyArrayConverter))] + [Newtonsoft.Json.JsonConverter(typeof(Converters.ResponsePropertyProductPropertyArrayNewtonsoftJsonConverter))] [System.Text.Json.Serialization.JsonPropertyName("product")] - [System.Text.Json.Serialization.JsonConverter(typeof(Converters.SystemTextJsonProductPropertyArrayConverter))] + [System.Text.Json.Serialization.JsonConverter(typeof(Converters.ResponsePropertyProductPropertyArraySystemTextJsonConverter))] public Types.ProductProperty[] ProductPropertyList { get; set; } = default!; } } internal static class Converters { - internal class NewtonsoftJsonProductPropertyArrayConverter : Newtonsoft.Json.JsonConverter + internal class ResponsePropertyProductPropertyArrayNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter { public override bool CanRead { @@ -154,7 +154,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models.Platform } } - internal class SystemTextJsonProductPropertyArrayConverter : System.Text.Json.Serialization.JsonConverter + internal class ResponsePropertyProductPropertyArraySystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter { public override Types.Result.Types.ProductProperty[]? Read(ref System.Text.Json.Utf8JsonReader reader, Type typeToConvert, System.Text.Json.JsonSerializerOptions options) { @@ -250,9 +250,9 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models.Platform /// 获取或设置抽取结果信息。 /// [Newtonsoft.Json.JsonProperty("entities")] - [Newtonsoft.Json.JsonConverter(typeof(Converters.NewtonsoftJsonProductPropertyArrayConverter))] + [Newtonsoft.Json.JsonConverter(typeof(Converters.ResponsePropertyProductPropertyArrayNewtonsoftJsonConverter))] [System.Text.Json.Serialization.JsonPropertyName("entities")] - [System.Text.Json.Serialization.JsonConverter(typeof(Converters.SystemTextJsonProductPropertyArrayConverter))] + [System.Text.Json.Serialization.JsonConverter(typeof(Converters.ResponsePropertyProductPropertyArraySystemTextJsonConverter))] public Types.Result Result { get; set; } = default!; } } diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/Platform_NLP/NLPSensitiveResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/Platform_NLP/NLPSensitiveResponse.cs index 620e0862..d289d9f2 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/Platform_NLP/NLPSensitiveResponse.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/Platform_NLP/NLPSensitiveResponse.cs @@ -31,7 +31,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models.Platform internal static class Converters { - internal class NewtonsoftJsonResultArrayConverter : Newtonsoft.Json.JsonConverter + internal class ResponsePropertyResultArrayNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter { public override bool CanRead { @@ -114,7 +114,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models.Platform } } - internal class SystemTextJsonResultArrayConverter : System.Text.Json.Serialization.JsonConverter + internal class ResponsePropertyResultArraySystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter { public override Types.Result[]? Read(ref System.Text.Json.Utf8JsonReader reader, Type typeToConvert, System.Text.Json.JsonSerializerOptions options) { @@ -193,9 +193,9 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models.Platform /// 获取或设置结果。 /// [Newtonsoft.Json.JsonProperty("result")] - [Newtonsoft.Json.JsonConverter(typeof(Converters.NewtonsoftJsonResultArrayConverter))] + [Newtonsoft.Json.JsonConverter(typeof(Converters.ResponsePropertyResultArrayNewtonsoftJsonConverter))] [System.Text.Json.Serialization.JsonPropertyName("result")] - [System.Text.Json.Serialization.JsonConverter(typeof(Converters.SystemTextJsonResultArrayConverter))] + [System.Text.Json.Serialization.JsonConverter(typeof(Converters.ResponsePropertyResultArraySystemTextJsonConverter))] public Types.Result[] ResultList { get; set; } = default!; } } diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/Platform_NLP/NLPSentimentResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/Platform_NLP/NLPSentimentResponse.cs index 11fe8c4c..b959711d 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/Platform_NLP/NLPSentimentResponse.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Models/Platform_NLP/NLPSentimentResponse.cs @@ -31,7 +31,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models.Platform internal static class Converters { - internal class NewtonsoftJsonResultArrayConverter : Newtonsoft.Json.JsonConverter + internal class ResponsePropertyResultArrayNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter { public override bool CanRead { @@ -114,7 +114,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models.Platform } } - internal class SystemTextJsonResultArrayConverter : System.Text.Json.Serialization.JsonConverter + internal class ResponsePropertyResultArraySystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter { public override Types.Result[]? Read(ref System.Text.Json.Utf8JsonReader reader, Type typeToConvert, System.Text.Json.JsonSerializerOptions options) { @@ -193,9 +193,9 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models.Platform /// 获取或设置结果。 /// [Newtonsoft.Json.JsonProperty("result")] - [Newtonsoft.Json.JsonConverter(typeof(Converters.NewtonsoftJsonResultArrayConverter))] + [Newtonsoft.Json.JsonConverter(typeof(Converters.ResponsePropertyResultArrayNewtonsoftJsonConverter))] [System.Text.Json.Serialization.JsonPropertyName("result")] - [System.Text.Json.Serialization.JsonConverter(typeof(Converters.SystemTextJsonResultArrayConverter))] + [System.Text.Json.Serialization.JsonConverter(typeof(Converters.ResponsePropertyResultArraySystemTextJsonConverter))] public Types.Result[] ResultList { get; set; } = default!; } } diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/README.md b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/README.md new file mode 100644 index 00000000..641992a4 --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/README.md @@ -0,0 +1,27 @@ +## SKIT.FlurlHttpClient.Wechat.OpenAI + +[![GitHub Stars](https://img.shields.io/github/stars/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat?logo=github&label=Stars)](https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat) [![GitHub Forks](https://img.shields.io/github/forks/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat?logo=github&label=Forks)](https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat) [![NuGet Download](https://img.shields.io/nuget/dt/SKIT.FlurlHttpClient.Wechat.OpenAI.svg?sanitize=true&label=Downloads)](https://www.nuget.org/packages/SKIT.FlurlHttpClient.Wechat.OpenAI) [![License](https://img.shields.io/github/license/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat?label=License)](https://mit-license.org/) + +基于 `Flurl.Http` 的微信对话开放平台 API 版客户端。 + +--- + +### 【功能特性】 + +- 基于微信对话开放平台 API 封装。 +- 支持平台接入、第三方接入两种模式。 +- 对于第三方接入,请求时自动生成加密参数,无需开发者手动干预。 +- 对于平台接入,请求时自动生成请求唯一标识,无需开发者手动干预。 +- 提供了解析回调通知事件等扩展方法。 + +--- + +### 【开发文档】 + +[点此查看](https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat)。 + +--- + +### 【更新日志】 + +[点此查看](https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat/blob/main/CHANGELOG.md)。 \ No newline at end of file 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 a6e31d69..645a8dbd 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/SKIT.FlurlHttpClient.Wechat.OpenAI.csproj +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/SKIT.FlurlHttpClient.Wechat.OpenAI.csproj @@ -9,6 +9,8 @@ SKIT.FlurlHttpClient.Wechat.OpenAI + LOGO.png + README.md MIT https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat Flurl.Http Wechat Weixin MicroMessage WechatAI WechatOpenAI WexinAI WeixinOpenAI 微信 微信智能对话 微信对话开放平台 微信智能对话开放平台 智能对话平台 @@ -17,18 +19,29 @@ Fu Diwei git https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat.git - true - true - snupkg + + true + true + true + true + true + snupkg + + + + + + + - + diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Utilities/SHA1Utility.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Utilities/SHA1Utility.cs index f2e1ae31..7e15e01b 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Utilities/SHA1Utility.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Utilities/SHA1Utility.cs @@ -10,7 +10,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Utilities public static class SHA1Utility { /// - /// 获取信息摘要。 + /// 获取 SHA-1 信息摘要。 /// /// 信息字节数组。 /// 信息摘要。 @@ -24,7 +24,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Utilities } /// - /// 获取信息摘要。 + /// 获取 SHA-1 信息摘要。 /// /// 文本信息。 /// 信息摘要。 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 0536d0f6..f452d823 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 @@ -1,8 +1,11 @@  - netcoreapp3.1; net6.0 - 9.0 + net472; netcoreapp3.1; net6.0 + latest + enable + true + false diff --git a/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/TestCase_CodeReviewAnalyzer.cs b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/TestCase_CodeReviewAnalyzer.cs new file mode 100644 index 00000000..61dee698 --- /dev/null +++ b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/TestCase_CodeReviewAnalyzer.cs @@ -0,0 +1,69 @@ +using System.IO; +using System.Reflection; +using Xunit; + +namespace SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests +{ + public class TestCase_CodeReviewAnalyzer + { + private Assembly SourceAssembly { get; } = Assembly.Load("SKIT.FlurlHttpClient.Wechat.OpenAI"); + + [Fact(DisplayName = "代码评审:分析 API 模型命名")] + public void TestApiModelsNaming() + { + CodeStyleUtil.VerifyApiModelsNaming(SourceAssembly, out var ex); + + if (ex != null) + throw ex; + + Assert.Null(ex); + } + + [Fact(DisplayName = "代码评审:分析 API 模型定义")] + public void TestApiModelsDefinition() + { + string workdir = Path.Combine(TestConfigs.ProjectTestDirectory, "ModelSamples"); + CodeStyleUtil.VerifyApiModelsDefinition(SourceAssembly, workdir, out var ex); + + if (ex != null) + throw ex; + + Assert.Null(ex); + } + + [Fact(DisplayName = "代码评审:分析 API 事件定义")] + public void TestApiEventsDefinition() + { + string workdir = Path.Combine(TestConfigs.ProjectTestDirectory, "EventSamples"); + CodeStyleUtil.VerifyApiEventsDefinition(SourceAssembly, workdir, out var ex); + + if (ex != null) + throw ex; + + Assert.Null(ex); + } + + [Fact(DisplayName = "代码评审:分析 API 接口命名")] + public void TestApiExtensionsNaming() + { + CodeStyleUtil.VerifyApiExtensionsNaming(SourceAssembly, out var ex); + + if (ex != null) + throw ex; + + Assert.Null(ex); + } + + [Fact(DisplayName = "代码评审:分析代码规范")] + public void TestCodeStyle() + { + string workdir = Path.Combine(TestConfigs.ProjectSourceDirectory); + CodeStyleUtil.VerifySourceCodeStyle(workdir, out var ex); + + if (ex != null) + throw ex; + + Assert.Null(ex); + } + } +} diff --git a/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/WechatOpenAIJWTTests.cs b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/TestCase_JWTUtilityTests.cs similarity index 82% rename from test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/WechatOpenAIJWTTests.cs rename to test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/TestCase_JWTUtilityTests.cs index 0b0009d6..fa1379df 100644 --- a/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/WechatOpenAIJWTTests.cs +++ b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/TestCase_JWTUtilityTests.cs @@ -1,17 +1,11 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Xunit; +using Xunit; namespace SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests { - public class WechatOpenAIJWTTests + public class TestCase_JWTUtilityTests { - [Fact(DisplayName = "JWT 编码(HS256)")] - public void JWTEncodeWithHS256Test() + [Fact(DisplayName = "测试用例:JWT HS256 编码")] + public void TestJWTEncodeWithHS256() { object payload = new { diff --git a/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/TestClients.cs b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/TestClients.cs index 744358d5..9fa4e136 100644 --- a/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/TestClients.cs +++ b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/TestClients.cs @@ -1,13 +1,11 @@ -using System; - -namespace SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests +namespace SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests { - class TestClients + internal class TestClients { static TestClients() { InstanceForPlatform = new WechatOpenAIPlatformClient(new WechatOpenAIPlatformClientOptions() - { + { 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 bd543053..c412f441 100644 --- a/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/TestConfigs.cs +++ b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/TestConfigs.cs @@ -4,12 +4,13 @@ using System.Text.Json; namespace SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests { - class TestConfigs + internal class TestConfigs { static TestConfigs() { - // NOTICE: 请在项目根目录下按照 appsettings.json 的格式新建 appsettings.local.json 填入测试参数。 - // WARN: 敏感信息请不要提交到 git! + // NOTICE: 请在项目根目录下按照 appsettings.json 的格式新建 appsettings.local.json 填入测试参数。 + // WARNING: 请在 DEBUG 模式下运行测试用例。 + // WARNING: 敏感信息请不要提交到 git! try { @@ -17,15 +18,15 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests using var jdoc = JsonDocument.Parse(stream); var config = jdoc.RootElement.GetProperty("TestConfig"); - 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(); + 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 = jdoc.RootElement.GetProperty("ProjectSourceDirectory").GetString(); - ProjectTestDirectory = jdoc.RootElement.GetProperty("ProjectTestDirectory").GetString(); + ProjectSourceDirectory = jdoc.RootElement.GetProperty("ProjectSourceDirectory").GetString()!; + ProjectTestDirectory = jdoc.RootElement.GetProperty("ProjectTestDirectory").GetString()!; } catch (Exception ex) { diff --git a/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/WechatOpenAIDeclarationTests.cs b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/WechatOpenAIDeclarationTests.cs deleted file mode 100644 index e131a135..00000000 --- a/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/WechatOpenAIDeclarationTests.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Threading; -using System.Threading.Tasks; -using Xunit; - -namespace SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests -{ - public class WechatOpenAIDeclarationTests - { - private static readonly Assembly _assembly = Assembly.Load("SKIT.FlurlHttpClient.Wechat.OpenAI"); - - [Fact(DisplayName = "验证 API 模型命名")] - public void ApiModelsNamingTest() - { - CodeStyleUtil.VerifyApiModelsNaming(_assembly, out var ex); - - if (ex != null) - throw ex; - - Assert.Null(ex); - } - - [Fact(DisplayName = "验证 API 模型定义")] - public void ApiModelsDefinitionTest() - { - string workdir = Path.Combine(TestConfigs.ProjectTestDirectory, "ModelSamples"); - CodeStyleUtil.VerifyApiModelsDefinition(_assembly, workdir, out var ex); - - if (ex != null) - throw ex; - - Assert.Null(ex); - } - - [Fact(DisplayName = "验证 API 事件定义")] - public void ApiEventsDefinitionTest() - { - string workdir = Path.Combine(TestConfigs.ProjectTestDirectory, "EventSamples"); - CodeStyleUtil.VerifyApiEventsDefinition(_assembly, workdir, out var ex); - - if (ex != null) - throw ex; - - Assert.Null(ex); - } - - [Fact(DisplayName = "验证 API 接口命名")] - public void ApiExtensionsNamingTest() - { - CodeStyleUtil.VerifyApiExtensionsNaming(_assembly, out var ex); - - if (ex != null) - throw ex; - - Assert.Null(ex); - } - - [Fact(DisplayName = "验证代码规范")] - public void CodeStyleTest() - { - string workdir = Path.Combine(TestConfigs.ProjectSourceDirectory); - CodeStyleUtil.VerifySourceCodeStyle(workdir, out var ex); - - if (ex != null) - throw ex; - - Assert.Null(ex); - } - } -}