mirror of
https://gitee.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat.git
synced 2025-09-18 17:48:12 +08:00
feat(openai): 新增 OpenAI v2 版接口客户端,并实现加解密及签名中间件
This commit is contained in:
@@ -15,6 +15,26 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests
|
||||
// 如果 Visual Studio 遇到 “缺少 SKIT.FlurlHttpClient.Tools.CodeAnalyzer 包” 的错误,
|
||||
// 请参考此 Issue:https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient/issues/8
|
||||
|
||||
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",
|
||||
IgnoreRequestModelTypes = (type) => !typeof(WechatOpenAIRequest).IsAssignableFrom(type),
|
||||
IgnoreResponseModelTypes = (type) => !typeof(WechatOpenAIResponse).IsAssignableFrom(type),
|
||||
IgnoreExecutingExtensionTypes = (type) => !type.Name.StartsWith(nameof(WechatOpenAIClient)),
|
||||
IgnoreWebhookEventTypes = (_) => true,
|
||||
ThrowOnNotFoundRequestModelTypes = true,
|
||||
ThrowOnNotFoundResponseModelTypes = true,
|
||||
ThrowOnNotFoundExecutingExtensionTypes = true
|
||||
};
|
||||
new TypeDeclarationAnalyzer(options).AssertNoIssues();
|
||||
}));
|
||||
|
||||
Assert.Null(Record.Exception(() =>
|
||||
{
|
||||
var options = new TypeDeclarationAnalyzerOptions()
|
||||
@@ -36,6 +56,35 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests
|
||||
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/"),
|
||||
ProjectSourceRequestModelClassCodeSubDirectory = "Models/OpenAI/",
|
||||
ProjectSourceResponseModelClassCodeSubDirectory = "Models/OpenAI/",
|
||||
ProjectSourceWebhookEventClassCodeSubDirectory = "Events/OpenAI/",
|
||||
ProjectTestRequestModelSerializationSampleSubDirectory = "ModelSamples/OpenAI/",
|
||||
ProjectTestResponseModelSerializationSampleSubDirectory = "ModelSamples/OpenAI/",
|
||||
ProjectTestWebhookEventSerializationSampleSubDirectory = "EventSamples/OpenAI/",
|
||||
IgnoreExecutingExtensionClassCodeFiles = (file) => !file.Name.StartsWith(nameof(WechatOpenAIClient)),
|
||||
ThrowOnNotFoundRequestModelClassCodeFiles = true,
|
||||
ThrowOnNotFoundResponseModelClassCodeFiles = true,
|
||||
ThrowOnNotFoundExecutingExtensionClassCodeFiles = true,
|
||||
ThrowOnNotFoundRequestModelSerializationSampleFiles = true,
|
||||
ThrowOnNotFoundResponseModelSerializationSampleFiles = true,
|
||||
};
|
||||
new SourceFileAnalyzer(options).AssertNoIssues();
|
||||
}));
|
||||
|
||||
Assert.Null(Record.Exception(() =>
|
||||
{
|
||||
string workdir = Environment.CurrentDirectory;
|
||||
@@ -55,6 +104,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests
|
||||
ProjectTestRequestModelSerializationSampleSubDirectory = "ModelSamples/Chatbot/",
|
||||
ProjectTestResponseModelSerializationSampleSubDirectory = "ModelSamples/Chatbot/",
|
||||
ProjectTestWebhookEventSerializationSampleSubDirectory = "EventSamples/Chatbot/",
|
||||
IgnoreExecutingExtensionClassCodeFiles = (file) => !file.Name.StartsWith(nameof(WechatChatbotClient)),
|
||||
ThrowOnNotFoundRequestModelClassCodeFiles = true,
|
||||
ThrowOnNotFoundResponseModelClassCodeFiles = true,
|
||||
ThrowOnNotFoundExecutingExtensionClassCodeFiles = true,
|
||||
|
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"account": "fb2ab07ce06"
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"code": 0,
|
||||
"data": {
|
||||
"access_token": "MX6ddM5mN07ucVKy+Y-to7tKRufZ1YF05eb542d5170000001c"
|
||||
},
|
||||
"msg": "success",
|
||||
"request_id": "54ae04cf-5e95-44fd-ad3f-62e7b163836b"
|
||||
}
|
@@ -9,7 +9,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests
|
||||
public async Task TestExecuteSign()
|
||||
{
|
||||
var request = new Models.SignRequest() { UserId = "TEST_USERID" };
|
||||
var response = await TestClients.Instance.ExecuteSignAsync(request);
|
||||
var response = await TestClients.ChatbotInstance.ExecuteSignAsync(request);
|
||||
|
||||
Assert.NotNull(response.Signature);
|
||||
}
|
||||
|
@@ -0,0 +1,17 @@
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests
|
||||
{
|
||||
public class TestCase_ApiExecuteTokenTests
|
||||
{
|
||||
[Fact(DisplayName = "测试用例:调用 API [POST] /v2/token")]
|
||||
public async Task TestExecuteTokenV2()
|
||||
{
|
||||
var request = new Models.TokenV2Request() { Account = "TEST_ACCOUNTID" };
|
||||
var response = await TestClients.OpenAIInstance.ExecuteTokenV2Async(request);
|
||||
|
||||
Assert.NotNull(response.Data?.AccessToken);
|
||||
}
|
||||
}
|
||||
}
|
@@ -10,7 +10,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests
|
||||
public void TestAESCBCEncryption()
|
||||
{
|
||||
string key = "q1Os1ZMe0nG28KUEx9lg3HjK7V5QyXvi212fzsgDqgz=";
|
||||
string iv = "q1Os1ZMe0nG28KUEx9lg3A=="; // iv 是 key 的前 16 个字节
|
||||
string iv = "q1Os1ZMe0nG28KUEx9lg3A==";
|
||||
string plainText = "{\"answer_type\":\"text\",\"text_info\":{\"short_answer\":\"answer\"}}";
|
||||
|
||||
string expectedCipherData = "aJhHfz6xc9iQiTLwusQe0HYKT6itYwq/YgQHltmLPf2UfpD+8ODJ8lrrxOMxy5NiALZqz1eYGtwD7cLQDP3ADg==";
|
||||
@@ -23,7 +23,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests
|
||||
public void TestAESCBCDecryption()
|
||||
{
|
||||
string key = "q1Os1ZMe0nG28KUEx9lg3HjK7V5QyXvi212fzsgDqgz=";
|
||||
string iv = "q1Os1ZMe0nG28KUEx9lg3A=="; // iv 是 key 的前 16 个字节
|
||||
string iv = "q1Os1ZMe0nG28KUEx9lg3A==";
|
||||
string cipherText = "rUWkvTY9vRPOeVDSH/IdNXHmvgsUQtPkp7QtBQjSS1tcuTHGPWv8O3PlxbnsjCogsM7+EY+As4yF2kp4yxXpP2U7RmbDsU/luRO/EqkpFFsoxMZZArz2XH1YeSdnDyHYPWzjiicBYjNiqqpTMX8ekrqooN0cCEH7JBcbEe6btmiK8hZkysKTUJfG1DTpbONxON5+YuVPelVpzW5ry9sRYLDcqhImMb9FqI+BlIVAIXt5g+e70rheSqpeXz98pEROx7yPeRi3tXPAibuwg+vKDhoN6LuM0hzvyNzPjwK2gMmQB5yVuBZUalYIIZTVaMNGu4H6RK6MovLyM2cKfMUTphKaBBKpAvsV0o4/QRY0MvxeRYvZAQXEzOG3dJ7BRB2KEqBKttT7jMK8MO5HEXDE0CJxtNI4Rjww9XYmPhBM7lOZSF97YNEg1NhwcXvUc3YcrR334PhWJeu2dZCHaJzBqVXFxq/WprNHM0Gw06o6p5oWb4/nzXKYbpJWDyqTN/aztwo5sppHwlYrzNzF7gERP691qoabTHiCd0H+Ea3t65gTyNo2+ssvS1RVsKubApS4BkbZb/EaZCTKP20pcvDBoJk3QLi8ObyBq8sIcLwVjzelLMUgCDa059gBuao+S9qdHXebEZyS49BqAxngMWjHU5uCRO/x2b9w8nwfCCT8b0Q=";
|
||||
|
||||
string expectedPlainData = "{\"RequestId\":\"123123456456789789123456789\",\"SessionId\":\"12345678901234567_12345678909876543\",\"Query\":\"北京限行尾号是多少\",\"SkillName\":\"限行\",\"IntentName\":\"查限行尾号\",\"Slots\":[{\"SlotName\":\"from_loc\",\"SlotValue\":\"北京\",\"NormalizeValue\":\"{\\\"type\\\":\\\"LOC_CHINA_CITY\\\",\\\"city\\\":\\\"北京市\\\",\\\"city_simple\\\":\\\"北京\\\",\\\"loc_ori\\\":\\\"北京\\\"}\"}],\"Timestamp\":1704135845,\"Signature\":\"96f439043e1f7d2bb38162e35406f173\",\"ThirdApiId\":1234,\"ThirdApiName\":\"车辆限行\",\"UserId\":\"97f7e892\"}";
|
||||
|
@@ -4,7 +4,13 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests
|
||||
{
|
||||
static TestClients()
|
||||
{
|
||||
Instance = new WechatChatbotClient(new WechatChatbotClientOptions()
|
||||
OpenAIInstance = new WechatOpenAIClient(new WechatOpenAIClientOptions()
|
||||
{
|
||||
AppId = TestConfigs.WechatAppId,
|
||||
Token = TestConfigs.WechatToken,
|
||||
EncodingAESKey = TestConfigs.WechatEncodingAESKey
|
||||
});
|
||||
ChatbotInstance = new WechatChatbotClient(new WechatChatbotClientOptions()
|
||||
{
|
||||
AppId = TestConfigs.WechatAppId,
|
||||
Token = TestConfigs.WechatToken,
|
||||
@@ -12,6 +18,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests
|
||||
});
|
||||
}
|
||||
|
||||
public static readonly WechatChatbotClient Instance;
|
||||
public static readonly WechatOpenAIClient OpenAIInstance;
|
||||
public static readonly WechatChatbotClient ChatbotInstance;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user