feat(wxapi): 升级公共组件

This commit is contained in:
Fu Diwei 2022-01-21 16:57:42 +08:00
parent 782504def6
commit 5650e3be25
62 changed files with 523 additions and 939 deletions

View File

@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Newtonsoft.Json.Converters
{
internal class TextualStringArrayWithPipeSplitConverter : JsonConverter<string[]?>
{
public override bool CanRead
{
get { return true; }
}
public override bool CanWrite
{
get { return true; }
}
public override string[]? ReadJson(JsonReader reader, Type objectType, string[]? existingValue, bool hasExistingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
{
return null;
}
else if (reader.TokenType == JsonToken.String)
{
string? value = serializer.Deserialize<string>(reader);
if (value == null)
return null;
if (string.IsNullOrEmpty(value))
return Array.Empty<string>();
return value.Split('|');
}
throw new JsonSerializationException();
}
public override void WriteJson(JsonWriter writer, string[]? value, JsonSerializer serializer)
{
if (value != null)
writer.WriteValue(string.Join("|", value));
else
writer.WriteNull();
}
}
}

View File

@ -4,7 +4,7 @@ using System.Linq;
namespace Newtonsoft.Json.Converters namespace Newtonsoft.Json.Converters
{ {
internal class TextualStringListWithSemicolonConverter : JsonConverter<List<string>?> internal class TextualStringArrayWithSemicolonSplitConverter : JsonConverter<string[]?>
{ {
public override bool CanRead public override bool CanRead
{ {
@ -16,7 +16,7 @@ namespace Newtonsoft.Json.Converters
get { return true; } get { return true; }
} }
public override List<string>? ReadJson(JsonReader reader, Type objectType, List<string>? existingValue, bool hasExistingValue, JsonSerializer serializer) public override string[]? ReadJson(JsonReader reader, Type objectType, string[]? existingValue, bool hasExistingValue, JsonSerializer serializer)
{ {
if (reader.TokenType == JsonToken.Null) if (reader.TokenType == JsonToken.Null)
{ {
@ -26,15 +26,17 @@ namespace Newtonsoft.Json.Converters
{ {
string? value = serializer.Deserialize<string>(reader); string? value = serializer.Deserialize<string>(reader);
if (value == null) if (value == null)
return existingValue; return null;
if (string.IsNullOrEmpty(value))
return Array.Empty<string>();
return value.Split(';').ToList(); return value.Split(';');
} }
throw new JsonReaderException(); throw new JsonSerializationException();
} }
public override void WriteJson(JsonWriter writer, List<string>? value, JsonSerializer serializer) public override void WriteJson(JsonWriter writer, string[]? value, JsonSerializer serializer)
{ {
if (value != null) if (value != null)
writer.WriteValue(string.Join(";", value)); writer.WriteValue(string.Join(";", value));

View File

@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Newtonsoft.Json.Converters
{
internal class TextualStringListWithPipeSplitConverter : JsonConverter
{
private readonly JsonConverter<string[]?> _converter = new TextualStringArrayWithPipeSplitConverter();
public override bool CanConvert(Type objectType)
{
return objectType.IsGenericType &&
typeof(IList<>).IsAssignableFrom(objectType.GetGenericTypeDefinition()) &&
typeof(string) == objectType.GetGenericArguments()[0];
}
public override bool CanRead
{
get { return true; }
}
public override bool CanWrite
{
get { return true; }
}
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
{
string[]? array = _converter.ReadJson(reader, objectType, null, false, serializer);
return array?.ToList();
}
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
{
_converter.WriteJson(writer, ((IList<string>?)value)?.ToArray(), serializer);
}
}
}

View File

@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Newtonsoft.Json.Converters
{
internal class TextualStringListWithSemicolonSplitConverter : JsonConverter
{
private readonly JsonConverter<string[]?> _converter = new TextualStringArrayWithSemicolonSplitConverter();
public override bool CanConvert(Type objectType)
{
return objectType.IsGenericType &&
typeof(IList<>).IsAssignableFrom(objectType.GetGenericTypeDefinition()) &&
typeof(string) == objectType.GetGenericArguments()[0];
}
public override bool CanRead
{
get { return true; }
}
public override bool CanWrite
{
get { return true; }
}
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
{
string[]? array = _converter.ReadJson(reader, objectType, null, false, serializer);
return array?.ToList();
}
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
{
_converter.WriteJson(writer, ((IList<string>?)value)?.ToArray(), serializer);
}
}
}

View File

@ -4,9 +4,9 @@ using System.Text.Json.Serialization;
namespace System.Text.Json.Converters namespace System.Text.Json.Converters
{ {
internal class TextualInt32ListConverter : JsonConverter<List<int>?> internal class TextualStringArrayWithPipeSplitConverter : JsonConverter<string[]?>
{ {
public override List<int>? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) public override string[]? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{ {
if (reader.TokenType == JsonTokenType.Null) if (reader.TokenType == JsonTokenType.Null)
{ {
@ -17,24 +17,19 @@ namespace System.Text.Json.Converters
string? value = reader.GetString(); string? value = reader.GetString();
if (value == null) if (value == null)
return null; return null;
if (string.IsNullOrEmpty(value))
return Array.Empty<string>();
try return value.Split('|');
{
return value.Split(',').Select(e => int.Parse(e.Trim())).ToList();
}
catch (Exception ex)
{
throw new JsonException(ex.Message, ex);
}
} }
throw new JsonException(); throw new JsonException();
} }
public override void Write(Utf8JsonWriter writer, List<int>? value, JsonSerializerOptions options) public override void Write(Utf8JsonWriter writer, string[]? value, JsonSerializerOptions options)
{ {
if (value != null) if (value != null)
writer.WriteStringValue(string.Join(",", value)); writer.WriteStringValue(string.Join("|", value));
else else
writer.WriteNullValue(); writer.WriteNullValue();
} }

View File

@ -4,9 +4,9 @@ using System.Text.Json.Serialization;
namespace System.Text.Json.Converters namespace System.Text.Json.Converters
{ {
internal class TextualStringListWithSemicolonConverter : JsonConverter<List<string>?> internal class TextualStringArrayWithSemicolonSplitConverter : JsonConverter<string[]?>
{ {
public override List<string>? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) public override string[]? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{ {
if (reader.TokenType == JsonTokenType.Null) if (reader.TokenType == JsonTokenType.Null)
{ {
@ -17,14 +17,16 @@ namespace System.Text.Json.Converters
string? value = reader.GetString(); string? value = reader.GetString();
if (value == null) if (value == null)
return null; return null;
if (string.IsNullOrEmpty(value))
return Array.Empty<string>();
return value.Split(';').ToList(); return value.Split(';');
} }
throw new JsonException(); throw new JsonException();
} }
public override void Write(Utf8JsonWriter writer, List<string>? value, JsonSerializerOptions options) public override void Write(Utf8JsonWriter writer, string[]? value, JsonSerializerOptions options)
{ {
if (value != null) if (value != null)
writer.WriteStringValue(string.Join(";", value)); writer.WriteStringValue(string.Join(";", value));

View File

@ -0,0 +1,38 @@
using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Serialization;
namespace System.Text.Json.Converters
{
internal class TextualStringListWithPipeSplitConverter : JsonConverterFactory
{
private sealed class InnerTextualStringListWithPipeSplitConverter : JsonConverter<IList<string>?>
{
private readonly JsonConverter<string[]?> _converter = new TextualStringArrayWithPipeSplitConverter();
public override IList<string>? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
string[]? array = _converter.Read(ref reader, typeToConvert, options);
IList<string>? list = array?.ToList();
return list;
}
public override void Write(Utf8JsonWriter writer, IList<string>? value, JsonSerializerOptions options)
{
_converter.Write(writer, value?.ToArray(), options);
}
}
public override bool CanConvert(Type typeToConvert)
{
return typeToConvert.IsGenericType &&
typeof(IList<>).IsAssignableFrom(typeToConvert.GetGenericTypeDefinition()) &&
typeof(string) == typeToConvert.GetGenericArguments()[0];
}
public override JsonConverter? CreateConverter(Type typeToConvert, JsonSerializerOptions options)
{
return new InnerTextualStringListWithPipeSplitConverter();
}
}
}

View File

@ -0,0 +1,38 @@
using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Serialization;
namespace System.Text.Json.Converters
{
internal class TextualStringListWithSemicolonSplitConverter : JsonConverterFactory
{
private sealed class InnerTextualStringListWithSemicolonSplitConverter : JsonConverter<IList<string>?>
{
private readonly JsonConverter<string[]?> _converter = new TextualStringArrayWithSemicolonSplitConverter();
public override IList<string>? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
string[]? array = _converter.Read(ref reader, typeToConvert, options);
IList<string>? list = array?.ToList();
return list;
}
public override void Write(Utf8JsonWriter writer, IList<string>? value, JsonSerializerOptions options)
{
_converter.Write(writer, value?.ToArray(), options);
}
}
public override bool CanConvert(Type typeToConvert)
{
return typeToConvert.IsGenericType &&
typeof(IList<>).IsAssignableFrom(typeToConvert.GetGenericTypeDefinition()) &&
typeof(string) == typeToConvert.GetGenericArguments()[0];
}
public override JsonConverter? CreateConverter(Type typeToConvert, JsonSerializerOptions options)
{
return new InnerTextualStringListWithSemicolonSplitConverter();
}
}
}

View File

@ -1,31 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Newtonsoft.Json.Converters
{
internal class TextualStringArrayWithSemicolonConverter : JsonConverter<string[]?>
{
private readonly JsonConverter<List<string>?> _converter = new TextualStringListWithSemicolonConverter();
public override bool CanRead
{
get { return true; }
}
public override bool CanWrite
{
get { return true; }
}
public override string[]? ReadJson(JsonReader reader, Type objectType, string[]? existingValue, bool hasExistingValue, JsonSerializer serializer)
{
return _converter.ReadJson(reader, objectType, existingValue?.ToList(), hasExistingValue, serializer)?.ToArray();
}
public override void WriteJson(JsonWriter writer, string[]? value, JsonSerializer serializer)
{
_converter.WriteJson(writer, value?.ToList(), serializer);
}
}
}

View File

@ -1,42 +0,0 @@
using System;
using System.Collections.Generic;
namespace Newtonsoft.Json.Converters
{
internal class TextualInt32IListConverter : JsonConverter<IList<int>?>
{
private readonly JsonConverter<List<int>?> _converter = new TextualInt32ListConverter();
public override bool CanRead
{
get { return true; }
}
public override bool CanWrite
{
get { return true; }
}
public override IList<int>? ReadJson(JsonReader reader, Type objectType, IList<int>? existingValue, bool hasExistingValue, JsonSerializer serializer)
{
return _converter.ReadJson(reader, objectType, ConvertIListToList(existingValue), hasExistingValue, serializer);
}
public override void WriteJson(JsonWriter writer, IList<int>? value, JsonSerializer serializer)
{
_converter.WriteJson(writer, ConvertIListToList(value), serializer);
}
private List<int>? ConvertIListToList(IList<int>? src)
{
if (src == null)
return null;
List<int>? dest = src as List<int>;
if (dest != null)
return dest;
return new List<int>(src);
}
}
}

View File

@ -1,52 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Newtonsoft.Json.Converters
{
internal class TextualInt32ListConverter : JsonConverter<List<int>?>
{
public override bool CanRead
{
get { return true; }
}
public override bool CanWrite
{
get { return true; }
}
public override List<int>? ReadJson(JsonReader reader, Type objectType, List<int>? existingValue, bool hasExistingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
{
return null;
}
else if (reader.TokenType == JsonToken.String)
{
string? value = serializer.Deserialize<string>(reader);
if (value == null)
return existingValue;
try
{
return value.Split(',').Select(e => int.Parse(e.Trim())).ToList();
}
catch (Exception ex)
{
throw new JsonReaderException(ex.Message, ex);
}
}
throw new JsonReaderException();
}
public override void WriteJson(JsonWriter writer, List<int>? value, JsonSerializer serializer)
{
if (value != null)
writer.WriteValue(string.Join(",", value));
else
writer.WriteNull();
}
}
}

View File

@ -1,42 +0,0 @@
using System;
using System.Collections.Generic;
namespace Newtonsoft.Json.Converters
{
internal class TextualStringIListWithSemicolonConverter : JsonConverter<IList<string>?>
{
private readonly JsonConverter<List<string>?> _converter = new TextualStringListWithSemicolonConverter();
public override bool CanRead
{
get { return true; }
}
public override bool CanWrite
{
get { return true; }
}
public override IList<string>? ReadJson(JsonReader reader, Type objectType, IList<string>? existingValue, bool hasExistingValue, JsonSerializer serializer)
{
return _converter.ReadJson(reader, objectType, ConvertIListToList(existingValue), hasExistingValue, serializer);
}
public override void WriteJson(JsonWriter writer, IList<string>? value, JsonSerializer serializer)
{
_converter.WriteJson(writer, ConvertIListToList(value), serializer);
}
private List<string>? ConvertIListToList(IList<string>? src)
{
if (src == null)
return null;
List<string>? dest = src as List<string>;
if (dest != null)
return dest;
return new List<string>(src);
}
}
}

View File

@ -1,21 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Serialization;
namespace System.Text.Json.Converters
{
internal class TextualStringArrayWithSemicolonConverter : JsonConverter<string[]?>
{
private readonly JsonConverter<List<string>?> _converter = new TextualStringListWithSemicolonConverter();
public override string[]? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return _converter.Read(ref reader, typeToConvert, options)?.ToArray();
}
public override void Write(Utf8JsonWriter writer, string[]? value, JsonSerializerOptions options)
{
_converter.Write(writer, value?.ToList(), options);
}
}
}

View File

@ -1,32 +0,0 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
namespace System.Text.Json.Converters
{
internal class TextualInt32IListConverter : JsonConverter<IList<int>?>
{
private readonly JsonConverter<List<int>?> _converter = new TextualInt32ListConverter();
public override IList<int>? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return _converter.Read(ref reader, typeToConvert, options);
}
public override void Write(Utf8JsonWriter writer, IList<int>? value, JsonSerializerOptions options)
{
_converter.Write(writer, ConvertIListToList(value), options);
}
private List<int>? ConvertIListToList(IList<int>? src)
{
if (src == null)
return null;
List<int>? dest = src as List<int>;
if (dest != null)
return dest;
return new List<int>(src);
}
}
}

View File

@ -1,21 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Serialization;
namespace System.Text.Json.Converters
{
internal class TextualStringIListWithSemicolonConverter : JsonConverter<IList<string>?>
{
private readonly JsonConverter<List<string>?> _converter = new TextualStringListWithSemicolonConverter();
public override IList<string>? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return _converter.Read(ref reader, typeToConvert, options)?.ToArray();
}
public override void Write(Utf8JsonWriter writer, IList<string>? value, JsonSerializerOptions options)
{
_converter.Write(writer, value?.ToList(), options);
}
}
}

View File

@ -47,7 +47,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api
+ $"&org_loc={reqLoc}" + $"&org_loc={reqLoc}"
+ $"&method={method.ToUpper()}" + $"&method={method.ToUpper()}"
+ $"&secret={client.Credentials.MidasAppKey}"; + $"&secret={client.Credentials.MidasAppKey}";
request.Signature = Utilities.HMACSHA256Utility.Hash(client.Credentials.MidasAppKey ?? string.Empty, plainText).ToLower(); request.Signature = Utilities.HMACUtility.HashWithSHA256(client.Credentials.MidasAppKey ?? string.Empty, plainText).ToLower();
} }
return request; return request;

View File

@ -32,9 +32,9 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.Models
/// 获取或设置业务域名列表。 /// 获取或设置业务域名列表。
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("wxa_jump_h5_domain")] [Newtonsoft.Json.JsonProperty("wxa_jump_h5_domain")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.TextualStringIListWithSemicolonConverter))] [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.TextualStringListWithSemicolonSplitConverter))]
[System.Text.Json.Serialization.JsonPropertyName("wxa_jump_h5_domain")] [System.Text.Json.Serialization.JsonPropertyName("wxa_jump_h5_domain")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.TextualStringIListWithSemicolonConverter))] [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.TextualStringListWithSemicolonSplitConverter))]
public IList<string>? WxaJumpH5DomainList { get; set; } public IList<string>? WxaJumpH5DomainList { get; set; }
} }
} }

View File

@ -9,27 +9,27 @@
/// 获取或设置目前生效的全网发布版第三方平台小程序业务域名列表。 /// 获取或设置目前生效的全网发布版第三方平台小程序业务域名列表。
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("published_wxa_jump_h5_domain")] [Newtonsoft.Json.JsonProperty("published_wxa_jump_h5_domain")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.TextualStringArrayWithSemicolonConverter))] [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.TextualStringArrayWithSemicolonSplitConverter))]
[System.Text.Json.Serialization.JsonPropertyName("published_wxa_jump_h5_domain")] [System.Text.Json.Serialization.JsonPropertyName("published_wxa_jump_h5_domain")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.TextualStringArrayWithSemicolonConverter))] [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.TextualStringArrayWithSemicolonSplitConverter))]
public string[]? PublishedWxaJumpH5DomainList { get; set; } public string[]? PublishedWxaJumpH5DomainList { get; set; }
/// <summary> /// <summary>
/// 获取或设置目前生效的测试版第三方平台小程序业务域名列表。 /// 获取或设置目前生效的测试版第三方平台小程序业务域名列表。
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("testing_wxa_jump_h5_domain")] [Newtonsoft.Json.JsonProperty("testing_wxa_jump_h5_domain")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.TextualStringArrayWithSemicolonConverter))] [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.TextualStringArrayWithSemicolonSplitConverter))]
[System.Text.Json.Serialization.JsonPropertyName("testing_wxa_jump_h5_domain")] [System.Text.Json.Serialization.JsonPropertyName("testing_wxa_jump_h5_domain")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.TextualStringArrayWithSemicolonConverter))] [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.TextualStringArrayWithSemicolonSplitConverter))]
public string[]? TestingWxaJumpH5DomainList { get; set; } public string[]? TestingWxaJumpH5DomainList { get; set; }
/// <summary> /// <summary>
/// 获取或设置未通过验证的第三方平台小程序业务域名列表。 /// 获取或设置未通过验证的第三方平台小程序业务域名列表。
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("invalid_wxa_jump_h5_domain")] [Newtonsoft.Json.JsonProperty("invalid_wxa_jump_h5_domain")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.TextualStringArrayWithSemicolonConverter))] [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.TextualStringArrayWithSemicolonSplitConverter))]
[System.Text.Json.Serialization.JsonPropertyName("invalid_wxa_jump_h5_domain")] [System.Text.Json.Serialization.JsonPropertyName("invalid_wxa_jump_h5_domain")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.TextualStringArrayWithSemicolonConverter))] [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.TextualStringArrayWithSemicolonSplitConverter))]
public string[]? InvalidWxaJumpH5DomainList { get; set; } public string[]? InvalidWxaJumpH5DomainList { get; set; }
} }
} }

View File

@ -32,9 +32,9 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.Models
/// 获取或设置服务器域名列表。 /// 获取或设置服务器域名列表。
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("wxa_server_domain")] [Newtonsoft.Json.JsonProperty("wxa_server_domain")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.TextualStringIListWithSemicolonConverter))] [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.TextualStringListWithSemicolonSplitConverter))]
[System.Text.Json.Serialization.JsonPropertyName("wxa_server_domain")] [System.Text.Json.Serialization.JsonPropertyName("wxa_server_domain")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.TextualStringIListWithSemicolonConverter))] [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.TextualStringListWithSemicolonSplitConverter))]
public IList<string>? WxaServerDomainList { get; set; } public IList<string>? WxaServerDomainList { get; set; }
} }
} }

View File

@ -9,27 +9,27 @@
/// 获取或设置目前生效的全网发布版第三方平台小程序服务器域名列表。 /// 获取或设置目前生效的全网发布版第三方平台小程序服务器域名列表。
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("published_wxa_server_domain")] [Newtonsoft.Json.JsonProperty("published_wxa_server_domain")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.TextualStringArrayWithSemicolonConverter))] [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.TextualStringArrayWithSemicolonSplitConverter))]
[System.Text.Json.Serialization.JsonPropertyName("published_wxa_server_domain")] [System.Text.Json.Serialization.JsonPropertyName("published_wxa_server_domain")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.TextualStringArrayWithSemicolonConverter))] [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.TextualStringArrayWithSemicolonSplitConverter))]
public string[]? PublishedWxaServerDomainList { get; set; } public string[]? PublishedWxaServerDomainList { get; set; }
/// <summary> /// <summary>
/// 获取或设置目前生效的测试版第三方平台小程序服务器域名列表。 /// 获取或设置目前生效的测试版第三方平台小程序服务器域名列表。
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("testing_wxa_server_domain")] [Newtonsoft.Json.JsonProperty("testing_wxa_server_domain")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.TextualStringArrayWithSemicolonConverter))] [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.TextualStringArrayWithSemicolonSplitConverter))]
[System.Text.Json.Serialization.JsonPropertyName("testing_wxa_server_domain")] [System.Text.Json.Serialization.JsonPropertyName("testing_wxa_server_domain")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.TextualStringArrayWithSemicolonConverter))] [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.TextualStringArrayWithSemicolonSplitConverter))]
public string[]? TestingWxaServerDomainList { get; set; } public string[]? TestingWxaServerDomainList { get; set; }
/// <summary> /// <summary>
/// 获取或设置未通过验证的第三方平台小程序服务器域名列表。 /// 获取或设置未通过验证的第三方平台小程序服务器域名列表。
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("invalid_wxa_server_domain")] [Newtonsoft.Json.JsonProperty("invalid_wxa_server_domain")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.TextualStringArrayWithSemicolonConverter))] [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.TextualStringArrayWithSemicolonSplitConverter))]
[System.Text.Json.Serialization.JsonPropertyName("invalid_wxa_server_domain")] [System.Text.Json.Serialization.JsonPropertyName("invalid_wxa_server_domain")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.TextualStringArrayWithSemicolonConverter))] [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.TextualStringArrayWithSemicolonSplitConverter))]
public string[]? InvalidWxaServerDomainList { get; set; } public string[]? InvalidWxaServerDomainList { get; set; }
} }
} }

View File

@ -17,7 +17,7 @@
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("tagid_list")] [Newtonsoft.Json.JsonProperty("tagid_list")]
[System.Text.Json.Serialization.JsonPropertyName("tagid_list")] [System.Text.Json.Serialization.JsonPropertyName("tagid_list")]
public int[] TagIdList { get; set; } = default!; public string[] TagIdList { get; set; } = default!;
/// <summary> /// <summary>
/// 获取或设置打印员数量。 /// 获取或设置打印员数量。

View File

@ -25,9 +25,9 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.Models
/// 获取或设置打印员面单打印权限列表。 /// 获取或设置打印员面单打印权限列表。
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("tagid_list")] [Newtonsoft.Json.JsonProperty("tagid_list")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.TextualInt32IListConverter))] [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.TextualStringListWithCommaSplitConverter))]
[System.Text.Json.Serialization.JsonPropertyName("tagid_list")] [System.Text.Json.Serialization.JsonPropertyName("tagid_list")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.TextualInt32IListConverter))] [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.TextualStringListWithCommaSplitConverter))]
public IList<int>? TagIdList { get; set; } public IList<string>? TagIdList { get; set; }
} }
} }

View File

@ -145,7 +145,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.Models
internal static class Converters internal static class Converters
{ {
internal class NewtonsoftJsonWaybillDataListConverter : Newtonsoft.Json.JsonConverter<IList<Types.WaybillData>?> internal class RequestPropertyWaybillDataListNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter<IList<Types.WaybillData>?>
{ {
public override bool CanRead public override bool CanRead
{ {
@ -194,7 +194,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.Models
} }
} }
internal class SystemTextJsonWaybillDataListConverter : System.Text.Json.Serialization.JsonConverter<IList<Types.WaybillData>?> internal class RequestPropertyWaybillDataListSystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter<IList<Types.WaybillData>?>
{ {
public override IList<Types.WaybillData>? Read(ref System.Text.Json.Utf8JsonReader reader, Type typeToConvert, System.Text.Json.JsonSerializerOptions options) public override IList<Types.WaybillData>? Read(ref System.Text.Json.Utf8JsonReader reader, Type typeToConvert, System.Text.Json.JsonSerializerOptions options)
{ {
@ -252,9 +252,9 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.Models
/// 获取或设置面单数据列表。 /// 获取或设置面单数据列表。
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("waybill_data")] [Newtonsoft.Json.JsonProperty("waybill_data")]
[Newtonsoft.Json.JsonConverter(typeof(Converters.NewtonsoftJsonWaybillDataListConverter))] [Newtonsoft.Json.JsonConverter(typeof(Converters.RequestPropertyWaybillDataListNewtonsoftJsonConverter))]
[System.Text.Json.Serialization.JsonPropertyName("waybill_data")] [System.Text.Json.Serialization.JsonPropertyName("waybill_data")]
[System.Text.Json.Serialization.JsonConverter(typeof(Converters.SystemTextJsonWaybillDataListConverter))] [System.Text.Json.Serialization.JsonConverter(typeof(Converters.RequestPropertyWaybillDataListSystemTextJsonConverter))]
public IList<Types.WaybillData> WaybillDataList { get; set; } = new List<Types.WaybillData>(); public IList<Types.WaybillData> WaybillDataList { get; set; } = new List<Types.WaybillData>();
/// <summary> /// <summary>

View File

@ -21,7 +21,8 @@
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("json")] [Newtonsoft.Json.JsonProperty("json")]
[System.Text.Json.Serialization.JsonPropertyName("json")] [System.Text.Json.Serialization.JsonPropertyName("json")]
public object Data { get; set; } = default!; [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.DynamicObjectReadOnlyConverter))]
public dynamic? Data { get; set; }
} }
} }

View File

@ -49,9 +49,9 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.Models
/// 获取或设置商品价格(单位:分)。 /// 获取或设置商品价格(单位:分)。
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("price")] [Newtonsoft.Json.JsonProperty("price")]
[Newtonsoft.Json.JsonConverter(typeof(Converters.NewtonsoftJsonCurrencyConverter))] [Newtonsoft.Json.JsonConverter(typeof(Converters.ResponsePropertyCurrencyNewtonsoftJsonConverter))]
[System.Text.Json.Serialization.JsonPropertyName("price")] [System.Text.Json.Serialization.JsonPropertyName("price")]
[System.Text.Json.Serialization.JsonConverter(typeof(Converters.SystemTextJsonCurrencyConverter))] [System.Text.Json.Serialization.JsonConverter(typeof(Converters.ResponsePropertyCurrencySystemTextJsonConverter))]
public int Price { get; set; } public int Price { get; set; }
/// <summary> /// <summary>
@ -72,18 +72,18 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.Models
/// 获取或设置佣金金额(单位:分)。 /// 获取或设置佣金金额(单位:分)。
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("commission")] [Newtonsoft.Json.JsonProperty("commission")]
[Newtonsoft.Json.JsonConverter(typeof(Converters.NewtonsoftJsonCurrencyConverter))] [Newtonsoft.Json.JsonConverter(typeof(Converters.ResponsePropertyCurrencyNewtonsoftJsonConverter))]
[System.Text.Json.Serialization.JsonPropertyName("commission")] [System.Text.Json.Serialization.JsonPropertyName("commission")]
[System.Text.Json.Serialization.JsonConverter(typeof(Converters.SystemTextJsonCurrencyConverter))] [System.Text.Json.Serialization.JsonConverter(typeof(Converters.ResponsePropertyCurrencySystemTextJsonConverter))]
public int CommissionValue { get; set; } public int CommissionValue { get; set; }
/// <summary> /// <summary>
/// 获取或设置预估佣金金额(单位:分)。 /// 获取或设置预估佣金金额(单位:分)。
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("estimatedCommission")] [Newtonsoft.Json.JsonProperty("estimatedCommission")]
[Newtonsoft.Json.JsonConverter(typeof(Converters.NewtonsoftJsonCurrencyConverter))] [Newtonsoft.Json.JsonConverter(typeof(Converters.ResponsePropertyCurrencyNewtonsoftJsonConverter))]
[System.Text.Json.Serialization.JsonPropertyName("estimatedCommission")] [System.Text.Json.Serialization.JsonPropertyName("estimatedCommission")]
[System.Text.Json.Serialization.JsonConverter(typeof(Converters.SystemTextJsonCurrencyConverter))] [System.Text.Json.Serialization.JsonConverter(typeof(Converters.ResponsePropertyCurrencySystemTextJsonConverter))]
public int EstimatedCommissionValue { get; set; } public int EstimatedCommissionValue { get; set; }
/// <summary> /// <summary>
@ -196,7 +196,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.Models
internal static class Converters internal static class Converters
{ {
internal class NewtonsoftJsonCurrencyConverter : Newtonsoft.Json.JsonConverter<int> internal class ResponsePropertyCurrencyNewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter<int>
{ {
public override bool CanRead public override bool CanRead
{ {
@ -239,7 +239,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.Models
} }
} }
internal class SystemTextJsonCurrencyConverter : System.Text.Json.Serialization.JsonConverter<int> internal class ResponsePropertyCurrencySystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter<int>
{ {
public override int Read(ref System.Text.Json.Utf8JsonReader reader, Type typeToConvert, System.Text.Json.JsonSerializerOptions options) public override int Read(ref System.Text.Json.Utf8JsonReader reader, Type typeToConvert, System.Text.Json.JsonSerializerOptions options)
{ {

View File

@ -63,8 +63,9 @@
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("extInfo")] [Newtonsoft.Json.JsonProperty("extInfo")]
[System.Text.Json.Serialization.JsonPropertyName("extInfo")] [System.Text.Json.Serialization.JsonPropertyName("extInfo")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.DynamicObjectReadOnlyConverter))]
public object Extra { get; set; } = default!; public dynamic? Extra { get; set; }
} }
public class Product public class Product

View File

@ -105,208 +105,28 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.Models
internal static class Converters internal static class Converters
{ {
internal class NewtonsoftJsonPictureConverter : Newtonsoft.Json.JsonConverter<Types.Picture?> internal class RequestPropertyPictureNewtonsoftJsonConverter : Newtonsoft.Json.Converters.TextualObjectInJsonFormatConverterBase<Types.Picture?>
{ {
public override bool CanRead
{
get { return true; }
}
public override bool CanWrite
{
get { return true; }
}
public override Types.Picture? ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, Types.Picture? existingValue, bool hasExistingValue, Newtonsoft.Json.JsonSerializer serializer)
{
if (reader.TokenType == Newtonsoft.Json.JsonToken.Null)
{
return existingValue;
}
else if (reader.TokenType == Newtonsoft.Json.JsonToken.String)
{
string? value = serializer.Deserialize<string>(reader);
if (value == null)
return existingValue;
return Newtonsoft.Json.JsonConvert.DeserializeObject<Types.Picture>(value);
}
throw new Newtonsoft.Json.JsonReaderException();
}
public override void WriteJson(Newtonsoft.Json.JsonWriter writer, Types.Picture? value, Newtonsoft.Json.JsonSerializer serializer)
{
if (value != null)
writer.WriteValue(Newtonsoft.Json.JsonConvert.SerializeObject(value, Newtonsoft.Json.Formatting.None));
else
writer.WriteNull();
}
} }
internal class SystemTextJsonPictureConverter : System.Text.Json.Serialization.JsonConverter<Types.Picture?> internal class RequestPropertyPictureSystemTextJsonConverter : System.Text.Json.Converters.TextualObjectInJsonFormatConverterBase<Types.Picture?>
{ {
public override Types.Picture? 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.String)
{
string? value = reader.GetString();
if (value == null)
return null;
return System.Text.Json.JsonSerializer.Deserialize<Types.Picture>(value, options);
}
throw new System.Text.Json.JsonException();
}
public override void Write(System.Text.Json.Utf8JsonWriter writer, Types.Picture? value, System.Text.Json.JsonSerializerOptions options)
{
if (value != null)
writer.WriteStringValue(System.Text.Json.JsonSerializer.Serialize(value, options));
else
writer.WriteNullValue();
}
} }
internal class NewtonsoftJsonServiceConverter : Newtonsoft.Json.JsonConverter<Types.Service?> internal class RequestPropertyServiceNewtonsoftJsonConverter : Newtonsoft.Json.Converters.TextualObjectInJsonFormatConverterBase<Types.Service?>
{ {
public override bool CanRead
{
get { return true; }
}
public override bool CanWrite
{
get { return true; }
}
public override Types.Service? ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, Types.Service? existingValue, bool hasExistingValue, Newtonsoft.Json.JsonSerializer serializer)
{
if (reader.TokenType == Newtonsoft.Json.JsonToken.Null)
{
return existingValue;
}
else if (reader.TokenType == Newtonsoft.Json.JsonToken.String)
{
string? value = serializer.Deserialize<string>(reader);
if (value == null)
return existingValue;
return Newtonsoft.Json.JsonConvert.DeserializeObject<Types.Service>(value);
}
throw new Newtonsoft.Json.JsonReaderException();
}
public override void WriteJson(Newtonsoft.Json.JsonWriter writer, Types.Service? value, Newtonsoft.Json.JsonSerializer serializer)
{
if (value != null)
writer.WriteValue(Newtonsoft.Json.JsonConvert.SerializeObject(value, Newtonsoft.Json.Formatting.None));
else
writer.WriteNull();
}
} }
internal class SystemTextJsonServiceConverter : System.Text.Json.Serialization.JsonConverter<Types.Service?> internal class RequestPropertyServiceSystemTextJsonConverter : System.Text.Json.Converters.TextualObjectInJsonFormatConverterBase<Types.Service?>
{ {
public override Types.Service? 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.String)
{
string? value = reader.GetString();
if (value == null)
return null;
return System.Text.Json.JsonSerializer.Deserialize<Types.Service>(value, options);
}
throw new System.Text.Json.JsonException();
}
public override void Write(System.Text.Json.Utf8JsonWriter writer, Types.Service? value, System.Text.Json.JsonSerializerOptions options)
{
if (value != null)
writer.WriteStringValue(System.Text.Json.JsonSerializer.Serialize(value, options));
else
writer.WriteNullValue();
}
} }
internal class NewtonsoftJsonKfConverter : Newtonsoft.Json.JsonConverter<Types.Kf?> internal class RequsetPropertyKfNewtonsoftJsonConverter : Newtonsoft.Json.Converters.TextualObjectInJsonFormatConverterBase<Types.Kf?>
{ {
public override bool CanRead
{
get { return true; }
}
public override bool CanWrite
{
get { return true; }
}
public override Types.Kf? ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, Types.Kf? existingValue, bool hasExistingValue, Newtonsoft.Json.JsonSerializer serializer)
{
if (reader.TokenType == Newtonsoft.Json.JsonToken.Null)
{
return existingValue;
}
else if (reader.TokenType == Newtonsoft.Json.JsonToken.String)
{
string? value = serializer.Deserialize<string>(reader);
if (value == null)
return existingValue;
return Newtonsoft.Json.JsonConvert.DeserializeObject<Types.Kf>(value);
}
throw new Newtonsoft.Json.JsonReaderException();
}
public override void WriteJson(Newtonsoft.Json.JsonWriter writer, Types.Kf? value, Newtonsoft.Json.JsonSerializer serializer)
{
if (value != null)
writer.WriteValue(Newtonsoft.Json.JsonConvert.SerializeObject(value, Newtonsoft.Json.Formatting.None));
else
writer.WriteNull();
}
} }
internal class SystemTextJsonKfConverter : System.Text.Json.Serialization.JsonConverter<Types.Kf?> internal class RequestPropertyKfSystemTextJsonConverter : System.Text.Json.Converters.TextualObjectInJsonFormatConverterBase<Types.Kf?>
{ {
public override Types.Kf? 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.String)
{
string? value = reader.GetString();
if (value == null)
return null;
return System.Text.Json.JsonSerializer.Deserialize<Types.Kf>(value, options);
}
throw new System.Text.Json.JsonException();
}
public override void Write(System.Text.Json.Utf8JsonWriter writer, Types.Kf? value, System.Text.Json.JsonSerializerOptions options)
{
if (value != null)
writer.WriteStringValue(System.Text.Json.JsonSerializer.Serialize(value, options));
else
writer.WriteNullValue();
}
} }
} }
@ -337,27 +157,27 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.Models
/// 获取或设置门店图片信息。 /// 获取或设置门店图片信息。
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("pic_list")] [Newtonsoft.Json.JsonProperty("pic_list")]
[Newtonsoft.Json.JsonConverter(typeof(Converters.NewtonsoftJsonPictureConverter))] [Newtonsoft.Json.JsonConverter(typeof(Converters.RequestPropertyPictureNewtonsoftJsonConverter))]
[System.Text.Json.Serialization.JsonPropertyName("pic_list")] [System.Text.Json.Serialization.JsonPropertyName("pic_list")]
[System.Text.Json.Serialization.JsonConverter(typeof(Converters.SystemTextJsonPictureConverter))] [System.Text.Json.Serialization.JsonConverter(typeof(Converters.RequestPropertyPictureSystemTextJsonConverter))]
public Types.Picture Picture { get; set; } = new Types.Picture(); public Types.Picture Picture { get; set; } = new Types.Picture();
/// <summary> /// <summary>
/// 获取或设置服务标签信息。 /// 获取或设置服务标签信息。
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("service_infos")] [Newtonsoft.Json.JsonProperty("service_infos")]
[Newtonsoft.Json.JsonConverter(typeof(Converters.NewtonsoftJsonServiceConverter))] [Newtonsoft.Json.JsonConverter(typeof(Converters.RequestPropertyServiceNewtonsoftJsonConverter))]
[System.Text.Json.Serialization.JsonPropertyName("service_infos")] [System.Text.Json.Serialization.JsonPropertyName("service_infos")]
[System.Text.Json.Serialization.JsonConverter(typeof(Converters.SystemTextJsonServiceConverter))] [System.Text.Json.Serialization.JsonConverter(typeof(Converters.RequestPropertyServiceSystemTextJsonConverter))]
public Types.Service Service { get; set; } = new Types.Service(); public Types.Service Service { get; set; } = new Types.Service();
/// <summary> /// <summary>
/// 获取或设置客服信息。 /// 获取或设置客服信息。
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("kf_info")] [Newtonsoft.Json.JsonProperty("kf_info")]
[Newtonsoft.Json.JsonConverter(typeof(Converters.NewtonsoftJsonKfConverter))] [Newtonsoft.Json.JsonConverter(typeof(Converters.RequsetPropertyKfNewtonsoftJsonConverter))]
[System.Text.Json.Serialization.JsonPropertyName("kf_info")] [System.Text.Json.Serialization.JsonPropertyName("kf_info")]
[System.Text.Json.Serialization.JsonConverter(typeof(Converters.SystemTextJsonKfConverter))] [System.Text.Json.Serialization.JsonConverter(typeof(Converters.RequestPropertyKfSystemTextJsonConverter))]
public Types.Kf? Kf { get; set; } public Types.Kf? Kf { get; set; }
/// <summary> /// <summary>

View File

@ -31,7 +31,8 @@
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("data")] [Newtonsoft.Json.JsonProperty("data")]
[System.Text.Json.Serialization.JsonPropertyName("data")] [System.Text.Json.Serialization.JsonPropertyName("data")]
public object? Data { get; set; } [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.DynamicObjectReadOnlyConverter))]
public dynamic? Data { get; set; }
/// <summary> /// <summary>
/// 获取或设置调用方请求的唯一标识。 /// 获取或设置调用方请求的唯一标识。

View File

@ -23,72 +23,12 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.Models
internal static class Converters internal static class Converters
{ {
internal class NewtonsoftJsonPictureConverter : Newtonsoft.Json.JsonConverter<Types.Picture?> internal class RequestPropertyPictureNewtonsoftJsonConverter : Newtonsoft.Json.Converters.TextualObjectInJsonFormatConverterBase<Types.Picture?>
{ {
public override bool CanRead
{
get { return true; }
}
public override bool CanWrite
{
get { return true; }
}
public override Types.Picture? ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, Types.Picture? existingValue, bool hasExistingValue, Newtonsoft.Json.JsonSerializer serializer)
{
if (reader.TokenType == Newtonsoft.Json.JsonToken.Null)
{
return existingValue;
}
else if (reader.TokenType == Newtonsoft.Json.JsonToken.String)
{
string? value = serializer.Deserialize<string>(reader);
if (value == null)
return existingValue;
return Newtonsoft.Json.JsonConvert.DeserializeObject<Types.Picture>(value);
}
throw new Newtonsoft.Json.JsonReaderException();
}
public override void WriteJson(Newtonsoft.Json.JsonWriter writer, Types.Picture? value, Newtonsoft.Json.JsonSerializer serializer)
{
if (value != null)
writer.WriteValue(Newtonsoft.Json.JsonConvert.SerializeObject(value, Newtonsoft.Json.Formatting.None));
else
writer.WriteNull();
}
} }
internal class SystemTextJsonPictureConverter : System.Text.Json.Serialization.JsonConverter<Types.Picture?> internal class RequestPropertyPictureSystemTextJsonConverter : System.Text.Json.Converters.TextualObjectInJsonFormatConverterBase<Types.Picture?>
{ {
public override Types.Picture? 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.String)
{
string? value = reader.GetString();
if (value == null)
return null;
return System.Text.Json.JsonSerializer.Deserialize<Types.Picture>(value, options);
}
throw new System.Text.Json.JsonException();
}
public override void Write(System.Text.Json.Utf8JsonWriter writer, Types.Picture? value, System.Text.Json.JsonSerializerOptions options)
{
if (value != null)
writer.WriteStringValue(System.Text.Json.JsonSerializer.Serialize(value, options));
else
writer.WriteNullValue();
}
} }
} }
@ -110,9 +50,9 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.Models
/// 获取或设置门店图片信息。 /// 获取或设置门店图片信息。
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("pic_list")] [Newtonsoft.Json.JsonProperty("pic_list")]
[Newtonsoft.Json.JsonConverter(typeof(Converters.NewtonsoftJsonPictureConverter))] [Newtonsoft.Json.JsonConverter(typeof(Converters.RequestPropertyPictureNewtonsoftJsonConverter))]
[System.Text.Json.Serialization.JsonPropertyName("pic_list")] [System.Text.Json.Serialization.JsonPropertyName("pic_list")]
[System.Text.Json.Serialization.JsonConverter(typeof(Converters.SystemTextJsonPictureConverter))] [System.Text.Json.Serialization.JsonConverter(typeof(Converters.RequestPropertyPictureSystemTextJsonConverter))]
public Types.Picture Picture { get; set; } = new Types.Picture(); public Types.Picture Picture { get; set; } = new Types.Picture();
/// <summary> /// <summary>

View File

@ -16,72 +16,12 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.Models
internal static class Converters internal static class Converters
{ {
internal class NewtonsoftJsonPictureConverter : Newtonsoft.Json.JsonConverter<Types.Picture?> internal class RequestPropertyPictureNewtonsoftJsonConverter : Newtonsoft.Json.Converters.TextualObjectInJsonFormatConverterBase<Types.Picture?>
{ {
public override bool CanRead
{
get { return true; }
}
public override bool CanWrite
{
get { return true; }
}
public override Types.Picture? ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, Types.Picture? existingValue, bool hasExistingValue, Newtonsoft.Json.JsonSerializer serializer)
{
if (reader.TokenType == Newtonsoft.Json.JsonToken.Null)
{
return existingValue;
}
else if (reader.TokenType == Newtonsoft.Json.JsonToken.String)
{
string? value = serializer.Deserialize<string>(reader);
if (value == null)
return existingValue;
return Newtonsoft.Json.JsonConvert.DeserializeObject<Types.Picture>(value);
}
throw new Newtonsoft.Json.JsonReaderException();
}
public override void WriteJson(Newtonsoft.Json.JsonWriter writer, Types.Picture? value, Newtonsoft.Json.JsonSerializer serializer)
{
if (value != null)
writer.WriteValue(Newtonsoft.Json.JsonConvert.SerializeObject(value, Newtonsoft.Json.Formatting.None));
else
writer.WriteNull();
}
} }
internal class SystemTextJsonPictureConverter : System.Text.Json.Serialization.JsonConverter<Types.Picture?> internal class RequestPropertyPictureSystemTextJsonConverter : System.Text.Json.Converters.TextualObjectInJsonFormatConverterBase<Types.Picture?>
{ {
public override Types.Picture? 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.String)
{
string? value = reader.GetString();
if (value == null)
return null;
return System.Text.Json.JsonSerializer.Deserialize<Types.Picture>(value, options);
}
throw new System.Text.Json.JsonException();
}
public override void Write(System.Text.Json.Utf8JsonWriter writer, Types.Picture? value, System.Text.Json.JsonSerializerOptions options)
{
if (value != null)
writer.WriteStringValue(System.Text.Json.JsonSerializer.Serialize(value, options));
else
writer.WriteNullValue();
}
} }
} }
@ -103,9 +43,9 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.Models
/// 获取或设置门店图片信息。 /// 获取或设置门店图片信息。
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("pic_list")] [Newtonsoft.Json.JsonProperty("pic_list")]
[Newtonsoft.Json.JsonConverter(typeof(Converters.NewtonsoftJsonPictureConverter))] [Newtonsoft.Json.JsonConverter(typeof(Converters.RequestPropertyPictureNewtonsoftJsonConverter))]
[System.Text.Json.Serialization.JsonPropertyName("pic_list")] [System.Text.Json.Serialization.JsonPropertyName("pic_list")]
[System.Text.Json.Serialization.JsonConverter(typeof(Converters.SystemTextJsonPictureConverter))] [System.Text.Json.Serialization.JsonConverter(typeof(Converters.RequestPropertyPictureSystemTextJsonConverter))]
public Types.Picture Picture { get; set; } = new Types.Picture(); public Types.Picture Picture { get; set; } = new Types.Picture();
/// <summary> /// <summary>

View File

@ -49,72 +49,12 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.Models
internal static class Converters internal static class Converters
{ {
internal class NewtonsoftJsonDefaultTimeDataConverter : Newtonsoft.Json.JsonConverter<Types.DefaultTimeData?> internal class ResponsePropertyDefaultTimeDataNewtonsoftJsonConverter : Newtonsoft.Json.Converters.TextualObjectInJsonFormatConverterBase<Types.DefaultTimeData?>
{ {
public override bool CanRead
{
get { return true; }
}
public override bool CanWrite
{
get { return true; }
}
public override Types.DefaultTimeData? ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, Types.DefaultTimeData? existingValue, bool hasExistingValue, Newtonsoft.Json.JsonSerializer serializer)
{
if (reader.TokenType == Newtonsoft.Json.JsonToken.Null)
{
return existingValue;
}
else if (reader.TokenType == Newtonsoft.Json.JsonToken.String)
{
string? value = serializer.Deserialize<string>(reader);
if (value == null)
return existingValue;
return Newtonsoft.Json.JsonConvert.DeserializeObject<Types.DefaultTimeData>(value);
}
throw new Newtonsoft.Json.JsonReaderException();
}
public override void WriteJson(Newtonsoft.Json.JsonWriter writer, Types.DefaultTimeData? value, Newtonsoft.Json.JsonSerializer serializer)
{
if (value != null)
writer.WriteValue(Newtonsoft.Json.JsonConvert.SerializeObject(value, Newtonsoft.Json.Formatting.None));
else
writer.WriteNull();
}
} }
internal class SystemTextJsonDefaultTimeDataConverter : System.Text.Json.Serialization.JsonConverter<Types.DefaultTimeData?> internal class ResponsePropertyDefaultTimeDataSystemTextJsonConverter : System.Text.Json.Converters.TextualObjectInJsonFormatConverterBase<Types.DefaultTimeData?>
{ {
public override Types.DefaultTimeData? 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.String)
{
string? value = reader.GetString();
if (value == null)
return null;
return System.Text.Json.JsonSerializer.Deserialize<Types.DefaultTimeData>(value, options);
}
throw new System.Text.Json.JsonException();
}
public override void Write(System.Text.Json.Utf8JsonWriter writer, Types.DefaultTimeData? value, System.Text.Json.JsonSerializerOptions options)
{
if (value != null)
writer.WriteStringValue(System.Text.Json.JsonSerializer.Serialize(value, options));
else
writer.WriteNullValue();
}
} }
} }
@ -122,9 +62,9 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.Models
/// 获取或设置查询数据。 /// 获取或设置查询数据。
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("default_time_data")] [Newtonsoft.Json.JsonProperty("default_time_data")]
[Newtonsoft.Json.JsonConverter(typeof(Converters.NewtonsoftJsonDefaultTimeDataConverter))] [Newtonsoft.Json.JsonConverter(typeof(Converters.ResponsePropertyDefaultTimeDataNewtonsoftJsonConverter))]
[System.Text.Json.Serialization.JsonPropertyName("default_time_data")] [System.Text.Json.Serialization.JsonPropertyName("default_time_data")]
[System.Text.Json.Serialization.JsonConverter(typeof(Converters.SystemTextJsonDefaultTimeDataConverter))] [System.Text.Json.Serialization.JsonConverter(typeof(Converters.ResponsePropertyDefaultTimeDataSystemTextJsonConverter))]
public Types.DefaultTimeData? DefaultTimeData { get; set; } public Types.DefaultTimeData? DefaultTimeData { get; set; }
/// <summary> /// <summary>

View File

@ -136,77 +136,6 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.Models
} }
} }
internal static class Converters
{
internal class NewtonsoftJsonMediaIdListConverter : Newtonsoft.Json.JsonConverter<IList<string>?>
{
public override bool CanRead
{
get { return true; }
}
public override bool CanWrite
{
get { return true; }
}
public override IList<string>? ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, IList<string>? existingValue, bool hasExistingValue, Newtonsoft.Json.JsonSerializer serializer)
{
if (reader.TokenType == Newtonsoft.Json.JsonToken.Null)
{
return existingValue;
}
else if (reader.TokenType == Newtonsoft.Json.JsonToken.String)
{
string? value = serializer.Deserialize<string>(reader);
if (value == null)
return existingValue;
return value.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries).ToList();
}
throw new Newtonsoft.Json.JsonReaderException();
}
public override void WriteJson(Newtonsoft.Json.JsonWriter writer, IList<string>? value, Newtonsoft.Json.JsonSerializer serializer)
{
if (value != null)
writer.WriteValue(string.Join("|", value));
else
writer.WriteNull();
}
}
internal class SystemTextJsonMediaIdListConverter : System.Text.Json.Serialization.JsonConverter<IList<string>?>
{
public override IList<string>? 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.String)
{
string? value = reader.GetString();
if (value == null)
return null;
return value.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries).ToList();
}
throw new System.Text.Json.JsonException();
}
public override void Write(System.Text.Json.Utf8JsonWriter writer, IList<string>? value, System.Text.Json.JsonSerializerOptions options)
{
if (value != null)
writer.WriteStringValue(string.Join("|", value));
else
writer.WriteNullValue();
}
}
}
/// <summary> /// <summary>
/// 获取或设置审核页面列表。 /// 获取或设置审核页面列表。
/// </summary> /// </summary>
@ -239,9 +168,9 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.Models
/// 获取或设置反馈附件 MediaId 列表。 /// 获取或设置反馈附件 MediaId 列表。
/// </summary> /// </summary>
[Newtonsoft.Json.JsonProperty("feedback_stuff")] [Newtonsoft.Json.JsonProperty("feedback_stuff")]
[Newtonsoft.Json.JsonConverter(typeof(Converters.NewtonsoftJsonMediaIdListConverter))] [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.TextualStringListWithPipeSplitConverter))]
[System.Text.Json.Serialization.JsonPropertyName("feedback_stuff")] [System.Text.Json.Serialization.JsonPropertyName("feedback_stuff")]
[System.Text.Json.Serialization.JsonConverter(typeof(Converters.SystemTextJsonMediaIdListConverter))] [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.TextualStringListWithPipeSplitConverter))]
public IList<string>? FeedbackStuffMediaIdList { get; set; } public IList<string>? FeedbackStuffMediaIdList { get; set; }
/// <summary> /// <summary>

View File

@ -0,0 +1,25 @@
## SKIT.FlurlHttpClient.Wechat.Api
[![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.Api.svg?sanitize=true&label=Downloads)](https://www.nuget.org/packages/SKIT.FlurlHttpClient.Wechat.Api) [![License](https://img.shields.io/github/license/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat?label=License)](https://mit-license.org/)
基于 `Flurl.Http` 的微信公众平台 & 微信开放平台 API 客户端。
---
### 【功能特性】
- 基于微信公众平台 & 微信开放平台 API 封装。
- 提供了微信公众平台 & 微信开放平台 API 所需的 SHA-1、HMAC-SHA-256、AES 等算法工具类。
- 提供了 JS-SDK 签名、解析回调通知事件等扩展方法。
---
### 【开发文档】
[点此查看](https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat)。
---
### 【更新日志】
[点此查看](https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat/blob/main/CHANGELOG.md)。

View File

@ -9,6 +9,8 @@
<PropertyGroup> <PropertyGroup>
<PackageId>SKIT.FlurlHttpClient.Wechat.Api</PackageId> <PackageId>SKIT.FlurlHttpClient.Wechat.Api</PackageId>
<PackageIcon>LOGO.png</PackageIcon>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageLicenseExpression>MIT</PackageLicenseExpression> <PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat</PackageProjectUrl> <PackageProjectUrl>https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat</PackageProjectUrl>
<PackageTags>Flurl.Http Wechat Weixin MicroMessage MiniProgram MiniGame MiniStore 微信 公众号 服务号 订阅号 小程序 小游戏 小商店 公众平台 开放平台 微信公众号 微信服务号 微信订阅号 微信小程序 微信小游戏 微信小商店 微信公众平台 微信开放平台</PackageTags> <PackageTags>Flurl.Http Wechat Weixin MicroMessage MiniProgram MiniGame MiniStore 微信 公众号 服务号 订阅号 小程序 小游戏 小商店 公众平台 开放平台 微信公众号 微信服务号 微信订阅号 微信小程序 微信小游戏 微信小商店 微信公众平台 微信开放平台</PackageTags>
@ -17,17 +19,28 @@
<Authors>Fu Diwei</Authors> <Authors>Fu Diwei</Authors>
<RepositoryType>git</RepositoryType> <RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat.git</RepositoryUrl> <RepositoryUrl>https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat.git</RepositoryUrl>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
<Deterministic>true</Deterministic>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
<ItemGroup>
<None Include="../../LOGO.png" Pack="true" PackagePath="/" />
<None Include="README.md" Pack="true" PackagePath="/" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<Reference Include="System.Web" Condition="'$(TargetFramework)' == 'net461'" /> <Reference Include="System.Web" Condition="'$(TargetFramework)' == 'net461'" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="SKIT.FlurlHttpClient.Common" Version="2.1.1" /> <PackageReference Include="SKIT.FlurlHttpClient.Common" Version="2.2.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -4,6 +4,9 @@ using System.Text;
namespace SKIT.FlurlHttpClient.Wechat.Api.Utilities namespace SKIT.FlurlHttpClient.Wechat.Api.Utilities
{ {
/// <summary>
/// AES 算法工具类。
/// </summary>
public static class AESUtility public static class AESUtility
{ {
/// <summary> /// <summary>

View File

@ -5,17 +5,17 @@ using System.Text;
namespace SKIT.FlurlHttpClient.Wechat.Api.Utilities namespace SKIT.FlurlHttpClient.Wechat.Api.Utilities
{ {
/// <summary> /// <summary>
/// HMAC-SHA-256 算法工具类。 /// HMAC 算法工具类。
/// </summary> /// </summary>
public static class HMACSHA256Utility public static class HMACUtility
{ {
/// <summary> /// <summary>
/// 获取信息摘要 /// 获取 HMAC-SHA-256 消息认证码
/// </summary> /// </summary>
/// <param name="secretBytes">密钥字节数组。</param> /// <param name="secretBytes">密钥字节数组。</param>
/// <param name="bytes">信息字节数组。</param> /// <param name="bytes">信息字节数组。</param>
/// <returns>信息摘要。</returns> /// <returns>信息摘要。</returns>
public static string Hash(byte[] secretBytes, byte[] bytes) public static string HashWithSHA256(byte[] secretBytes, byte[] bytes)
{ {
if (secretBytes == null) throw new ArgumentNullException(nameof(secretBytes)); if (secretBytes == null) throw new ArgumentNullException(nameof(secretBytes));
if (bytes == null) throw new ArgumentNullException(nameof(bytes)); if (bytes == null) throw new ArgumentNullException(nameof(bytes));
@ -26,19 +26,19 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.Utilities
} }
/// <summary> /// <summary>
/// 获取信息摘要 /// 获取 HMAC-SHA-256 消息认证码
/// </summary> /// </summary>
/// <param name="secret">密钥。</param> /// <param name="secret">密钥。</param>
/// <param name="message">文本信息。</param> /// <param name="message">文本信息。</param>
/// <returns>信息摘要。</returns> /// <returns>信息摘要。</returns>
public static string Hash(string secret, string message) public static string HashWithSHA256(string secret, string message)
{ {
if (secret == null) throw new ArgumentNullException(nameof(secret)); if (secret == null) throw new ArgumentNullException(nameof(secret));
if (message == null) throw new ArgumentNullException(nameof(message)); if (message == null) throw new ArgumentNullException(nameof(message));
byte[] secretBytes = Encoding.UTF8.GetBytes(secret); byte[] secretBytes = Encoding.UTF8.GetBytes(secret);
byte[] bytes = Encoding.UTF8.GetBytes(message); byte[] bytes = Encoding.UTF8.GetBytes(message);
return Hash(secretBytes, bytes); return HashWithSHA256(secretBytes, bytes);
} }
} }
} }

View File

@ -10,7 +10,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.Utilities
public static class SHA1Utility public static class SHA1Utility
{ {
/// <summary> /// <summary>
/// 获取信息摘要。 /// 获取 SHA-1 信息摘要。
/// </summary> /// </summary>
/// <param name="bytes">信息字节数组。</param> /// <param name="bytes">信息字节数组。</param>
/// <returns>信息摘要。</returns> /// <returns>信息摘要。</returns>
@ -24,7 +24,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.Utilities
} }
/// <summary> /// <summary>
/// 获取信息摘要。 /// 获取 SHA-1 信息摘要。
/// </summary> /// </summary>
/// <param name="message">文本信息。</param> /// <param name="message">文本信息。</param>
/// <returns>信息摘要。</returns> /// <returns>信息摘要。</returns>

View File

@ -2,7 +2,10 @@
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>netcoreapp3.1; net6.0</TargetFrameworks> <TargetFrameworks>netcoreapp3.1; net6.0</TargetFrameworks>
<LangVersion>9.0</LangVersion> <LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<NullableReferenceTypes>true</NullableReferenceTypes>
<IsPackable>false</IsPackable>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -0,0 +1,21 @@
using System;
using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
{
public class TestCase_AESUtilityTests
{
[Fact(DisplayName = "测试用例AES-CBC 解密")]
public void TestAESCBCDecryption()
{
string iv = "KEWv/gyiIwAfHvjrLeaX6w==";
string key = "YZJqKnNFi0KAiKUc0ggC2g==";
string cipherText = "Gu2PVnxVWl+jK4F8c0liGxfkB5Bj3m5HRvwgEIk1Yb+36RZ3Bg7YmUnud/ooiHz0PQroipsH7GCjlGwUeT04NwmrFaP1y3dRYPLpS43ed9QZWcFIFo+8vTs3Zco6S98DUvaNEAs8duhz/BzfBOZaIHMziRqEtPFI0ZDzCgJluBirJ6Wl3UkygZ5/QLo3KA53qGdip7K48Rq8XbCwuidTCw==";
string expectedPlainData = "{\"phoneNumber\":\"186****5613\",\"purePhoneNumber\":\"186****5613\",\"countryCode\":\"86\",\"watermark\":{\"timestamp\":1634545675,\"appid\":\"wxc****17e87e0e0a7\"}}";
string actualPlainData = Utilities.AESUtility.DecryptWithCBC(encodingKey: key, encodingIV: iv, encodingCipherText: cipherText);
Assert.Equal(expectedPlainData, actualPlainData, ignoreCase: true);
}
}
}

View File

@ -7,10 +7,10 @@ using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
{ {
public class WechatApiExecuteCVTests public class TestCase_ApiExecuteCVTests
{ {
[Fact(DisplayName = "[POST] /cv/img/qrcode")] [Fact(DisplayName = "测试用例:调用 API [POST] /cv/img/qrcode")]
public async Task CVImageQrcodeTest() public async Task TestExecuteCVImageQrcode()
{ {
var request = new Models.CVImageQrcodeRequest() var request = new Models.CVImageQrcodeRequest()
{ {
@ -24,8 +24,8 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
Assert.NotNull(response.ImageSize); Assert.NotNull(response.ImageSize);
} }
[Fact(DisplayName = "[POST] /cv/img/aicrop")] [Fact(DisplayName = "测试用例:调用 API [POST] /cv/img/aicrop")]
public async Task CVImageAICropTest() public async Task TestExecuteCVImageAICrop()
{ {
var request = new Models.CVImageAICropRequest() var request = new Models.CVImageAICropRequest()
{ {
@ -39,8 +39,8 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
Assert.NotNull(response.ImageSize); Assert.NotNull(response.ImageSize);
} }
[Fact(DisplayName = "[POST] /cv/img/superresolution")] [Fact(DisplayName = "测试用例:调用 API [POST] /cv/img/superresolution")]
public async Task CVImageSuperResolutionTest() public async Task TestExecuteCVImageSuperResolution()
{ {
var request = new Models.CVImageSuperResolutionRequest() var request = new Models.CVImageSuperResolutionRequest()
{ {
@ -53,8 +53,8 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
Assert.NotNull(response.MediaId); Assert.NotNull(response.MediaId);
} }
[Fact(DisplayName = "[POST] /cv/ocr/comm")] [Fact(DisplayName = "测试用例:调用 API [POST] /cv/ocr/comm")]
public async Task CVOCRCommonTest() public async Task TestExecuteCVOCRCommon()
{ {
var request = new Models.CVOCRCommonRequest() var request = new Models.CVOCRCommonRequest()
{ {

View File

@ -7,10 +7,10 @@ using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
{ {
public class WechatApiExecuteCgibinMaterialTests public class TestCase_ApiExecuteCgibinMaterialTests
{ {
[Fact(DisplayName = "[GET] /cgi-bin/material/get_materialcount")] [Fact(DisplayName = "测试用例:调用 API [GET] /cgi-bin/material/get_materialcount")]
public async Task CgibinMaterialGetMaterialCountTest() public async Task TestExecuteCgibinMaterialGetMaterialCount()
{ {
var request = new Models.CgibinMaterialGetMaterialCountRequest() var request = new Models.CgibinMaterialGetMaterialCountRequest()
{ {
@ -21,8 +21,8 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
Assert.True(response.IsSuccessful()); Assert.True(response.IsSuccessful());
} }
[Fact(DisplayName = "[POST] /cgi-bin/material/batchget_material")] [Fact(DisplayName = "测试用例:调用 API [POST] /cgi-bin/material/batchget_material")]
public async Task CgibinMaterialBatchGetMaterialTest() public async Task TestExecuteCgibinMaterialBatchGetMaterial()
{ {
var request = new Models.CgibinMaterialBatchGetMaterialRequest() var request = new Models.CgibinMaterialBatchGetMaterialRequest()
{ {

View File

@ -7,10 +7,10 @@ using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
{ {
public class WechatApiExecuteCgibinMediaTests public class TestCase_ApiExecuteCgibinMediaTests
{ {
[Fact(DisplayName = "[POST] /cgi-bin/media/upload")] [Fact(DisplayName = "测试用例:调用 API [POST] /cgi-bin/media/upload")]
public async Task CgibinMediaUploadTest() public async Task TestExecuteCgibinMediaUpload()
{ {
var request = new Models.CgibinMediaUploadRequest() var request = new Models.CgibinMediaUploadRequest()
{ {
@ -26,8 +26,8 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
Assert.NotNull(response.MediaId); Assert.NotNull(response.MediaId);
} }
[Fact(DisplayName = "[GET] /cgi-bin/media/get")] [Fact(DisplayName = "测试用例:调用 API [GET] /cgi-bin/media/get")]
public async Task CgibinMediaGetTest() public async Task TestExecuteCgibinMediaGet()
{ {
var request = new Models.CgibinMediaGetRequest() var request = new Models.CgibinMediaGetRequest()
{ {
@ -39,8 +39,8 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
Assert.True(response.IsSuccessful()); Assert.True(response.IsSuccessful());
} }
[Fact(DisplayName = "[POST] /cgi-bin/media/uploadimg")] [Fact(DisplayName = "测试用例:调用 API [POST] /cgi-bin/media/uploadimg")]
public async Task CgibinMediaUploadImageTest() public async Task TestExecuteCgibinMediaUploadImage()
{ {
var request = new Models.CgibinMediaUploadImageRequest() var request = new Models.CgibinMediaUploadImageRequest()
{ {

View File

@ -7,10 +7,10 @@ using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
{ {
public class WechatApiExecuteCgibinMessageMassTests public class TestCase_ApiExecuteCgibinMessageMassTests
{ {
[Fact(DisplayName = "[POST] /cgi-bin/message/mass/send")] [Fact(DisplayName = "测试用例:调用 API [POST] /cgi-bin/message/mass/send")]
public async Task CgibinMessageMassSendTest() public async Task TestExecuteCgibinMessageMassSend()
{ {
var request = new Models.CgibinMessageMassSendRequest() var request = new Models.CgibinMessageMassSendRequest()
{ {
@ -27,8 +27,8 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
Assert.True(response.MessageId > 0); Assert.True(response.MessageId > 0);
} }
[Fact(DisplayName = "[POST] /cgi-bin/message/mass/preview")] [Fact(DisplayName = "测试用例:调用 API [POST] /cgi-bin/message/mass/preview")]
public async Task CgibinMessageMassPreviewTest() public async Task TestExecuteCgibinMessageMassPreview()
{ {
var request = new Models.CgibinMessageMassPreviewRequest() var request = new Models.CgibinMessageMassPreviewRequest()
{ {
@ -45,8 +45,8 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
Assert.True(response.IsSuccessful()); Assert.True(response.IsSuccessful());
} }
[Fact(DisplayName = "[GET] /cgi-bin/message/mass/speed/get")] [Fact(DisplayName = "测试用例:调用 API [GET] /cgi-bin/message/mass/speed/get")]
public async Task CgibinMessageMassSpeedGetTest() public async Task TestExecuteCgibinMessageMassSpeedGet()
{ {
var request = new Models.CgibinMessageMassSpeedGetRequest() var request = new Models.CgibinMessageMassSpeedGetRequest()
{ {
@ -58,8 +58,8 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
Assert.True(response.SpeedValue > 0); Assert.True(response.SpeedValue > 0);
} }
[Fact(DisplayName = "[POST] /cgi-bin/message/mass/speed/set")] [Fact(DisplayName = "测试用例:调用 API [POST] /cgi-bin/message/mass/speed/set")]
public async Task CgibinMessageMassSpeedSetTest() public async Task TestExecuteCgibinMessageMassSpeedSet()
{ {
var request = new Models.CgibinMessageMassSpeedSetRequest() var request = new Models.CgibinMessageMassSpeedSetRequest()
{ {

View File

@ -7,10 +7,10 @@ using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
{ {
public class WechatApiExecuteCgibinQrcodeTests public class TestCase_ApiExecuteCgibinQrcodeTests
{ {
[Fact(DisplayName = "[POST] /cgi-bin/qrcode/create")] [Fact(DisplayName = "测试用例:调用 API [POST] /cgi-bin/qrcode/create")]
public async Task CgibinQrcodeCreateTest() public async Task TestExecuteCgibinQrcodeCreate()
{ {
var request = new Models.CgibinQrcodeCreateRequest() var request = new Models.CgibinQrcodeCreateRequest()
{ {

View File

@ -7,10 +7,10 @@ using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
{ {
public class WechatApiExecuteCgibinTagsTests public class TestCase_ApiExecuteCgibinTagsTests
{ {
[Fact(DisplayName = "[POST] /cgi-bin/tags/create")] [Fact(DisplayName = "测试用例:调用 API [POST] /cgi-bin/tags/create")]
public async Task CgibinTagsCreateTest() public async Task TestExecuteCgibinTagsCreate()
{ {
var request = new Models.CgibinTagsCreateRequest() var request = new Models.CgibinTagsCreateRequest()
{ {
@ -26,8 +26,8 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
Assert.Equal(request.Tag.Name, response.Tag.Name); Assert.Equal(request.Tag.Name, response.Tag.Name);
} }
[Fact(DisplayName = "[POST] /cgi-bin/tags/get")] [Fact(DisplayName = "测试用例:调用 API [POST] /cgi-bin/tags/get")]
public async Task CgibinTagsGetTest() public async Task TestExecuteCgibinTagsGet()
{ {
var request = new Models.CgibinTagsGetRequest() var request = new Models.CgibinTagsGetRequest()
{ {

View File

@ -7,10 +7,10 @@ using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
{ {
public class WechatApiExecuteCgibinTests public class TestCase_ApiExecuteCgibinTests
{ {
[Fact(DisplayName = "[GET] /cgi-bin/token")] [Fact(DisplayName = "测试用例:调用 API [GET] /cgi-bin/token")]
public async Task CgibinTokenTest() public async Task TestExecuteCgibinToken()
{ {
var request = new Models.CgibinTokenRequest(); var request = new Models.CgibinTokenRequest();
var response = await TestClients.Instance.ExecuteCgibinTokenAsync(request); var response = await TestClients.Instance.ExecuteCgibinTokenAsync(request);
@ -18,8 +18,8 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
Assert.NotNull(response.AccessToken); Assert.NotNull(response.AccessToken);
} }
[Fact(DisplayName = "[GET] /cgi-bin/ticket/getticket")] [Fact(DisplayName = "测试用例:调用 API [GET] /cgi-bin/ticket/getticket")]
public async Task CgibinTicketGetTicketTest() public async Task TestExecuteCgibinTicketGetTicket()
{ {
var request = new Models.CgibinTicketGetTicketRequest() var request = new Models.CgibinTicketGetTicketRequest()
{ {
@ -30,8 +30,8 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
Assert.NotNull(response.Ticket); Assert.NotNull(response.Ticket);
} }
[Fact(DisplayName = "[GET] /cgi-bin/getcallbackip")] [Fact(DisplayName = "测试用例:调用 API [GET] /cgi-bin/getcallbackip")]
public async Task CgibinGetCallbackIpTest() public async Task TestExecuteCgibinGetCallbackIp()
{ {
var request = new Models.CgibinGetCallbackIpRequest() var request = new Models.CgibinGetCallbackIpRequest()
{ {
@ -42,8 +42,8 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
Assert.NotEmpty(response.IPList); Assert.NotEmpty(response.IPList);
} }
[Fact(DisplayName = "[GET] /cgi-bin/get_api_domain_ip")] [Fact(DisplayName = "测试用例:调用 API [GET] /cgi-bin/get_api_domain_ip")]
public async Task CgibinGetApiDomainIpTest() public async Task TestExecuteCgibinGetApiDomainIp()
{ {
var request = new Models.CgibinGetApiDomainIpRequest() var request = new Models.CgibinGetApiDomainIpRequest()
{ {
@ -54,8 +54,8 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
Assert.NotEmpty(response.IPList); Assert.NotEmpty(response.IPList);
} }
[Fact(DisplayName = "[POST] /cgi-bin/clear_quota")] [Fact(DisplayName = "测试用例:调用 API [POST] /cgi-bin/clear_quota")]
public async Task CgibinClearQuotaTest() public async Task TestExecuteCgibinClearQuota()
{ {
var request = new Models.CgibinClearQuotaRequest() var request = new Models.CgibinClearQuotaRequest()
{ {

View File

@ -7,10 +7,10 @@ using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
{ {
public class WechatApiExecuteCgibinUserTests public class TestCase_ApiExecuteCgibinUserTests
{ {
[Fact(DisplayName = "[GET] /cgi-bin/user/info")] [Fact(DisplayName = "测试用例:调用 API [GET] /cgi-bin/user/info")]
public async Task CgibinUserInfoTest() public async Task TestExecuteCgibinUserInfo()
{ {
var request = new Models.CgibinUserInfoRequest() var request = new Models.CgibinUserInfoRequest()
{ {
@ -24,8 +24,8 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
Assert.True(response.IsSubscribed); Assert.True(response.IsSubscribed);
} }
[Fact(DisplayName = "[POST] /cgi-bin/user/info/batchget")] [Fact(DisplayName = "测试用例:调用 API [POST] /cgi-bin/user/info/batchget")]
public async Task CgibinUserInfoBatchGetTest() public async Task TestExecuteCgibinUserInfoBatchGet()
{ {
var request = new Models.CgibinUserInfoBatchGetRequest() var request = new Models.CgibinUserInfoBatchGetRequest()
{ {
@ -43,8 +43,8 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
Assert.True(response.UserList.First().IsSubscribed); Assert.True(response.UserList.First().IsSubscribed);
} }
[Fact(DisplayName = "[POST] /cgi-bin/user/info/updateremark")] [Fact(DisplayName = "测试用例:调用 API [POST] /cgi-bin/user/info/updateremark")]
public async Task CgibinUserInfoUpdateRemarkTest() public async Task TestExecuteCgibinUserInfoUpdateRemark()
{ {
var request = new Models.CgibinUserInfoUpdateRemarkRequest() var request = new Models.CgibinUserInfoUpdateRemarkRequest()
{ {
@ -57,8 +57,8 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
Assert.Equal(0, response.ErrorCode); Assert.Equal(0, response.ErrorCode);
} }
[Fact(DisplayName = "[GET] /cgi-bin/user/get")] [Fact(DisplayName = "测试用例:调用 API [GET] /cgi-bin/user/get")]
public async Task CgibinUserGetTest() public async Task TestExecuteCgibinUserGet()
{ {
var request = new Models.CgibinUserGetRequest() var request = new Models.CgibinUserGetRequest()
{ {

View File

@ -7,10 +7,10 @@ using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
{ {
public class WechatApiExecuteSemanticTests public class TestCase_ApiExecuteSemanticTests
{ {
[Fact(DisplayName = "[POST] /semantic/semproxy/search")] [Fact(DisplayName = "测试用例:调用 API [POST] /semantic/semproxy/search")]
public async Task SemanticSemproxySearchRestaurantTest() public async Task TestExecuteSemanticSemproxySearchRestaurant()
{ {
var request = new Models.SemanticSemproxySearchRequest() var request = new Models.SemanticSemproxySearchRequest()
{ {

View File

@ -6,10 +6,10 @@ using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
{ {
public class WechatApiExecuteSnsWithAccessTokenTests public class TestCase_ApiExecuteSnsWithAccessTokenTests
{ {
[Fact(DisplayName = "[GET] /sns/userinfo")] [Fact(DisplayName = "测试用例:调用 API [GET] /sns/userinfo")]
public async Task SnsUserInfoTest() public async Task TestExecuteSnsUserInfo()
{ {
var request = new Models.SnsUserInfoRequest() var request = new Models.SnsUserInfoRequest()
{ {
@ -22,8 +22,8 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
Assert.NotNull(response.Nickname); Assert.NotNull(response.Nickname);
} }
[Fact(DisplayName = "[GET] /sns/auth")] [Fact(DisplayName = "测试用例:调用 API [GET] /sns/auth")]
public async Task SnsAuthTest() public async Task TestExecuteSnsAuth()
{ {
var request = new Models.SnsAuthRequest() var request = new Models.SnsAuthRequest()
{ {

View File

@ -6,10 +6,10 @@ using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
{ {
public class WechatApiExecuteSnsWithAppSecretTests public class TestCase_ApiExecuteSnsWithAppSecretTests
{ {
[Fact(DisplayName = "[GET] /sns/oauth2/access_token")] [Fact(DisplayName = "测试用例:调用 API [GET] /sns/oauth2/access_token")]
public async Task SnsOAuth2AccessTokenTest() public async Task TestExecuteSnsOAuth2AccessToken()
{ {
var request = new Models.SnsOAuth2AccessTokenRequest() var request = new Models.SnsOAuth2AccessTokenRequest()
{ {
@ -22,8 +22,8 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
Assert.NotNull(response.OpenId); Assert.NotNull(response.OpenId);
} }
[Fact(DisplayName = "[GET] /sns/oauth2/refresh_token")] [Fact(DisplayName = "测试用例:调用 API [GET] /sns/oauth2/refresh_token")]
public async Task SnsOAuth2RefreshTokenTest() public async Task TestExecuteSnsOAuth2RefreshToken()
{ {
var request = new Models.SnsOAuth2RefreshTokenRequest() var request = new Models.SnsOAuth2RefreshTokenRequest()
{ {
@ -35,8 +35,8 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
Assert.NotNull(response.RefreshToken); Assert.NotNull(response.RefreshToken);
} }
[Fact(DisplayName = "[GET] /sns/jscode2session")] [Fact(DisplayName = "测试用例:调用 API [GET] /sns/jscode2session")]
public async Task SnsJsCode2SessionTest() public async Task TestExecuteSnsJsCode2Session()
{ {
var request = new Models.SnsJsCode2SessionRequest() var request = new Models.SnsJsCode2SessionRequest()
{ {

View File

@ -7,10 +7,10 @@ using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
{ {
public class WechatApiExecuteWxaApiTests public class TestCase_ApiExecuteWxaApiTests
{ {
[Fact(DisplayName = "[POST] /wxaapi/log/jserr_list")] [Fact(DisplayName = "测试用例:调用 API [POST] /wxaapi/log/jserr_list")]
public async Task WxaApiLogGetPerformanceTest() public async Task TestExecuteWxaApiLogGetPerformance()
{ {
var request = new Models.WxaApiLogGetPerformanceRequest() var request = new Models.WxaApiLogGetPerformanceRequest()
{ {
@ -26,8 +26,8 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
Assert.NotEmpty(response.DefaultTimeData.DataList); Assert.NotEmpty(response.DefaultTimeData.DataList);
} }
[Fact(DisplayName = "[GET] /wxaapi/log/get_scene")] [Fact(DisplayName = "测试用例:调用 API [GET] /wxaapi/log/get_scene")]
public async Task WxaApiLogGetSceneTest() public async Task TestExecuteWxaApiLogGetScene()
{ {
var request = new Models.WxaApiLogGetSceneRequest() var request = new Models.WxaApiLogGetSceneRequest()
{ {
@ -39,8 +39,8 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
Assert.NotEmpty(response.SceneDataList); Assert.NotEmpty(response.SceneDataList);
} }
[Fact(DisplayName = "[GET] /wxaapi/log/get_client_version")] [Fact(DisplayName = "测试用例:调用 API [GET] /wxaapi/log/get_client_version")]
public async Task WxaApiLogGetClientVersionTest() public async Task TestExecuteWxaApiLogGetClientVersion()
{ {
var request = new Models.WxaApiLogGetClientVersionRequest() var request = new Models.WxaApiLogGetClientVersionRequest()
{ {

View File

@ -9,14 +9,14 @@ using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
{ {
public class WechatApiDeclarationTests public class TestCase_CodeReviewAnalyzer
{ {
private static readonly Assembly _assembly = Assembly.Load("SKIT.FlurlHttpClient.Wechat.Api"); private Assembly SourceAssembly { get; } = Assembly.Load("SKIT.FlurlHttpClient.Wechat.Api");
[Fact(DisplayName = "验证 API 模型命名")] [Fact(DisplayName = "代码评审:分析 API 模型命名")]
public void ApiModelsNamingTest() public void TestApiModelsNaming()
{ {
CodeStyleUtil.VerifyApiModelsNaming(_assembly, out var ex); CodeStyleUtil.VerifyApiModelsNaming(SourceAssembly, out var ex);
if (ex != null) if (ex != null)
throw ex; throw ex;
@ -24,11 +24,11 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
Assert.Null(ex); Assert.Null(ex);
} }
[Fact(DisplayName = "验证 API 模型定义")] [Fact(DisplayName = "代码评审:分析 API 模型定义")]
public void ApiModelsDefinitionTest() public void TestApiModelsDefinition()
{ {
string workdir = Path.Combine(TestConfigs.ProjectTestDirectory, "ModelSamples"); string workdir = Path.Combine(TestConfigs.ProjectTestDirectory, "ModelSamples");
CodeStyleUtil.VerifyApiModelsDefinition(_assembly, workdir, out var ex); CodeStyleUtil.VerifyApiModelsDefinition(SourceAssembly, workdir, out var ex);
if (ex != null) if (ex != null)
throw ex; throw ex;
@ -36,11 +36,11 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
Assert.Null(ex); Assert.Null(ex);
} }
[Fact(DisplayName = "验证 API 事件定义")] [Fact(DisplayName = "代码评审:分析 API 事件定义")]
public void ApiEventsDefinitionTest() public void TestApiEventsDefinition()
{ {
string workdir = Path.Combine(TestConfigs.ProjectTestDirectory, "EventSamples"); string workdir = Path.Combine(TestConfigs.ProjectTestDirectory, "EventSamples");
CodeStyleUtil.VerifyApiEventsDefinition(_assembly, workdir, out var ex); CodeStyleUtil.VerifyApiEventsDefinition(SourceAssembly, workdir, out var ex);
if (ex != null) if (ex != null)
throw ex; throw ex;
@ -48,10 +48,10 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
Assert.Null(ex); Assert.Null(ex);
} }
[Fact(DisplayName = "验证 API 接口命名")] [Fact(DisplayName = "代码评审:分析 API 接口命名")]
public void ApiExtensionsNamingTest() public void TestApiExtensionsNaming()
{ {
CodeStyleUtil.VerifyApiExtensionsNaming(_assembly, out var ex); CodeStyleUtil.VerifyApiExtensionsNaming(SourceAssembly, out var ex);
if (ex != null) if (ex != null)
throw ex; throw ex;
@ -59,8 +59,8 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
Assert.Null(ex); Assert.Null(ex);
} }
[Fact(DisplayName = "验证代码规范")] [Fact(DisplayName = "代码评审:分析代码规范")]
public void CodeStyleTest() public void TestCodeStyle()
{ {
string workdir = Path.Combine(TestConfigs.ProjectSourceDirectory); string workdir = Path.Combine(TestConfigs.ProjectSourceDirectory);
CodeStyleUtil.VerifySourceCodeStyle(workdir, out var ex); CodeStyleUtil.VerifySourceCodeStyle(workdir, out var ex);

View File

@ -7,10 +7,10 @@ using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
{ {
public class WechatApiExecuteCgibinExpressTests public class TestCase_DeliveryRequestSignatureTests
{ {
[Fact(DisplayName = "即时配送请求签名")] [Fact(DisplayName = "测试用例:即时配送请求签名")]
public async Task DeliverySignatureTest() public async Task TestDeliveryRequestSignature()
{ {
var client = new WechatApiClient(new WechatApiClientOptions() var client = new WechatApiClient(new WechatApiClientOptions()
{ {

View File

@ -8,10 +8,10 @@ using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
{ {
public class WechatApiEventDeserializationTests public class TestCase_EventDeserializationTests
{ {
[Fact(DisplayName = "获取事件消息类型")] [Fact(DisplayName = "测试用例:获取事件消息类型")]
public void GetEventMessageTypeTest() public void TestGetEventMessageType()
{ {
string xml = "<xml><ToUserName><![CDATA[toUser]]></ToUserName><FromUserName><![CDATA[fromUser]]></FromUserName><CreateTime>1348831860</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[this is a test]]></Content><MsgId>1234567890123456</MsgId></xml>"; string xml = "<xml><ToUserName><![CDATA[toUser]]></ToUserName><FromUserName><![CDATA[fromUser]]></FromUserName><CreateTime>1348831860</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[this is a test]]></Content><MsgId>1234567890123456</MsgId></xml>";
@ -24,8 +24,8 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
Assert.Equal("TEXT", eventModel.MessageType, ignoreCase: true); Assert.Equal("TEXT", eventModel.MessageType, ignoreCase: true);
} }
[Fact(DisplayName = "反序列化 TEXT 事件")] [Fact(DisplayName = "测试用例:反序列化 TEXT 事件")]
public void DeserializeTextMessageEventTest() public void TestDeserializeTextMessageEvent()
{ {
string xml = "<xml><ToUserName><![CDATA[toUser]]></ToUserName><FromUserName><![CDATA[fromUser]]></FromUserName><CreateTime>1348831860</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[this is a test]]></Content><MsgId>1234567890123456</MsgId></xml>"; string xml = "<xml><ToUserName><![CDATA[toUser]]></ToUserName><FromUserName><![CDATA[fromUser]]></FromUserName><CreateTime>1348831860</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[this is a test]]></Content><MsgId>1234567890123456</MsgId></xml>";

View File

@ -8,10 +8,10 @@ using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
{ {
public class WechatApiEventVerificationTests public class TestCase_EventVerificationTests
{ {
[Fact(DisplayName = "验签并解密回调数据")] [Fact(DisplayName = "测试用例:验签并解密回调数据")]
public void GetEventMessageTypeTest() public void TestVerifyEvent()
{ {
string callbacMsgSig = "477715d11cdb4164915debcba66cb864d751f3e6"; string callbacMsgSig = "477715d11cdb4164915debcba66cb864d751f3e6";
string callbacTimeStamp = "1409659813"; string callbacTimeStamp = "1409659813";

View File

@ -0,0 +1,31 @@
using System;
using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
{
public class TestCase_HashUtilityTests
{
[Fact(DisplayName = "测试用例SHA-1 信息摘要")]
public void TestSHA1Hash()
{
string rawData = "jsapi_ticket=HoagFKDcsGMVCIY2vOjf9nGrZ3eaM0qXs5ROFN_3k_HrGc0VocemA6wMXkvrL-Ei4IitXxwKF62CJWR8mWXZ3Q&noncestr=e7b435f73835402da44f16640ddc8696&timestamp=1621348162&url=https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign";
string actualHash = Utilities.SHA1Utility.Hash(rawData);
string expectedHash = "b214ea1f8ae019c207f8c6ffb843c8474cbab28c";
Assert.Equal(expectedHash, actualHash, ignoreCase: true);
}
[Fact(DisplayName = "测试用例HMAC-SHA-256 消息认证码")]
public void TestHMACHashWithSHA1()
{
string secret = "zNLgAGgqsEWJOg1nFVaO5r7fAlIQxr1u";
string rawData = "appid=wx1234567&offer_id=12345678&openid=odkx20ENSNa2w5y3g_qOkOvBNM1g&pf=android&ts=1507530737&zone_id=1&org_loc=/cgi-bin/midas/getbalance&method=POST&secret=zNLgAGgqsEWJOg1nFVaO5r7fAlIQxr1u";
string actualHash = Utilities.HMACUtility.HashWithSHA256(secret, rawData);
string expectedHash = "1ad64e8dcb2ec1dc486b7fdf01f4a15159fc623dc3422470e51cf6870734726b";
Assert.Equal(expectedHash, actualHash, ignoreCase: true);
}
}
}

View File

@ -7,10 +7,10 @@ using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
{ {
public class WechatApiExecuteCgibinMidasTests public class TestCase_MidasRequestSignatureTests
{ {
[Fact(DisplayName = "米大师请求签名")] [Fact(DisplayName = "测试用例:米大师请求签名")]
public async Task MidasSigTest() public async Task TestMidasRequestSignature()
{ {
var client = new WechatApiClient(new WechatApiClientOptions() var client = new WechatApiClient(new WechatApiClientOptions()
{ {

View File

@ -8,10 +8,10 @@ using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
{ {
public class WechatApiWxBizMsgCryptorTests public class TestCase_WxBizMsgCryptorUtilityTests
{ {
[Fact(DisplayName = "验签并解密回调数据")] [Fact(DisplayName = "试用例:验签并解密回调数据")]
public void VerifyAndDecryptEventTest() public void TestVerifyAndDecryptEvent()
{ {
string token = "QDG6eK"; string token = "QDG6eK";
string appId = "wx5823bf96d3bd56c7"; string appId = "wx5823bf96d3bd56c7";
@ -29,8 +29,8 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
Assert.True(Utilities.WxBizMsgCryptor.VerifySignature(token, reqTimeStamp, reqNonce, reqCipherText, reqMsgSig)); Assert.True(Utilities.WxBizMsgCryptor.VerifySignature(token, reqTimeStamp, reqNonce, reqCipherText, reqMsgSig));
} }
[Fact(DisplayName = "验签回调数据")] [Fact(DisplayName = "试用例:验签回调数据")]
public void VerifyEventTest() public void TestVerifyEvent()
{ {
string token = "ovAkP0Tb"; string token = "ovAkP0Tb";
string reqMsgSig = "8128e41a38892d814e4aa67753425da9dc8ec2b3"; string reqMsgSig = "8128e41a38892d814e4aa67753425da9dc8ec2b3";

View File

@ -8,8 +8,9 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
{ {
static TestConfigs() static TestConfigs()
{ {
// NOTICE: 请在项目根目录下按照 appsettings.json 的格式新建 appsettings.local.json 填入测试参数。 // NOTICE: 请在项目根目录下按照 appsettings.json 的格式新建 appsettings.local.json 填入测试参数。
// WARN: 敏感信息请不要提交到 git // WARNING: 请在 DEBUG 模式下运行测试用例。
// WARNING: 敏感信息请不要提交到 git
try try
{ {
@ -17,13 +18,13 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
using var jdoc = JsonDocument.Parse(stream); using var jdoc = JsonDocument.Parse(stream);
var config = jdoc.RootElement.GetProperty("TestConfig"); var config = jdoc.RootElement.GetProperty("TestConfig");
WechatAppId = config.GetProperty("AppId").GetString(); WechatAppId = config.GetProperty("AppId").GetString()!;
WechatAppSecret = config.GetProperty("AppSecret").GetString(); WechatAppSecret = config.GetProperty("AppSecret").GetString()!;
WechatAccessToken = config.GetProperty("AccessToken").GetString(); WechatAccessToken = config.GetProperty("AccessToken").GetString()!;
WechatOpenId = config.GetProperty("OpenId").GetString(); WechatOpenId = config.GetProperty("OpenId").GetString()!;
ProjectSourceDirectory = jdoc.RootElement.GetProperty("ProjectSourceDirectory").GetString(); ProjectSourceDirectory = jdoc.RootElement.GetProperty("ProjectSourceDirectory").GetString()!;
ProjectTestDirectory = jdoc.RootElement.GetProperty("ProjectTestDirectory").GetString(); ProjectTestDirectory = jdoc.RootElement.GetProperty("ProjectTestDirectory").GetString()!;
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@ -1,44 +0,0 @@
using System;
using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
{
public class WechatApiSecurityTests
{
[Fact(DisplayName = "信息摘要SHA-1")]
public void Sha1HashTest()
{
string rawData = "jsapi_ticket=HoagFKDcsGMVCIY2vOjf9nGrZ3eaM0qXs5ROFN_3k_HrGc0VocemA6wMXkvrL-Ei4IitXxwKF62CJWR8mWXZ3Q&noncestr=e7b435f73835402da44f16640ddc8696&timestamp=1621348162&url=https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign";
string actualHash = Utilities.SHA1Utility.Hash(rawData);
string expectedHash = "b214ea1f8ae019c207f8c6ffb843c8474cbab28c";
Assert.Equal(expectedHash, actualHash, ignoreCase: true);
}
[Fact(DisplayName = "信息摘要HMAC-SHA-256")]
public void HmacSha1HashTest()
{
string secret = "zNLgAGgqsEWJOg1nFVaO5r7fAlIQxr1u";
string rawData = "appid=wx1234567&offer_id=12345678&openid=odkx20ENSNa2w5y3g_qOkOvBNM1g&pf=android&ts=1507530737&zone_id=1&org_loc=/cgi-bin/midas/getbalance&method=POST&secret=zNLgAGgqsEWJOg1nFVaO5r7fAlIQxr1u";
string actualHash = Utilities.HMACSHA256Utility.Hash(secret, rawData);
string expectedHash = "1ad64e8dcb2ec1dc486b7fdf01f4a15159fc623dc3422470e51cf6870734726b";
Assert.Equal(expectedHash, actualHash, ignoreCase: true);
}
[Fact(DisplayName = "AES-CBC 解密")]
public void AesCbcDecryptTest()
{
string iv = "KEWv/gyiIwAfHvjrLeaX6w==";
string key = "YZJqKnNFi0KAiKUc0ggC2g==";
string cipherText = "Gu2PVnxVWl+jK4F8c0liGxfkB5Bj3m5HRvwgEIk1Yb+36RZ3Bg7YmUnud/ooiHz0PQroipsH7GCjlGwUeT04NwmrFaP1y3dRYPLpS43ed9QZWcFIFo+8vTs3Zco6S98DUvaNEAs8duhz/BzfBOZaIHMziRqEtPFI0ZDzCgJluBirJ6Wl3UkygZ5/QLo3KA53qGdip7K48Rq8XbCwuidTCw==";
string expectedPlainData = "{\"phoneNumber\":\"186****5613\",\"purePhoneNumber\":\"186****5613\",\"countryCode\":\"86\",\"watermark\":{\"timestamp\":1634545675,\"appid\":\"wxc****17e87e0e0a7\"}}";
string actualPlainData = Utilities.AESUtility.DecryptWithCBC(encodingKey: key, encodingIV: iv, encodingCipherText: cipherText);
Assert.Equal(expectedPlainData, actualPlainData, ignoreCase: true);
}
}
}

View File

@ -2,7 +2,7 @@
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
{ {
public class TestCase_AesUtilityTests public class TestCase_AESUtilityTests
{ {
[Fact(DisplayName = "测试用例AES-GCM 解密")] [Fact(DisplayName = "测试用例AES-GCM 解密")]
public void TestAESGCMDecrypt() public void TestAESGCMDecrypt()

View File

@ -3,7 +3,7 @@ using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
{ {
public class TestCase_RsaUtilityTests public class TestCase_RSAUtilityTests
{ {
// 此处测试的 RSA 证书/公钥/私钥是自签名生成的,仅供执行 RSA 相关的单元测试,不能用于调用微信支付 API。 // 此处测试的 RSA 证书/公钥/私钥是自签名生成的,仅供执行 RSA 相关的单元测试,不能用于调用微信支付 API。
private const string RSA_CERT_SN = "3050f72e2dce03e7efe49557dd231d176649afbd"; private const string RSA_CERT_SN = "3050f72e2dce03e7efe49557dd231d176649afbd";