diff --git a/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Utilities/Internal/JwtUtility.cs b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Utilities/Internal/JwtUtility.cs new file mode 100644 index 00000000..3e7495b5 --- /dev/null +++ b/src/SKIT.FlurlHttpClient.Wechat.OpenAI/Utilities/Internal/JwtUtility.cs @@ -0,0 +1,25 @@ +using System; +using JWT; +using JWT.Algorithms; +using JWT.Serializers; +using Newtonsoft.Json; + +namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Utilities +{ + internal static class JwtUtility + { + private static readonly Lazy _encoder = new Lazy(() => + { + IJwtAlgorithm algorithm = new HMACSHA256Algorithm(); + IJsonSerializer serializer = new JsonNetSerializer(new JsonSerializer() { NullValueHandling = NullValueHandling.Ignore }); + IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder(); + IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder); + return encoder; + }, isThreadSafe: true); + + public static string EncodeWithHS256(object payload, string secret) + { + return _encoder.Value.Encode(payload, secret); + } + } +} diff --git a/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Utilities/Internal/JsonUtility.cs b/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Utilities/Internal/JsonUtility.cs index bbb1ef2e..d6fc4608 100644 --- a/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Utilities/Internal/JsonUtility.cs +++ b/src/SKIT.FlurlHttpClient.Wechat.TenpayV2/Utilities/Internal/JsonUtility.cs @@ -1,7 +1,7 @@ -using System.Linq; +using System.Collections.Generic; +using System.Linq; using System.Text; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; +using System.Text.Json.Nodes; namespace SKIT.FlurlHttpClient.Wechat.TenpayV2.Utilities { @@ -13,22 +13,15 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV2.Utilities return string.Empty; StringBuilder stringBuilder = new StringBuilder(); - - JObject jObject = JsonConvert.DeserializeObject(json); - JProperty[] jProps = jObject.Properties().OrderBy(p => p.Name).ToArray(); - foreach (JProperty jProp in jProps) + JsonObject jObject = JsonNode.Parse(json)!.AsObject(); + foreach (KeyValuePair jProp in jObject.OrderBy(p => p.Key)) { - if (jProp.Value.Type == JTokenType.Null) - { + string key = jProp.Key; + string? value = jProp.Value?.ToString(); + if (string.IsNullOrEmpty(value)) continue; - } - else if (jProp.Value.Type == JTokenType.String) - { - if (string.IsNullOrEmpty((string)jProp.Value)) - continue; - } - stringBuilder.Append($"{jProp.Name}={jProp.Value}&"); + stringBuilder.Append($"{key}={value}&"); } return stringBuilder.ToString().TrimEnd('&'); diff --git a/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/TestCase_JwtUtilityTests.cs b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/TestCase_JwtUtilityTests.cs new file mode 100644 index 00000000..4a1f42e5 --- /dev/null +++ b/test/SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests/TestCase_JwtUtilityTests.cs @@ -0,0 +1,26 @@ +using Xunit; + +namespace SKIT.FlurlHttpClient.Wechat.OpenAI.UnitTests +{ + public class TestCase_JwtUtilityTests + { + [Fact(DisplayName = "测试用例:JWT HS256 编码")] + public void TestJWTEncodeWithHS256() + { + object payload = new + { + uid = "xjlsj33lasfaf", + data = new + { + q = "在微信智言与微信智聆两大技术的支持下,微信AI团队推出了“微信对话开放平台”和“腾讯小微”智能硬件两大核心产品。微信支付团队最新发布的“微信青蛙Pro”在现场设置了体验区,让大家感受AI认脸的本事。" + } + }; + string secret = "jWmYm7qr5nMoAUwZRjGtBxmz3KA1tkAj3ykkR6q2B2C"; + + string actualJwt = Utilities.JwtUtility.EncodeWithHS256(payload: payload, secret: secret); + string expectedJwt = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1aWQiOiJ4amxzajMzbGFzZmFmIiwiZGF0YSI6eyJxIjoi5Zyo5b6u5L-h5pm66KiA5LiO5b6u5L-h5pm66IGG5Lik5aSn5oqA5pyv55qE5pSv5oyB5LiL77yM5b6u5L-hQUnlm6LpmJ_mjqjlh7rkuobigJzlvq7kv6Hlr7nor53lvIDmlL7lubPlj7DigJ3lkozigJzohb7orq_lsI_lvq7igJ3mmbrog73noazku7bkuKTlpKfmoLjlv4Pkuqflk4HjgILlvq7kv6HmlK_ku5jlm6LpmJ_mnIDmlrDlj5HluIPnmoTigJzlvq7kv6HpnZLom5lQcm_igJ3lnKjnjrDlnLrorr7nva7kuobkvZPpqozljLrvvIzorqnlpKflrrbmhJ_lj5dBSeiupOiEuOeahOacrOS6i-OAgiJ9fQ.8FeSvxKlIrbI6MCAaWGekB4sHGA8DeUxgVXiHa8ulJk"; + + Assert.Equal(expectedJwt, actualJwt, ignoreCase: true); + } + } +}