mirror of
https://gitee.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat.git
synced 2025-04-05 17:37:54 +08:00
feat(openai): 升级公共组件
This commit is contained in:
parent
5a110785f8
commit
fcc5e91510
@ -4,7 +4,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Events
|
||||
/// <para>表示 userEnter 事件的数据。</para>
|
||||
/// <para>REF: https://developers.weixin.qq.com/doc/aispeech/confapi/thirdkefu/recivemsg.html </para>
|
||||
/// </summary>
|
||||
public class UserEnterEvent : WechatOpenAIEvent, WechatOpenAIEvent.Serialization.IXmlSerializable
|
||||
public class UserEnterEvent : WechatOpenAIEvent
|
||||
{
|
||||
public static class Types
|
||||
{
|
||||
|
@ -1,24 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Exceptions
|
||||
{
|
||||
public class WechatOpenAIEventSerializationException : WechatOpenAIException
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
internal WechatOpenAIEventSerializationException()
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal WechatOpenAIEventSerializationException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal WechatOpenAIEventSerializationException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Exceptions
|
||||
{
|
||||
public class WechatOpenAIRequestTimeoutException : WechatOpenAIException
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
internal WechatOpenAIRequestTimeoutException()
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal WechatOpenAIRequestTimeoutException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal WechatOpenAIRequestTimeoutException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -7,19 +7,19 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI
|
||||
/// </summary>
|
||||
public static class WechatOpenAIClientEventExtensions
|
||||
{
|
||||
private static TEvent InnerDeserializeEventFromXml<TEvent>(this WechatOpenAIClient client, string callbackXml)
|
||||
private static TEvent InnerDeserializeEventFromXml<TEvent>(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<TEvent>(callbackXml);
|
||||
webhookXml = Utilities.WxMsgCryptor.AESDecrypt(cipherText: encryptedXml!, encodingAESKey: client.Credentials.EncodingAESKey!, out _);
|
||||
return Utilities.XmlHelper.Deserialize<TEvent>(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
|
||||
/// </summary>
|
||||
/// <typeparam name="TEvent"></typeparam>
|
||||
/// <param name="client"></param>
|
||||
/// <param name="callbackXml"></param>
|
||||
/// <param name="webhookXml"></param>
|
||||
/// <returns></returns>
|
||||
public static TEvent DeserializeEventFromXml<TEvent>(this WechatOpenAIClient client, string callbackXml)
|
||||
where TEvent : WechatOpenAIEvent, WechatOpenAIEvent.Serialization.IXmlSerializable, new()
|
||||
public static TEvent DeserializeEventFromXml<TEvent>(this WechatOpenAIClient client, string webhookXml)
|
||||
where TEvent : WechatOpenAIEvent, new()
|
||||
{
|
||||
return InnerDeserializeEventFromXml<TEvent>(client, callbackXml);
|
||||
return InnerDeserializeEventFromXml<TEvent>(client, webhookXml);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>从 XML 反序列化得到 <see cref="WechatOpenAIEvent"/> 对象。</para>
|
||||
/// </summary>
|
||||
/// <param name="client"></param>
|
||||
/// <param name="callbackXml"></param>
|
||||
/// <param name="webhookXml"></param>
|
||||
/// <returns></returns>
|
||||
public static WechatOpenAIEvent DeserializeEventFromXml(this WechatOpenAIClient client, string callbackXml)
|
||||
public static WechatOpenAIEvent DeserializeEventFromXml(this WechatOpenAIClient client, string webhookXml)
|
||||
{
|
||||
return InnerDeserializeEventFromXml<WechatOpenAIEvent>(client, callbackXml);
|
||||
return InnerDeserializeEventFromXml<WechatOpenAIEvent>(client, webhookXml);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -60,26 +60,26 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI
|
||||
/// </summary>
|
||||
/// <typeparam name="TEvent"></typeparam>
|
||||
/// <param name="client"></param>
|
||||
/// <param name="callbackModel"></param>
|
||||
/// <param name="webhookEvent"></param>
|
||||
/// <returns></returns>
|
||||
public static string SerializeEventToXml<TEvent>(this WechatOpenAIClient client, TEvent callbackModel)
|
||||
where TEvent : WechatOpenAIEvent, WechatOpenAIEvent.Serialization.IXmlSerializable, new()
|
||||
public static string SerializeEventToXml<TEvent>(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;
|
||||
|
@ -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<Models.BatchImportSkillResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.BatchImportSkillResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -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<Models.PublishResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.PublishResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -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<Models.PublishProgressResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.PublishProgressResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -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<Models.SetAutoReplyResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.SetAutoReplyResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -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<Models.LabelBatchSetResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.LabelBatchSetResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<Models.SignResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.SignResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -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<Models.AIBotResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.AIBotResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -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<Models.FeedbackResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.FeedbackResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -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<Models.GetHotQueryListResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.GetHotQueryListResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -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<Models.GetHotQueryDetailResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.GetHotQueryDetailResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<Models.GetBindLinkResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.GetBindLinkResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -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<Models.GetBindListResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.GetBindListResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -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<Models.UnbindMpResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.UnbindMpResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -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<Models.GetH5LinkResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.GetH5LinkResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -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<byte>());
|
||||
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<Models.AssetsUploadResponse>(flurlReq, httpContent: httpContent, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsync<Models.AssetsUploadResponse>(flurlReq, httpContent: httpContent, cancellationToken: cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<Models.SendMessageResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.SendMessageResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -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<Models.KefuStateGetResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.KefuStateGetResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -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<Models.KefuStateChangeResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
return await client.SendFlurlRequestAsJsonAsync<Models.KefuStateChangeResponse>(flurlReq, data: request, cancellationToken: cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("confidence")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("confidence")]
|
||||
public float Confidence { get; set; } = default!;
|
||||
public decimal Confidence { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置消息类型。
|
||||
@ -156,7 +156,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models
|
||||
/// </summary>
|
||||
[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
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("confidence")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("confidence")]
|
||||
public double Confidence { get; set; }
|
||||
public decimal Confidence { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置发起查询的用户 ID。
|
||||
|
@ -46,7 +46,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("score")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("score")]
|
||||
public double Score { get; set; }
|
||||
public decimal Score { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("score")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("score")]
|
||||
public double Score { get; set; }
|
||||
public decimal Score { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,45 +46,45 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Models
|
||||
/// 获取或设置是否开通微信门店功能。
|
||||
/// </summary>
|
||||
[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; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置是否开通微信扫商品功能。
|
||||
/// </summary>
|
||||
[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; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置是否开通微信支付功能。
|
||||
/// </summary>
|
||||
[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; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置是否开通微信卡券功能。
|
||||
/// </summary>
|
||||
[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; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置是否开通微信摇一摇功能。
|
||||
/// </summary>
|
||||
[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; }
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net461; netstandard2.0; net6.0</TargetFrameworks>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
<LangVersion>10.0</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<NullableReferenceTypes>true</NullableReferenceTypes>
|
||||
</PropertyGroup>
|
||||
@ -14,7 +14,7 @@
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<PackageProjectUrl>https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat</PackageProjectUrl>
|
||||
<PackageTags>Flurl.Http Wechat Weixin MicroMessage WechatAI WechatOpenAI WexinAI WeixinOpenAI 微信 微信智能对话 微信对话开放平台 微信智能对话开放平台 智能对话平台</PackageTags>
|
||||
<Version>2.0.1</Version>
|
||||
<Version>3.0.0-preview.1</Version>
|
||||
<Description>基于 Flurl.Http 的微信对话开放平台(微信智能对话) API 客户端,支持智能对话接口、第三方客服接入、机器人配置、公众号/小程序/H5 绑定等功能。</Description>
|
||||
<Authors>Fu Diwei</Authors>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
@ -40,7 +40,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SKIT.FlurlHttpClient.Common" Version="2.6.0" />
|
||||
<PackageReference Include="SKIT.FlurlHttpClient.Common" Version="3.0.0-preview.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -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;
|
||||
|
@ -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>(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<T>(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;
|
||||
}
|
||||
}
|
||||
}
|
@ -16,7 +16,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Utilities
|
||||
/// <returns>信息摘要字节数组。</returns>
|
||||
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
|
||||
/// <returns>信息摘要。</returns>
|
||||
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);
|
||||
|
@ -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
|
||||
/// <returns>解密后的文本内容。</returns>
|
||||
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
|
||||
/// <returns>加密后的文本内容。</returns>
|
||||
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
|
||||
/// <returns>验证结果。</returns>
|
||||
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
|
||||
/// <returns>签名。</returns>
|
||||
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<string> tmp = new List<string>(capacity: 4) { sToken, sTimestamp, sNonce, sMsgEncrypt };
|
||||
tmp.Sort(StringComparer.Ordinal);
|
||||
@ -257,7 +257,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Utilities
|
||||
/// <returns>指示是否是有效的 XML 内容。</returns>
|
||||
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
|
||||
/// <returns></returns>
|
||||
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
|
||||
/// <returns></returns>
|
||||
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("<xml>");
|
@ -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>(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<T>(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;
|
||||
}
|
||||
}
|
||||
}
|
@ -21,42 +21,37 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI
|
||||
/// </summary>
|
||||
/// <param name="options">配置项。</param>
|
||||
public WechatOpenAIClient(WechatOpenAIClientOptions options)
|
||||
: base()
|
||||
: this(options, null)
|
||||
{
|
||||
if (options == null) throw new ArgumentNullException(nameof(options));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="options"></param>
|
||||
/// <param name="httpClient"></param>
|
||||
/// <param name="disposeClient"></param>
|
||||
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));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 用指定的微信智能对话 AppId、Token、EncodingAESKey 初始化 <see cref="WechatOpenAIThirdPartyClient"/> 类的新实例。
|
||||
/// </summary>
|
||||
/// <param name="appId">微信智能对话 AppId。</param>
|
||||
/// <param name="token">微信智能对话 Token。</param>
|
||||
/// <param name="encodingAESKey">微信智能对话 EncodingAESKey。</param>
|
||||
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));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 使用当前客户端生成一个新的 <see cref="IFlurlRequest"/> 对象。
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="method"></param>
|
||||
/// <param name="httpMethod"></param>
|
||||
/// <param name="urlSegments"></param>
|
||||
/// <returns></returns>
|
||||
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
|
||||
/// <param name="httpContent"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<T> SendRequestAsync<T>(IFlurlRequest flurlRequest, HttpContent? httpContent = null, CancellationToken cancellationToken = default)
|
||||
public async Task<T> SendFlurlRequestAsync<T>(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<T>(flurlResponse, cancellationToken);
|
||||
}
|
||||
catch (FlurlHttpException ex)
|
||||
{
|
||||
throw new WechatOpenAIException(ex.Message, ex);
|
||||
}
|
||||
using IFlurlResponse flurlResponse = await base.SendFlurlRequestAsync(flurlRequest, httpContent, cancellationToken);
|
||||
return await WrapFlurlResponseAsJsonAsync<T>(flurlResponse, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -93,37 +81,26 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI
|
||||
/// <param name="data"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<T> SendRequestWithJsonAsync<T>(IFlurlRequest flurlRequest, object? data = null, CancellationToken cancellationToken = default)
|
||||
public async Task<T> SendFlurlRequestAsJsonAsync<T>(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<T>(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<T>(flurlResponse, cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,38 +1,27 @@
|
||||
using System;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace SKIT.FlurlHttpClient.Wechat.OpenAI
|
||||
{
|
||||
/// <summary>
|
||||
/// 表示微信智能对话 API 回调通知事件的基类。
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class WechatOpenAIEvent
|
||||
[System.Xml.Serialization.XmlRoot("xml")]
|
||||
public class WechatOpenAIEvent : ICommonWebhookEvent
|
||||
{
|
||||
public static class Serialization
|
||||
{
|
||||
[XmlRoot("xml")]
|
||||
public interface IXmlSerializable
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置 AppId。
|
||||
/// </summary>
|
||||
[XmlElement("appid", IsNullable = true)]
|
||||
[System.Xml.Serialization.XmlElement("appid", IsNullable = true)]
|
||||
public string? AppId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置事件类型。
|
||||
/// </summary>
|
||||
[XmlElement("event", IsNullable = true)]
|
||||
[System.Xml.Serialization.XmlElement("event", IsNullable = true)]
|
||||
public string? Event { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置消息创建时间戳。
|
||||
/// </summary>
|
||||
[XmlElement("createtime", IsNullable = true)]
|
||||
[System.Xml.Serialization.XmlElement("createtime", IsNullable = true)]
|
||||
public long? CreateTimestamp { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
using System;
|
||||
using System;
|
||||
|
||||
namespace SKIT.FlurlHttpClient.Wechat.OpenAI
|
||||
{
|
||||
/// <summary>
|
||||
/// 当调用微信智能对话 API 出错时引发的异常。
|
||||
/// </summary>
|
||||
public class WechatOpenAIException : CommonExceptionBase
|
||||
public class WechatOpenAIException : CommonException
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public WechatOpenAIException()
|
||||
|
@ -3,7 +3,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI
|
||||
/// <summary>
|
||||
/// 表示微信智能对话 API 请求的基类。
|
||||
/// </summary>
|
||||
public abstract class WechatOpenAIRequest : ICommonRequest
|
||||
public abstract class WechatOpenAIRequest : CommonRequestBase, ICommonRequest
|
||||
{
|
||||
public static class Serialization
|
||||
{
|
||||
@ -11,14 +11,5 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置请求超时时间(单位:毫秒)。如果不指定将使用构造 <see cref="WechatOpenAIClient"/> 时的 <see cref="WechatOpenAIClientOptions.Timeout"/> 参数,这在需要指定特定耗时请求(比如上传或下载文件)的超时时间时很有用。
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonIgnore]
|
||||
[System.Text.Json.Serialization.JsonIgnore]
|
||||
[System.Xml.Serialization.XmlIgnore]
|
||||
[System.Xml.Serialization.SoapIgnore]
|
||||
public virtual int? Timeout { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -1,60 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SKIT.FlurlHttpClient.Wechat.OpenAI
|
||||
{
|
||||
/// <summary>
|
||||
/// 表示微信智能对话 API 响应的基类。
|
||||
/// </summary>
|
||||
public abstract class WechatOpenAIResponse : ICommonResponse
|
||||
public abstract class WechatOpenAIResponse : CommonResponseBase, ICommonResponse
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
int ICommonResponse.RawStatus { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
IDictionary<string, string> ICommonResponse.RawHeaders { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
byte[] ICommonResponse.RawBytes { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 获取原始的 HTTP 响应状态码。
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonIgnore]
|
||||
[System.Text.Json.Serialization.JsonIgnore]
|
||||
public int RawStatus
|
||||
{
|
||||
get { return ((ICommonResponse)this).RawStatus; }
|
||||
internal set { ((ICommonResponse)this).RawStatus = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取原始的 HTTP 响应表头集合。
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonIgnore]
|
||||
[System.Text.Json.Serialization.JsonIgnore]
|
||||
public IDictionary<string, string> RawHeaders
|
||||
{
|
||||
get { return ((ICommonResponse)this).RawHeaders; }
|
||||
internal set { ((ICommonResponse)this).RawHeaders = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取原始的 HTTP 响应正文。
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonIgnore]
|
||||
[System.Text.Json.Serialization.JsonIgnore]
|
||||
public byte[] RawBytes
|
||||
{
|
||||
get { return ((ICommonResponse)this).RawBytes; }
|
||||
internal set { ((ICommonResponse)this).RawBytes = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取微信智能对话 API 返回的错误码。
|
||||
/// </summary>
|
||||
@ -84,12 +34,15 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI
|
||||
public virtual string? ReturnError { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个值,该值指示调用微信 API 是否成功(即 HTTP 状态码为 200、且 errcode/ret 值都为 0)。
|
||||
/// 获取一个值,该值指示调用微信 API 是否成功。
|
||||
/// <para>
|
||||
/// (即 HTTP 状态码为 200,且 <see cref="ErrorCode"/>、<see cref="ReturnCode"/> 值都为 0)
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
@ -10,23 +10,23 @@
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove=".gitignore" />
|
||||
<Content Include="appsettings.json">
|
||||
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
|
||||
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="appsettings.*.json" Condition="'$(Configuration)' == 'Debug'">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="appsettings.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="appsettings.*.json" Condition="'$(Configuration)' == 'Debug'">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<CopyToPublishDirectory>Always</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="ModelSamples/**/*.json" />
|
||||
<Content Include="EventSamples/**/*.xml" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.0" />
|
||||
<PackageReference Include="SKIT.FlurlHttpClient.Tools.CodeAnalyzer" Version="0.1.0-alpha.1" />
|
||||
<PackageReference Include="xunit" Version="2.4.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
|
||||
<PackageReference Include="SKIT.FlurlHttpClient.Tools.CodeAnalyzer" Version="0.3.0-preview.1" />
|
||||
<PackageReference Include="xunit" Version="2.6.6" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.6">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
@ -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();
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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\\"
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user