feat: 移除基础依赖库,升级公共组件,并适配 .NET 6.0

This commit is contained in:
Fu Diwei
2021-11-09 15:23:23 +08:00
parent b11f6bb73b
commit acea1b477c
62 changed files with 149 additions and 221 deletions

View File

@@ -38,7 +38,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
if (request.FileHash == null)
{
request.FileHash = Security.MD5Utility.Hash(request.FileBytes ?? new byte[0]);
request.FileHash = Utilities.MD5Utility.Hash(request.FileBytes ?? new byte[0]);
}
string boundary = "--BOUNDARY--" + DateTimeOffset.Now.Ticks.ToString("x");

View File

@@ -24,7 +24,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads.Interceptors
string timestamp = DateTimeOffset.Now.ToLocalTime().ToUnixTimeSeconds().ToString();
string nonce = Guid.NewGuid().ToString("N");
string sign = Security.MD5Utility.Hash($"{_agencyId}{timestamp}{nonce}{_agencyApiKey}").ToLower();
string sign = Utilities.MD5Utility.Hash($"{_agencyId}{timestamp}{nonce}{_agencyApiKey}").ToLower();
string token = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{_agencyId},{timestamp},{nonce},{sign}"));
flurlCall.Request.RemoveQueryParam("agency_token");

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net461; netstandard2.0; net5.0</TargetFrameworks>
<TargetFrameworks>net461; netstandard2.0; net5.0; net6.0</TargetFrameworks>
<LangVersion>8.0</LangVersion>
<Nullable>enable</Nullable>
<NullableReferenceTypes>true</NullableReferenceTypes>
@@ -27,11 +27,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SKIT.FlurlHttpClient.Wechat\SKIT.FlurlHttpClient.Wechat.csproj" />
<PackageReference Include="SKIT.FlurlHttpClient.Common" Version="2.0.0" />
</ItemGroup>
</Project>

View File

@@ -2,7 +2,7 @@
using System.Security.Cryptography;
using System.Text;
namespace SKIT.FlurlHttpClient.Wechat.Security
namespace SKIT.FlurlHttpClient.Wechat.Ads.Utilities
{
/// <summary>
/// MD5 算法工具类。

View File

@@ -1,21 +1,18 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Flurl.Http;
using Flurl.Http.Configuration;
namespace SKIT.FlurlHttpClient.Wechat.Ads
{
/// <summary>
/// 一个微信广告平台 API HTTP 客户端。
/// </summary>
public class WechatAdsClient : CommonClientBase, IWechatClient
public class WechatAdsClient : CommonClientBase, ICommonClient
{
/// <summary>
/// 获取当前客户端使用的微信广告平台凭证。

View File

@@ -3,7 +3,7 @@
/// <summary>
/// 微信广告平台 API 请求的基类。
/// </summary>
public abstract class WechatAdsRequest : IWechatRequest
public abstract class WechatAdsRequest : ICommonRequest
{
/// <summary>
/// 获取或设置请求超时时间(单位:毫秒)。如果不指定将使用构造 <see cref="WechatAdsClient"/> 时的 <see cref="WechatAdsClientOptions.Timeout"/> 参数,这在需要指定特定耗时请求(比如上传或下载文件)的超时时间时很有用。

View File

@@ -6,7 +6,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
/// <summary>
/// 微信广告平台 API 响应的基类。
/// </summary>
public abstract class WechatAdsResponse : IWechatResponse
public abstract class WechatAdsResponse : ICommonResponse
{
/// <summary>
/// 获取原始的 HTTP 响应状态码。

View File

@@ -270,7 +270,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api
if (callbackSignature == null) throw new ArgumentNullException(nameof(callbackSignature));
ISet<string> set = new SortedSet<string>(StringComparer.Ordinal) { client.Credentials.PushToken!, callbackTimestamp, callbackNonce };
string sign = Security.SHA1Utility.Hash(string.Concat(set));
string sign = Utilities.SHA1Utility.Hash(string.Concat(set));
return string.Equals(sign, callbackSignature, StringComparison.InvariantCultureIgnoreCase);
}

View File

@@ -25,7 +25,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api
if (request.DeliverySignature == null)
{
string plainText = $"{request.ShopId}{request.ShopOrderId}{client.Credentials.ImmeDeliveryAppSecret}";
request.DeliverySignature = Security.SHA1Utility.Hash(plainText).ToLower();
request.DeliverySignature = Utilities.SHA1Utility.Hash(plainText).ToLower();
}
return request;

View File

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

View File

@@ -25,7 +25,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api
string timestamp = DateTimeOffset.Now.ToLocalTime().ToUnixTimeSeconds().ToString();
string nonce = Guid.NewGuid().ToString("N");
string sign = Security.SHA1Utility.Hash($"jsapi_ticket={jsapiTicket}&noncestr={nonce}&timestamp={timestamp}&url={url.Split('#')[0]}").ToLower();
string sign = Utilities.SHA1Utility.Hash($"jsapi_ticket={jsapiTicket}&noncestr={nonce}&timestamp={timestamp}&url={url.Split('#')[0]}").ToLower();
return new ReadOnlyDictionary<string, string>(new Dictionary<string, string>()
{
@@ -58,7 +58,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api
sortedParams.Add(client.Credentials.AppId);
sortedParams.Add(nonce);
sortedParams.Add(wxcardTicket);
string cardSign = Security.SHA1Utility.Hash(string.Join(string.Empty, sortedParams)).ToLower();
string cardSign = Utilities.SHA1Utility.Hash(string.Join(string.Empty, sortedParams)).ToLower();
return new ReadOnlyDictionary<string, string>(new Dictionary<string, string>()
{

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net461; netstandard2.0; net5.0</TargetFrameworks>
<TargetFrameworks>net461; netstandard2.0; net5.0; net6.0</TargetFrameworks>
<LangVersion>8.0</LangVersion>
<Nullable>enable</Nullable>
<NullableReferenceTypes>true</NullableReferenceTypes>
@@ -26,12 +26,8 @@
<Reference Include="System.Web" Condition="'$(TargetFramework)' == 'net461'" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SKIT.FlurlHttpClient.Wechat\SKIT.FlurlHttpClient.Wechat.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="SKIT.FlurlHttpClient.Common" Version="2.0.0" />
</ItemGroup>
</Project>

View File

@@ -2,7 +2,7 @@
using System.Security.Cryptography;
using System.Text;
namespace SKIT.FlurlHttpClient.Wechat.Security
namespace SKIT.FlurlHttpClient.Wechat.Api.Utilities
{
/// <summary>
/// HMAC-SHA-256 算法工具类。

View File

@@ -2,7 +2,7 @@
using System.Security.Cryptography;
using System.Text;
namespace SKIT.FlurlHttpClient.Wechat.Security
namespace SKIT.FlurlHttpClient.Wechat.Api.Utilities
{
/// <summary>
/// SHA-1 算法工具类。

View File

@@ -81,7 +81,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.Utilities
if (ivBytes == null) throw new ArgumentNullException(nameof(ivBytes));
if (ciperBytes == null) throw new ArgumentNullException(nameof(ciperBytes));
using RijndaelManaged aes = new RijndaelManaged();
using var aes = Aes.Create();
aes.KeySize = 256;
aes.BlockSize = 128;
aes.Mode = CipherMode.CBC;
@@ -109,7 +109,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.Utilities
if (ivBytes == null) throw new ArgumentNullException(nameof(ivBytes));
if (plainBytes == null) throw new ArgumentNullException(nameof(plainBytes));
using var aes = new RijndaelManaged();
using var aes = Aes.Create();
aes.KeySize = AES_KEY_SIZE;
aes.BlockSize = AES_BLOCK_SIZE;
//aes.Padding = PaddingMode.PKCS7;
@@ -238,7 +238,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.Utilities
set.Add(sMsgEncrypt);
string rawText = string.Join(string.Empty, set.ToArray());
string signText = Security.SHA1Utility.Hash(rawText);
string signText = Utilities.SHA1Utility.Hash(rawText);
return signText.ToLower();
}
@@ -270,7 +270,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api.Utilities
try
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.XmlResolver = null;
xmlDoc.XmlResolver = null!;
xmlDoc.LoadXml(xml);
XmlNode? xmlRoot = xmlDoc.FirstChild;

View File

@@ -1,24 +1,21 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Flurl.Http;
using Flurl.Http.Configuration;
namespace SKIT.FlurlHttpClient.Wechat.Api
{
/// <summary>
/// 一个微信 API HTTP 客户端。
/// </summary>
public class WechatApiClient : CommonClientBase, IWechatClient
public class WechatApiClient : CommonClientBase, ICommonClient
{
/// <summary>
/// 获取当前客户端使用的微信公众平台凭证。
/// 获取当前客户端使用的微信公众平台/开放平台凭证。
/// </summary>
public Settings.Credentials Credentials { get; }

View File

@@ -5,7 +5,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api
/// <summary>
/// 表示微信 API 请求的基类。
/// </summary>
public abstract class WechatApiRequest : IWechatRequest
public abstract class WechatApiRequest : ICommonRequest
{
/// <summary>
/// 获取或设置请求超时时间(单位:毫秒)。如果不指定将使用构造 <see cref="WechatApiClient"/> 时的 <see cref="WechatApiClientOptions.Timeout"/> 参数,这在需要指定特定耗时请求(比如上传或下载文件)的超时时间时很有用。

View File

@@ -6,7 +6,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Api
/// <summary>
/// 表示微信 API 响应的基类。
/// </summary>
public abstract class WechatApiResponse : IWechatResponse
public abstract class WechatApiResponse : ICommonResponse
{
/// <summary>
/// 获取原始的 HTTP 响应状态码。

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net461; netstandard2.0; net5.0</TargetFrameworks>
<TargetFrameworks>net461; netstandard2.0; net5.0; net6.0</TargetFrameworks>
<LangVersion>8.0</LangVersion>
<Nullable>enable</Nullable>
<NullableReferenceTypes>true</NullableReferenceTypes>
@@ -28,11 +28,7 @@
<ItemGroup>
<PackageReference Include="JWT" Version="8.4.2" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SKIT.FlurlHttpClient.Wechat\SKIT.FlurlHttpClient.Wechat.csproj" />
</ItemGroup>
<PackageReference Include="SKIT.FlurlHttpClient.Common" Version="2.0.0" />
</ItemGroup>
</Project>

View File

@@ -2,43 +2,38 @@
using System.Security.Cryptography;
using System.Text;
namespace SKIT.FlurlHttpClient.Wechat.Security
namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Utilities
{
/// <summary>
/// HMAC-SHA-1 算法工具类。
/// SHA-1 算法工具类。
/// </summary>
public static class HMACSHA1Utility
public static class SHA1Utility
{
/// <summary>
/// 获取信息摘要。
/// </summary>
/// <param name="secretBytes">密钥字节数组。</param>
/// <param name="bytes">信息字节数组。</param>
/// <returns>信息摘要。</returns>
public static string Hash(byte[] secretBytes, byte[] bytes)
public static string Hash(byte[] bytes)
{
if (secretBytes == null) throw new ArgumentNullException(nameof(secretBytes));
if (bytes == null) throw new ArgumentNullException(nameof(bytes));
using HMAC hmac = new HMACSHA1(secretBytes);
byte[] hashBytes = hmac.ComputeHash(bytes);
using SHA1 sha = SHA1.Create();
byte[] hashBytes = sha.ComputeHash(bytes);
return BitConverter.ToString(hashBytes).Replace("-", "");
}
/// <summary>
/// 获取信息摘要。
/// </summary>
/// <param name="secret">密钥。</param>
/// <param name="message">文本信息。</param>
/// <returns>信息摘要。</returns>
public static string Hash(string secret, string message)
public static string Hash(string message)
{
if (secret == null) throw new ArgumentNullException(nameof(secret));
if (message == null) throw new ArgumentNullException(nameof(message));
byte[] secretBytes = Encoding.UTF8.GetBytes(secret);
byte[] bytes = Encoding.UTF8.GetBytes(message);
return Hash(secretBytes, bytes);
return Hash(bytes);
}
}
}

View File

@@ -80,7 +80,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Utilities
if (ivBytes == null) throw new ArgumentNullException(nameof(ivBytes));
if (ciperBytes == null) throw new ArgumentNullException(nameof(ciperBytes));
using RijndaelManaged aes = new RijndaelManaged();
using var aes = Aes.Create();
aes.KeySize = 256;
aes.BlockSize = 128;
aes.Mode = CipherMode.CBC;
@@ -108,7 +108,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Utilities
if (ivBytes == null) throw new ArgumentNullException(nameof(ivBytes));
if (plainBytes == null) throw new ArgumentNullException(nameof(plainBytes));
using var aes = new RijndaelManaged();
using var aes = Aes.Create();
aes.KeySize = AES_KEY_SIZE;
aes.BlockSize = AES_BLOCK_SIZE;
//aes.Padding = PaddingMode.PKCS7;
@@ -237,7 +237,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Utilities
set.Add(sMsgEncrypt);
string rawText = string.Join(string.Empty, set.ToArray());
string signText = Security.SHA1Utility.Hash(rawText);
string signText = Utilities.SHA1Utility.Hash(rawText);
return signText.ToLower();
}
@@ -269,7 +269,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI.Utilities
try
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.XmlResolver = null;
xmlDoc.XmlResolver = null!;
xmlDoc.LoadXml(xml);
XmlNode? xmlRoot = xmlDoc.FirstChild;

View File

@@ -12,7 +12,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI
/// <summary>
/// 一个微信智能对话平台接入 API HTTP 客户端。
/// </summary>
public class WechatOpenAIPlatformClient : CommonClientBase, IWechatClient
public class WechatOpenAIPlatformClient : CommonClientBase, ICommonClient
{
/// <summary>
/// 获取当前客户端使用的微信智能对话平台凭证。

View File

@@ -5,7 +5,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI
/// <summary>
/// 表示微信智能对话平台接入 API 请求的基类。
/// </summary>
public abstract class WechatOpenAIPlatformRequest : IWechatRequest
public abstract class WechatOpenAIPlatformRequest : ICommonRequest
{
public static class Serialization
{

View File

@@ -6,7 +6,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI
/// <summary>
/// 表示微信智能对话平台接入 API 响应的基类。
/// </summary>
public abstract class WechatOpenAIPlatformResponse : IWechatResponse
public abstract class WechatOpenAIPlatformResponse : ICommonResponse
{
/// <summary>
/// 获取原始的 HTTP 响应状态码。

View File

@@ -12,7 +12,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI
/// <summary>
/// 一个微信智能对话第三方接入 API HTTP 客户端。
/// </summary>
public class WechatOpenAIThirdPartyClient : CommonClientBase, IWechatClient
public class WechatOpenAIThirdPartyClient : CommonClientBase, ICommonClient
{
/// <summary>
/// 获取当前客户端使用的微信智能对话平台凭证。

View File

@@ -5,7 +5,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI
/// <summary>
/// 表示微信智能对话第三方接入 API 请求的基类。
/// </summary>
public abstract class WechatOpenAIThirdPartyRequest : IWechatRequest
public abstract class WechatOpenAIThirdPartyRequest : ICommonRequest
{
/// <summary>
/// 获取或设置请求超时时间(单位:毫秒)。如果不指定将使用构造 <see cref="WechatOpenAIPlatformClient"/> 时的 <see cref="WechatOpenAIPlatformClientOptions.Timeout"/> 参数,这在需要指定特定耗时请求(比如上传或下载文件)的超时时间时很有用。

View File

@@ -6,7 +6,7 @@ namespace SKIT.FlurlHttpClient.Wechat.OpenAI
/// <summary>
/// 表示微信智能对话第三方接入 API 响应的基类。
/// </summary>
public abstract class WechatOpenAIThirdPartyResponse : IWechatResponse
public abstract class WechatOpenAIThirdPartyResponse : ICommonResponse
{
/// <summary>
/// 获取原始的 HTTP 响应状态码。

View File

@@ -34,7 +34,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
request.FileName = Guid.NewGuid().ToString("N").ToLower() + ".txt";
if (request.FileHash == null)
request.FileHash = Security.SHA256Utility.Hash(request.FileBytes).ToLower();
request.FileHash = Utilities.SHA256Utility.Hash(request.FileBytes).ToLower();
if (request.FileContentType == null)
request.FileContentType = Utilities.FileNameToContentTypeMapper.GetContentTypeForImage(request.FileName!) ?? "text/plain";

View File

@@ -34,7 +34,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
request.FileName = Guid.NewGuid().ToString("N").ToLower() + ".png";
if (request.FileHash == null)
request.FileHash = Security.SHA256Utility.Hash(request.FileBytes).ToLower();
request.FileHash = Utilities.SHA256Utility.Hash(request.FileBytes).ToLower();
if (request.FileContentType == null)
request.FileContentType = Utilities.FileNameToContentTypeMapper.GetContentTypeForImage(request.FileName!) ?? "image/png";

View File

@@ -34,7 +34,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
request.FileName = Guid.NewGuid().ToString("N").ToLower() + ".png";
if (request.FileHash == null)
request.FileHash = Security.SHA256Utility.Hash(request.FileBytes).ToLower();
request.FileHash = Utilities.SHA256Utility.Hash(request.FileBytes).ToLower();
if (request.FileContentType == null)
request.FileContentType = Utilities.FileNameToContentTypeMapper.GetContentTypeForImage(request.FileName!) ?? "image/png";
@@ -73,7 +73,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
request.FileName = Guid.NewGuid().ToString("N").ToLower() + ".mp4";
if (request.FileHash == null)
request.FileHash = Security.SHA256Utility.Hash(request.FileBytes).ToLower();
request.FileHash = Utilities.SHA256Utility.Hash(request.FileBytes).ToLower();
if (request.FileContentType == null)
request.FileContentType = Utilities.FileNameToContentTypeMapper.GetContentTypeForVideo(request.FileName!) ?? "video/mp4";

View File

@@ -237,7 +237,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
request.FileName = Guid.NewGuid().ToString("N").ToLower() + ".png";
if (request.FileHash == null)
request.FileHash = Security.SHA256Utility.Hash(request.FileBytes).ToLower();
request.FileHash = Utilities.SHA256Utility.Hash(request.FileBytes).ToLower();
if (request.FileContentType == null)
request.FileContentType = Utilities.FileNameToContentTypeMapper.GetContentTypeForImage(request.FileName!) ?? "image/png";

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net461; netstandard2.0; net5.0</TargetFrameworks>
<TargetFrameworks>net461; netstandard2.0; net5.0; net6.0</TargetFrameworks>
<LangVersion>8.0</LangVersion>
<Nullable>enable</Nullable>
<NullableReferenceTypes>true</NullableReferenceTypes>
@@ -27,12 +27,8 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
<PackageReference Include="Portable.BouncyCastle" Version="1.8.10" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SKIT.FlurlHttpClient.Wechat\SKIT.FlurlHttpClient.Wechat.csproj" />
<PackageReference Include="SKIT.FlurlHttpClient.Common" Version="2.0.0" />
</ItemGroup>
</Project>

View File

@@ -2,7 +2,7 @@
using System.Security.Cryptography;
using System.Text;
namespace SKIT.FlurlHttpClient.Wechat.Security
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Utilities
{
/// <summary>
/// SHA-256 算法工具类。

View File

@@ -1,23 +1,19 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Flurl;
using Flurl.Http;
using Flurl.Http.Configuration;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
{
/// <summary>
/// 一个微信支付 API HTTP 客户端。
/// </summary>
public class WechatTenpayClient : CommonClientBase, IWechatClient
public class WechatTenpayClient : CommonClientBase, ICommonClient
{
/// <summary>
/// 获取当前客户端使用的微信商户平台凭证。

View File

@@ -5,7 +5,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
/// <summary>
/// 表示微信支付 API 请求的基类。
/// </summary>
public abstract class WechatTenpayRequest : IWechatRequest
public abstract class WechatTenpayRequest : ICommonRequest
{
/// <summary>
/// 获取或设置请求超时时间(单位:毫秒)。如果不指定将使用构造 <see cref="WechatTenpayClient"/> 时的 <see cref="WechatTenpayClientOptions.Timeout"/> 参数,这在需要指定特定耗时请求(比如上传或下载文件)的超时时间时很有用。

View File

@@ -6,7 +6,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
/// <summary>
/// 表示微信支付 API 响应的基类。
/// </summary>
public abstract class WechatTenpayResponse : IWechatResponse
public abstract class WechatTenpayResponse : ICommonResponse
{
/// <summary>
/// 获取原始的 HTTP 响应状态码。

View File

@@ -35,7 +35,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Work
string timestamp = DateTimeOffset.Now.ToLocalTime().ToUnixTimeSeconds().ToString();
string nonce = Guid.NewGuid().ToString("N");
string sign = Security.SHA1Utility.Hash($"jsapi_ticket={jsapiTicket}&noncestr={nonce}&timestamp={timestamp}&url={url.Split('#')[0]}").ToLower();
string sign = Utilities.SHA1Utility.Hash($"jsapi_ticket={jsapiTicket}&noncestr={nonce}&timestamp={timestamp}&url={url.Split('#')[0]}").ToLower();
return new ReadOnlyDictionary<string, string>(new Dictionary<string, string>()
{
@@ -64,7 +64,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Work
string timestamp = DateTimeOffset.Now.ToLocalTime().ToUnixTimeSeconds().ToString();
string nonce = Guid.NewGuid().ToString("N");
string sign = Security.SHA1Utility.Hash($"jsapi_ticket={jsapiTicket}&noncestr={nonce}&timestamp={timestamp}&url={url.Split('#')[0]}").ToLower();
string sign = Utilities.SHA1Utility.Hash($"jsapi_ticket={jsapiTicket}&noncestr={nonce}&timestamp={timestamp}&url={url.Split('#')[0]}").ToLower();
return new ReadOnlyDictionary<string, string>(new Dictionary<string, string>()
{

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net461; netstandard2.0; net5.0</TargetFrameworks>
<TargetFrameworks>net461; netstandard2.0; net5.0; net6.0</TargetFrameworks>
<LangVersion>8.0</LangVersion>
<Nullable>enable</Nullable>
<NullableReferenceTypes>true</NullableReferenceTypes>
@@ -27,11 +27,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SKIT.FlurlHttpClient.Wechat\SKIT.FlurlHttpClient.Wechat.csproj" />
<PackageReference Include="SKIT.FlurlHttpClient.Common" Version="2.0.0" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,39 @@
using System;
using System.Security.Cryptography;
using System.Text;
namespace SKIT.FlurlHttpClient.Wechat.Work.Utilities
{
/// <summary>
/// SHA-1 算法工具类。
/// </summary>
public static class SHA1Utility
{
/// <summary>
/// 获取信息摘要。
/// </summary>
/// <param name="bytes">信息字节数组。</param>
/// <returns>信息摘要。</returns>
public static string Hash(byte[] bytes)
{
if (bytes == null) throw new ArgumentNullException(nameof(bytes));
using SHA1 sha = SHA1.Create();
byte[] hashBytes = sha.ComputeHash(bytes);
return BitConverter.ToString(hashBytes).Replace("-", "");
}
/// <summary>
/// 获取信息摘要。
/// </summary>
/// <param name="message">文本信息。</param>
/// <returns>信息摘要。</returns>
public static string Hash(string message)
{
if (message == null) throw new ArgumentNullException(nameof(message));
byte[] bytes = Encoding.UTF8.GetBytes(message);
return Hash(bytes);
}
}
}

View File

@@ -81,7 +81,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.Utilities
if (ivBytes == null) throw new ArgumentNullException(nameof(ivBytes));
if (cipherBytes == null) throw new ArgumentNullException(nameof(cipherBytes));
using RijndaelManaged aes = new RijndaelManaged();
using var aes = Aes.Create();
aes.KeySize = 256;
aes.BlockSize = 128;
aes.Mode = CipherMode.CBC;
@@ -109,7 +109,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.Utilities
if (ivBytes == null) throw new ArgumentNullException(nameof(ivBytes));
if (plainBytes == null) throw new ArgumentNullException(nameof(plainBytes));
using var aes = new RijndaelManaged();
using var aes = Aes.Create();
aes.KeySize = AES_KEY_SIZE;
aes.BlockSize = AES_BLOCK_SIZE;
//aes.Padding = PaddingMode.PKCS7;
@@ -238,7 +238,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.Utilities
set.Add(sMsgEncrypt);
string rawText = string.Join(string.Empty, set.ToArray());
string signText = Security.SHA1Utility.Hash(rawText);
string signText = Utilities.SHA1Utility.Hash(rawText);
return signText.ToLower();
}
@@ -273,7 +273,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Work.Utilities
try
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.XmlResolver = null;
xmlDoc.XmlResolver = null!;
xmlDoc.LoadXml(xml);
XmlNode? xmlRoot = xmlDoc.FirstChild;

View File

@@ -1,21 +1,18 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Flurl.Http;
using Flurl.Http.Configuration;
namespace SKIT.FlurlHttpClient.Wechat.Work
{
/// <summary>
/// 一个企业微信 API HTTP 客户端。
/// </summary>
public class WechatWorkClient : CommonClientBase, IWechatClient
public class WechatWorkClient : CommonClientBase, ICommonClient
{
/// <summary>
/// 获取当前客户端使用的企业微信凭证。

View File

@@ -5,7 +5,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Work
/// <summary>
/// 表示企业微信 API 请求的基类。
/// </summary>
public abstract class WechatWorkRequest : IWechatRequest
public abstract class WechatWorkRequest : ICommonRequest
{
/// <summary>
/// 获取或设置请求超时时间(单位:毫秒)。如果不指定将使用构造 <see cref="WechatWorkClient"/> 时的 <see cref="WechatWorkClientOptions.Timeout"/> 参数,这在需要指定特定耗时请求(比如上传或下载文件)的超时时间时很有用。

View File

@@ -6,7 +6,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Work
/// <summary>
/// 表示企业微信 API 响应的基类。
/// </summary>
public abstract class WechatWorkResponse : IWechatResponse
public abstract class WechatWorkResponse : ICommonResponse
{
/// <summary>
/// 获取原始的 HTTP 响应状态码。

View File

@@ -1,14 +0,0 @@
using System;
using System.Net.Http;
using Flurl.Http;
using Flurl.Http.Configuration;
namespace SKIT.FlurlHttpClient.Wechat
{
/// <summary>
/// SKIT.FlurlHttpClient.Wechat 客户端接口。
/// </summary>
public interface IWechatClient : ICommonClient
{
}
}

View File

@@ -1,9 +0,0 @@
namespace SKIT.FlurlHttpClient.Wechat
{
/// <summary>
/// SKIT.FlurlHttpClient.Wechat 请求接口。
/// </summary>
public interface IWechatRequest : ICommonRequest
{
}
}

View File

@@ -1,9 +0,0 @@
namespace SKIT.FlurlHttpClient.Wechat
{
/// <summary>
/// SKIT.FlurlHttpClient.Wechat 响应接口。
/// </summary>
public interface IWechatResponse : ICommonResponse
{
}
}

View File

@@ -1,31 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net461; netstandard2.0; net5.0</TargetFrameworks>
<LangVersion>8.0</LangVersion>
<Nullable>enable</Nullable>
<NullableReferenceTypes>true</NullableReferenceTypes>
</PropertyGroup>
<PropertyGroup>
<PackageId>SKIT.FlurlHttpClient.Wechat</PackageId>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat</PackageProjectUrl>
<PackageTags>Flurl.Http Wechat Weixin MicroMessage 微信</PackageTags>
<Version>1.1.0</Version>
<Description>SKIT.FlurlClient.Wechat含 SKIT.FlurlHttpClient.Wechat.Api、SKIT.FlurlHttpClient.Wechat.TenpayV3、SKIT.FlurlHttpClient.Wechat.Work、SKIT.FlurlHttpClient.Wechat.Ads 等模块)的核心库,具体用法请参阅开发文档。</Description>
<Authors>Fu Diwei</Authors>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat.git</RepositoryUrl>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="SKIT.FlurlHttpClient.Common" Version="1.0.0" />
</ItemGroup>
</Project>