feat(tenpayv3): 升级核心库

This commit is contained in:
Fu Diwei 2021-08-20 22:10:16 +08:00
parent effc660268
commit c0b24b223f
34 changed files with 673 additions and 261 deletions

View File

@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace Newtonsoft.Json.Converters
{
internal class JsonTypedStringArrayConverter : 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 existingValue;
if (value.StartsWith("[") && value.EndsWith("["))
return JsonConvert.DeserializeObject<string[]>(value);
if (string.IsNullOrEmpty(value))
return new string[0];
else
return new string[1] { value };
}
throw new JsonReaderException();
}
public override void WriteJson(JsonWriter writer, string[]? value, JsonSerializer serializer)
{
if (value != null)
writer.WriteValue(JsonConvert.SerializeObject(value, Formatting.None));
else
writer.WriteNull();
}
}
}

View File

@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace Newtonsoft.Json.Converters
{
internal class YesOrNoBooleanConverter : JsonConverter<bool>
{
private readonly JsonConverter<bool?> _converter = new YesOrNoNullableBooleanConverter();
public override bool CanRead
{
get { return true; }
}
public override bool CanWrite
{
get { return true; }
}
public override bool ReadJson(JsonReader reader, Type objectType, bool existingValue, bool hasExistingValue, JsonSerializer serializer)
{
return _converter.ReadJson(reader, objectType, existingValue, hasExistingValue, serializer) ?? default;
}
public override void WriteJson(JsonWriter writer, bool value, JsonSerializer serializer)
{
_converter.WriteJson(writer, value, serializer);
}
}
}

View File

@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace Newtonsoft.Json.Converters
{
internal class YesOrNoNullableBooleanConverter : JsonConverter<bool?>
{
public override bool CanRead
{
get { return true; }
}
public override bool CanWrite
{
get { return true; }
}
public override bool? ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, bool? existingValue, bool hasExistingValue, Newtonsoft.Json.JsonSerializer serializer)
{
if (reader.TokenType == Newtonsoft.Json.JsonToken.Null)
{
return existingValue;
}
else if (reader.TokenType == Newtonsoft.Json.JsonToken.Boolean)
{
return serializer.Deserialize<bool>(reader);
}
else if (reader.TokenType == Newtonsoft.Json.JsonToken.String)
{
string? value = serializer.Deserialize<string>(reader);
if (value == null)
return existingValue;
if ("Y".Equals(value))
return true;
else if ("N".Equals(value))
return false;
}
throw new Newtonsoft.Json.JsonReaderException();
}
public override void WriteJson(Newtonsoft.Json.JsonWriter writer, bool? value, Newtonsoft.Json.JsonSerializer serializer)
{
if (value.HasValue)
writer.WriteValue(value.Value ? "Y" : "N");
else
writer.WriteNull();
}
}
}

View File

@ -5,9 +5,9 @@ using Newtonsoft.Json.Converters;
namespace Newtonsoft.Json.Converters
{
internal class CommonWithoutSeparatorsDateTimeOffsetConverter : JsonConverter<DateTimeOffset>
internal class PureDigitalTextDateTimeOffsetConverter : JsonConverter<DateTimeOffset>
{
private readonly JsonConverter<DateTimeOffset?> _converter = new CommonWithoutSeparatorsNullableDateTimeOffsetConverter();
private readonly JsonConverter<DateTimeOffset?> _converter = new PureDigitalTextNullableDateTimeOffsetConverter();
public override bool CanRead
{

View File

@ -5,7 +5,7 @@ using Newtonsoft.Json.Converters;
namespace Newtonsoft.Json.Converters
{
internal class CommonWithoutSeparatorsNullableDateTimeOffsetConverter : JsonConverter<DateTimeOffset?>
internal class PureDigitalTextNullableDateTimeOffsetConverter : JsonConverter<DateTimeOffset?>
{
internal const string DATETIME_FORMAT = "yyyyMMddHHmmss";

View File

@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace Newtonsoft.Json.Converters
{
internal class JsonTypedStringIListConverter : JsonConverter<IList<string>?>
{
private readonly JsonConverter<List<string>?> _converter = new JsonTypedStringListConverter();
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

@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace Newtonsoft.Json.Converters
{
internal class JsonTypedStringListConverter : JsonConverter<List<string>?>
{
public override bool CanRead
{
get { return true; }
}
public override bool CanWrite
{
get { return true; }
}
public override List<string>? ReadJson(JsonReader reader, Type objectType, List<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 existingValue;
return JsonConvert.DeserializeObject<List<string>>(value);
}
throw new JsonReaderException();
}
public override void WriteJson(JsonWriter writer, List<string>? value, JsonSerializer serializer)
{
if (value != null)
writer.WriteValue(JsonConvert.SerializeObject(value, Formatting.None));
else
writer.WriteNull();
}
}
}

View File

@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace Newtonsoft.Json.Converters
{
internal class StringTypedStringIListConverter : JsonConverter<IList<string>?>
{
private readonly JsonConverter<List<string>?> _converter = new StringTypedStringListConverter();
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

@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace Newtonsoft.Json.Converters
{
internal class StringTypedStringListConverter : JsonConverter<List<string>?>
{
public override bool CanRead
{
get { return true; }
}
public override bool CanWrite
{
get { return true; }
}
public override List<string>? ReadJson(JsonReader reader, Type objectType, List<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 existingValue;
return value.Split(',').ToList();
}
throw new JsonReaderException();
}
public override void WriteJson(JsonWriter writer, List<string>? value, JsonSerializer serializer)
{
if (value != null)
writer.WriteValue(string.Join(",", value));
else
writer.WriteNull();
}
}
}

View File

@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace System.Text.Json.Converters
{
internal class JsonTypedStringArrayConverter : JsonConverter<string[]?>
{
public override string[]? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.Null)
{
return null;
}
else if (reader.TokenType == JsonTokenType.String)
{
string? value = reader.GetString();
if (value == null)
return null;
if (value.StartsWith("[") && value.EndsWith("["))
return JsonSerializer.Deserialize<string[]>(value, options);
if (string.IsNullOrEmpty(value))
return new string[0];
else
return new string[1] { value };
}
throw new JsonException();
}
public override void Write(Utf8JsonWriter writer, string[]? value, JsonSerializerOptions options)
{
if (value != null)
writer.WriteStringValue(JsonSerializer.Serialize(value, options));
else
writer.WriteNullValue();
}
}
}

View File

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace System.Text.Json.Converters
{
internal class StringTypedBooleanConverter : JsonConverter<bool>
{
private readonly JsonConverter<bool?> _converter = new StringTypedNullableBooleanConverter();
public override bool Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return _converter.Read(ref reader, typeToConvert, options) ?? default;
}
public override void Write(Utf8JsonWriter writer, bool value, JsonSerializerOptions options)
{
_converter.Write(writer, value, options);
}
}
}

View File

@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace System.Text.Json.Converters
{
internal class StringTypedNullableBooleanConverter : JsonConverter<bool?>
{
public override bool? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.Null)
{
return null;
}
else if (reader.TokenType == JsonTokenType.True)
{
return true;
}
else if (reader.TokenType == JsonTokenType.False)
{
return false;
}
else if (reader.TokenType == JsonTokenType.String)
{
string? value = reader.GetString();
if (value == null)
return null;
if ("true".Equals(value, StringComparison.InvariantCultureIgnoreCase))
return true;
else if ("false".Equals(value, StringComparison.InvariantCultureIgnoreCase))
return false;
}
throw new JsonException();
}
public override void Write(Utf8JsonWriter writer, bool? value, JsonSerializerOptions options)
{
if (value.HasValue)
writer.WriteStringValue(value.Value ? "true" : "false");
else
writer.WriteNullValue();
}
}
}

View File

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace System.Text.Json.Converters
{
internal class YesOrNoBooleanConverter : JsonConverter<bool>
{
private readonly JsonConverter<bool?> _converter = new YesOrNoNullableBooleanConverter();
public override bool Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return _converter.Read(ref reader, typeToConvert, options) ?? default;
}
public override void Write(Utf8JsonWriter writer, bool value, JsonSerializerOptions options)
{
_converter.Write(writer, value, options);
}
}
}

View File

@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace System.Text.Json.Converters
{
internal class YesOrNoNullableBooleanConverter : JsonConverter<bool?>
{
public override bool? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.Null)
{
return null;
}
else if (reader.TokenType == JsonTokenType.True)
{
return true;
}
else if (reader.TokenType == JsonTokenType.False)
{
return false;
}
else if (reader.TokenType == System.Text.Json.JsonTokenType.String)
{
string? value = reader.GetString();
if (value == null)
return null;
if ("Y".Equals(value))
return true;
else if ("N".Equals(value))
return false;
}
throw new JsonException();
}
public override void Write(Utf8JsonWriter writer, bool? value, JsonSerializerOptions options)
{
if (value.HasValue)
writer.WriteStringValue(value.Value ? "Y" : "N");
else
writer.WriteNullValue();
}
}
}

View File

@ -5,9 +5,9 @@ using System.Text.Json.Serialization;
namespace System.Text.Json.Converters
{
internal class CommonWithoutSeparatorsDateTimeOffsetConverter : JsonConverter<DateTimeOffset>
internal class PureDigitalTextDateTimeOffsetConverter : JsonConverter<DateTimeOffset>
{
private readonly JsonConverter<DateTimeOffset?> _converter = new CommonWithoutSeparatorsNullableDateTimeOffsetConverter();
private readonly JsonConverter<DateTimeOffset?> _converter = new PureDigitalTextNullableDateTimeOffsetConverter();
public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{

View File

@ -5,9 +5,9 @@ using System.Text.Json.Serialization;
namespace System.Text.Json.Converters
{
internal class CommonWithoutSeparatorsNullableDateTimeOffsetConverter : JsonConverter<DateTimeOffset?>
internal class PureDigitalTextNullableDateTimeOffsetConverter : JsonConverter<DateTimeOffset?>
{
private const string DATETIME_FORMAT = Newtonsoft.Json.Converters.CommonWithoutSeparatorsNullableDateTimeOffsetConverter.DATETIME_FORMAT;
private const string DATETIME_FORMAT = Newtonsoft.Json.Converters.PureDigitalTextNullableDateTimeOffsetConverter.DATETIME_FORMAT;
public override DateTimeOffset? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{

View File

@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace System.Text.Json.Converters
{
internal class JsonTypedStringIListConverter : JsonConverter<IList<string>?>
{
private readonly JsonConverter<List<string>?> _converter = new JsonTypedStringListConverter();
public override IList<string>? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return _converter.Read(ref reader, typeToConvert, options);
}
public override void Write(Utf8JsonWriter writer, IList<string>? value, JsonSerializerOptions options)
{
_converter.Write(writer, ConvertIListToList(value), options);
}
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

@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace System.Text.Json.Converters
{
internal class JsonTypedStringListConverter : JsonConverter<List<string>?>
{
public override List<string>? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.Null)
{
return null;
}
else if (reader.TokenType == JsonTokenType.String)
{
string? value = reader.GetString();
if (value == null)
return null;
return JsonSerializer.Deserialize<List<string>>(value, options);
}
throw new JsonException();
}
public override void Write(Utf8JsonWriter writer, List<string>? value, JsonSerializerOptions options)
{
if (value != null)
writer.WriteStringValue(JsonSerializer.Serialize(value, options));
else
writer.WriteNullValue();
}
}
}

View File

@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace System.Text.Json.Converters
{
internal class StringTypedStringIListConverter : JsonConverter<IList<string>?>
{
private readonly JsonConverter<List<string>?> _converter = new StringTypedStringListConverter();
public override IList<string>? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return _converter.Read(ref reader, typeToConvert, options);
}
public override void Write(Utf8JsonWriter writer, IList<string>? value, JsonSerializerOptions options)
{
_converter.Write(writer, ConvertIListToList(value), options);
}
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

@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace System.Text.Json.Converters
{
internal class StringTypedStringListConverter : JsonConverter<List<string>?>
{
public override List<string>? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.Null)
{
return null;
}
else if (reader.TokenType == JsonTokenType.String)
{
string? value = reader.GetString();
if (value == null)
return null;
return value.Split(',').ToList();
}
throw new JsonException();
}
public override void Write(Utf8JsonWriter writer, List<string>? value, JsonSerializerOptions options)
{
if (value != null)
writer.WriteStringValue(string.Join(",", value));
else
writer.WriteNullValue();
}
}
}

View File

@ -76,9 +76,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Events
/// 获取或设置服务开启或解除授权时间。
/// </summary>
[Newtonsoft.Json.JsonProperty("openorclose_time")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.CommonWithoutSeparatorsNullableDateTimeOffsetConverter))]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.PureDigitalTextNullableDateTimeOffsetConverter))]
[System.Text.Json.Serialization.JsonPropertyName("openorclose_time")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.CommonWithoutSeparatorsNullableDateTimeOffsetConverter))]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.PureDigitalTextNullableDateTimeOffsetConverter))]
public DateTimeOffset? OpenOrCloseTime { get; set; }
}
}

View File

@ -62,9 +62,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Events
/// 获取或设置服务开启或解除授权时间。
/// </summary>
[Newtonsoft.Json.JsonProperty("openorclose_time")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.CommonWithoutSeparatorsNullableDateTimeOffsetConverter))]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.PureDigitalTextNullableDateTimeOffsetConverter))]
[System.Text.Json.Serialization.JsonPropertyName("openorclose_time")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.CommonWithoutSeparatorsNullableDateTimeOffsetConverter))]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.PureDigitalTextNullableDateTimeOffsetConverter))]
public DateTimeOffset? OpenOrCloseTime { get; set; }
}
}

View File

@ -72,9 +72,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Events
/// 获取或设置服务开始时间。
/// </summary>
[Newtonsoft.Json.JsonProperty("start_time")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.CommonWithoutSeparatorsDateTimeOffsetConverter))]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.PureDigitalTextDateTimeOffsetConverter))]
[System.Text.Json.Serialization.JsonPropertyName("start_time")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.CommonWithoutSeparatorsDateTimeOffsetConverter))]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.PureDigitalTextDateTimeOffsetConverter))]
public DateTimeOffset StartTime { get; set; }
/// <summary>
@ -88,9 +88,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Events
/// 获取或设置服务结束时间。
/// </summary>
[Newtonsoft.Json.JsonProperty("end_time")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.CommonWithoutSeparatorsNullableDateTimeOffsetConverter))]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.PureDigitalTextNullableDateTimeOffsetConverter))]
[System.Text.Json.Serialization.JsonPropertyName("end_time")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.CommonWithoutSeparatorsNullableDateTimeOffsetConverter))]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.PureDigitalTextNullableDateTimeOffsetConverter))]
public DateTimeOffset? EndTime { get; set; }
/// <summary>

View File

@ -29,17 +29,6 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Events
}
}
internal static class Converters
{
internal class NewtonsoftJsonYesOrNoConverter : Models.CreateVehicleTransactionParkingRequest.Converters.NewtonsoftJsonYesOrNoConverter
{
}
internal class SystemTextJsonYesOrNoConverter : Models.CreateVehicleTransactionParkingRequest.Converters.SystemTextJsonYesOrNoConverter
{
}
}
/// <summary>
/// 获取或设置微信商户号。
/// </summary>
@ -121,9 +110,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Events
/// 获取或设置用户是否还款。
/// </summary>
[Newtonsoft.Json.JsonProperty("user_repaid")]
[Newtonsoft.Json.JsonConverter(typeof(Converters.NewtonsoftJsonYesOrNoConverter))]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.YesOrNoNullableBooleanConverter))]
[System.Text.Json.Serialization.JsonPropertyName("user_repaid")]
[System.Text.Json.Serialization.JsonConverter(typeof(Converters.SystemTextJsonYesOrNoConverter))]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.YesOrNoNullableBooleanConverter))]
public bool? IsUserRepaid { get; set; }
/// <summary>

View File

@ -7,7 +7,7 @@ using Flurl.Http;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Interceptors
{
internal class WechatTenpaySignInterceptor : WechatHttpCallInterceptor
internal class WechatTenpaySignInterceptor : FlurlHttpCallInterceptor
{
private readonly string _scheme;
private readonly string _mchId;

View File

@ -72,9 +72,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// 获取或设置汇款截止时间。
/// </summary>
[Newtonsoft.Json.JsonProperty("deadline")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.CommonDateTimeOffsetConverter))]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RegularDateTimeOffsetConverter))]
[System.Text.Json.Serialization.JsonPropertyName("deadline")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.CommonDateTimeOffsetConverter))]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RegularDateTimeOffsetConverter))]
public DateTimeOffset Deadline { get; set; }
}

View File

@ -24,9 +24,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// 获取或设置服务开始时间。
/// </summary>
[Newtonsoft.Json.JsonProperty("start_time")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.CommonWithoutSeparatorsDateTimeOffsetConverter))]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.PureDigitalTextDateTimeOffsetConverter))]
[System.Text.Json.Serialization.JsonPropertyName("start_time")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.CommonWithoutSeparatorsDateTimeOffsetConverter))]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.PureDigitalTextDateTimeOffsetConverter))]
public DateTimeOffset StartTime { get; set; }
/// <summary>
@ -40,9 +40,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// 获取或设置服务结束时间。
/// </summary>
[Newtonsoft.Json.JsonProperty("end_time")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.CommonWithoutSeparatorsDateTimeOffsetConverter))]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.PureDigitalTextDateTimeOffsetConverter))]
[System.Text.Json.Serialization.JsonPropertyName("end_time")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.CommonWithoutSeparatorsDateTimeOffsetConverter))]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.PureDigitalTextDateTimeOffsetConverter))]
public DateTimeOffset EndTime { get; set; }
/// <summary>

View File

@ -175,9 +175,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// 获取或设置收款成功时间。
/// </summary>
[Newtonsoft.Json.JsonProperty("paid_time")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.CommonWithoutSeparatorsNullableDateTimeOffsetConverter))]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.PureDigitalTextNullableDateTimeOffsetConverter))]
[System.Text.Json.Serialization.JsonPropertyName("paid_time")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.CommonWithoutSeparatorsNullableDateTimeOffsetConverter))]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.PureDigitalTextNullableDateTimeOffsetConverter))]
public DateTimeOffset? PaidTime { get; set; }
/// <summary>

View File

@ -23,9 +23,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// 获取或设置收款成功时间。
/// </summary>
[Newtonsoft.Json.JsonProperty("paid_time")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.CommonWithoutSeparatorsNullableDateTimeOffsetConverter))]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.PureDigitalTextNullableDateTimeOffsetConverter))]
[System.Text.Json.Serialization.JsonPropertyName("paid_time")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.CommonWithoutSeparatorsNullableDateTimeOffsetConverter))]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.PureDigitalTextNullableDateTimeOffsetConverter))]
public DateTimeOffset? PaidTime { get; set; }
/// <summary>

View File

@ -92,95 +92,6 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
}
}
internal static class Converters
{
internal class NewtonsoftJsonYesOrNoConverter : Newtonsoft.Json.JsonConverter<bool?>
{
public override bool CanRead
{
get { return true; }
}
public override bool CanWrite
{
get { return true; }
}
public override bool? ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, bool? existingValue, bool hasExistingValue, Newtonsoft.Json.JsonSerializer serializer)
{
if (reader.TokenType == Newtonsoft.Json.JsonToken.Null)
{
return existingValue;
}
else if (reader.TokenType == Newtonsoft.Json.JsonToken.Boolean)
{
return serializer.Deserialize<bool>(reader);
}
else if (reader.TokenType == Newtonsoft.Json.JsonToken.String)
{
string? value = serializer.Deserialize<string>(reader);
if (value == null)
return existingValue;
if ("Y".Equals(value))
return true;
else if ("N".Equals(value))
return false;
}
throw new Newtonsoft.Json.JsonReaderException();
}
public override void WriteJson(Newtonsoft.Json.JsonWriter writer, bool? value, Newtonsoft.Json.JsonSerializer serializer)
{
if (value.HasValue)
writer.WriteValue(value.Value ? "Y" : "N");
else
writer.WriteNull();
}
}
internal class SystemTextJsonYesOrNoConverter : System.Text.Json.Serialization.JsonConverter<bool?>
{
public override bool? 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.True)
{
return true;
}
else if (reader.TokenType == System.Text.Json.JsonTokenType.False)
{
return false;
}
else if (reader.TokenType == System.Text.Json.JsonTokenType.String)
{
string? value = reader.GetString();
if (value == null)
return null;
if ("Y".Equals(value))
return true;
else if ("N".Equals(value))
return false;
}
throw new System.Text.Json.JsonException();
}
public override void Write(System.Text.Json.Utf8JsonWriter writer, bool? value, System.Text.Json.JsonSerializerOptions options)
{
if (value.HasValue)
writer.WriteStringValue(value.Value ? "Y" : "N");
else
writer.WriteNullValue();
}
}
}
/// <summary>
/// 获取或设置微信 AppId。
/// </summary>
@ -248,9 +159,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// 获取或设置是否分账。
/// </summary>
[Newtonsoft.Json.JsonProperty("profit_sharing")]
[Newtonsoft.Json.JsonConverter(typeof(Converters.NewtonsoftJsonYesOrNoConverter))]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.YesOrNoNullableBooleanConverter))]
[System.Text.Json.Serialization.JsonPropertyName("profit_sharing")]
[System.Text.Json.Serialization.JsonConverter(typeof(Converters.SystemTextJsonYesOrNoConverter))]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.YesOrNoNullableBooleanConverter))]
public bool? IsProfitSharing { get; set; }
/// <summary>

View File

@ -195,17 +195,6 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
}
}
internal static class Converters
{
internal class NewtonsoftJsonYesOrNoConverter : CreateVehicleTransactionParkingRequest.Converters.NewtonsoftJsonYesOrNoConverter
{
}
internal class SystemTextJsonYesOrNoConverter : CreateVehicleTransactionParkingRequest.Converters.SystemTextJsonYesOrNoConverter
{
}
}
/// <summary>
/// 获取或设置微信商户号。
/// </summary>
@ -287,9 +276,9 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Models
/// 获取或设置用户是否还款。
/// </summary>
[Newtonsoft.Json.JsonProperty("user_repaid")]
[Newtonsoft.Json.JsonConverter(typeof(Converters.NewtonsoftJsonYesOrNoConverter))]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.YesOrNoNullableBooleanConverter))]
[System.Text.Json.Serialization.JsonPropertyName("user_repaid")]
[System.Text.Json.Serialization.JsonConverter(typeof(Converters.SystemTextJsonYesOrNoConverter))]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.YesOrNoNullableBooleanConverter))]
public bool? IsUserRepaid { get; set; }
/// <summary>

View File

@ -17,7 +17,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
/// <summary>
/// 一个微信支付 API HTTP 客户端。
/// </summary>
public partial class WechatTenpayClient : WechatClientBase
public class WechatTenpayClient : CommonClientBase, IWechatClient
{
/// <summary>
/// 获取当前客户端使用的微信商户平台凭证。

View File

@ -5,7 +5,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
/// <summary>
/// 当调用微信支付 API 出错时引发的异常。
/// </summary>
public class WechatTenpayException : WechatExceptionBase
public class WechatTenpayException : CommonExceptionBase
{
/// <inheritdoc/>
public WechatTenpayException()

View File

@ -1,116 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.UnitTests
{
public class WechatConverterTests
{
class JsonDateTimeOffsetTestEntity
{
[Newtonsoft.Json.JsonProperty("datetime_rfc3339")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RFC3339DateTimeOffsetConverter))]
[System.Text.Json.Serialization.JsonPropertyName("datetime_rfc3339")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RFC3339DateTimeOffsetConverter))]
public DateTimeOffset DateTimeWithRFC3339 { get; set; }
[Newtonsoft.Json.JsonProperty("nullable_datetime_rfc3339")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.RFC3339NullableDateTimeOffsetConverter))]
[System.Text.Json.Serialization.JsonPropertyName("nullable_datetime_rfc3339")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.RFC3339NullableDateTimeOffsetConverter))]
public DateTimeOffset? NullableDateTimeWithRFC3339 { get; set; }
}
class JsonStringTypedStringListOrArrayTestEntity
{
[Newtonsoft.Json.JsonProperty("string_ilist")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.JsonTypedStringIListConverter))]
[System.Text.Json.Serialization.JsonPropertyName("string_ilist")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.JsonTypedStringIListConverter))]
public IList<string> StringTypedIList { get; set; }
[Newtonsoft.Json.JsonProperty("string_list")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.JsonTypedStringListConverter))]
[System.Text.Json.Serialization.JsonPropertyName("string_list")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.JsonTypedStringListConverter))]
public List<string> StringTypedList { get; set; }
[Newtonsoft.Json.JsonProperty("string_array")]
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.JsonTypedStringArrayConverter))]
[System.Text.Json.Serialization.JsonPropertyName("string_array")]
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.JsonTypedStringArrayConverter))]
public string[] StringTypedArray { get; set; }
}
[Fact(DisplayName = "日期时间 JSON 序列化 / 反序列化")]
public void JsonDateTimeOffsetTest()
{
const string FORMAT_RFC3339 = "yyyy-MM-dd'T'HH:mm:sszzz";
string datestr = "2018-06-08T10:34:56+08:00";
var date = DateTimeOffset.Parse(datestr);
var raw = new JsonDateTimeOffsetTestEntity();
Assert.Equal(datestr, date.ToString(FORMAT_RFC3339));
raw.DateTimeWithRFC3339 = date;
raw.NullableDateTimeWithRFC3339 = date;
var json = new FlurlNewtonsoftJsonSerializer().Serialize(raw);
var entity = new FlurlNewtonsoftJsonSerializer().Deserialize<JsonDateTimeOffsetTestEntity>(json);
Assert.Contains($"\"datetime_rfc3339\":\"{datestr}\"", json);
Assert.Contains($"\"nullable_datetime_rfc3339\":\"{datestr}\"", json);
Assert.Equal(raw.DateTimeWithRFC3339, entity.DateTimeWithRFC3339);
Assert.Equal(raw.NullableDateTimeWithRFC3339, entity.NullableDateTimeWithRFC3339);
raw.NullableDateTimeWithRFC3339 = null;
json = new FlurlNewtonsoftJsonSerializer().Serialize(raw);
entity = new FlurlNewtonsoftJsonSerializer().Deserialize<JsonDateTimeOffsetTestEntity>(json);
Assert.Equal(datestr, date.ToString(FORMAT_RFC3339));
Assert.DoesNotContain($"\"nullable_datetime_rfc3339\"", json);
Assert.Null(entity.NullableDateTimeWithRFC3339);
json = new FlurlSystemTextJsonSerializer().Serialize(raw);
entity = new FlurlSystemTextJsonSerializer().Deserialize<JsonDateTimeOffsetTestEntity>(json);
Assert.Equal(datestr, date.ToString(FORMAT_RFC3339));
Assert.DoesNotContain($"\"nullable_datetime_rfc3339\"", json);
Assert.Null(entity.NullableDateTimeWithRFC3339);
}
[Fact(DisplayName = "字符串类型的字符串列表、数组 JSON 序列化 / 反序列化")]
public void JsonStringTypedStringListOrArrayTest()
{
const string STR = "test";
var raw = new JsonStringTypedStringListOrArrayTestEntity();
raw.StringTypedIList = new List<string>() { STR };
raw.StringTypedList = new List<string>() { STR };
raw.StringTypedArray = new string[] { STR };
var json = new FlurlNewtonsoftJsonSerializer().Serialize(raw);
var entity = new FlurlNewtonsoftJsonSerializer().Deserialize<JsonDateTimeOffsetTestEntity>(json);
Assert.Contains($"\"string_ilist\":\"[\\\"{STR}\\\"]\"", json);
Assert.Contains($"\"string_list\":\"[\\\"{STR}\\\"]\"", json);
Assert.Contains($"\"string_array\":\"[\\\"{STR}\\\"]\"", json);
Assert.Contains(raw.StringTypedIList, e => STR.Equals(e));
Assert.Contains(raw.StringTypedList, e => STR.Equals(e));
Assert.Contains(raw.StringTypedArray, e => STR.Equals(e));
json = new FlurlSystemTextJsonSerializer().Serialize(raw);
entity = new FlurlSystemTextJsonSerializer().Deserialize<JsonDateTimeOffsetTestEntity>(json);
Assert.Contains($"\"string_ilist\":\"[\\\"{STR}\\\"]\"", json);
Assert.Contains($"\"string_list\":\"[\\\"{STR}\\\"]\"", json);
Assert.Contains($"\"string_array\":\"[\\\"{STR}\\\"]\"", json);
Assert.Contains(raw.StringTypedIList, e => STR.Equals(e));
Assert.Contains(raw.StringTypedList, e => STR.Equals(e));
Assert.Contains(raw.StringTypedArray, e => STR.Equals(e));
}
}
}