refactor: clean code

This commit is contained in:
Fu Diwei 2022-03-11 10:38:15 +08:00
parent 6010c202e8
commit 23d144fef7
7 changed files with 84 additions and 30 deletions

View File

@ -0,0 +1,24 @@
using System;
namespace SKIT.FlurlHttpClient.Wechat.Ads.Exceptions
{
public class WechatAdsRequestAgencyTokenException : WechatAdsException
{
/// <inheritdoc/>
internal WechatAdsRequestAgencyTokenException()
{
}
/// <inheritdoc/>
internal WechatAdsRequestAgencyTokenException(string message)
: base(message)
{
}
/// <inheritdoc/>
internal WechatAdsRequestAgencyTokenException(string message, Exception innerException)
: base(message, innerException)
{
}
}
}

View File

@ -6,12 +6,12 @@ using Flurl.Http;
namespace SKIT.FlurlHttpClient.Wechat.Ads.Interceptors
{
internal class WechatAdsAgencyTokenInterceptor : FlurlHttpCallInterceptor
internal class WechatAdsRequestAgencyTokenInterceptor : FlurlHttpCallInterceptor
{
private readonly string _agencyId;
private readonly string _agencyApiKey;
public WechatAdsAgencyTokenInterceptor(string agencyId, string agencyApiKey)
public WechatAdsRequestAgencyTokenInterceptor(string agencyId, string agencyApiKey)
{
_agencyId = agencyId;
_agencyApiKey = agencyApiKey;
@ -20,6 +20,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads.Interceptors
public override async Task BeforeCallAsync(FlurlCall flurlCall)
{
if (flurlCall == null) throw new ArgumentNullException(nameof(flurlCall));
if (flurlCall.Completed) throw new Exceptions.WechatAdsRequestAgencyTokenException("This interceptor must be called before request completed.");
string timestamp = DateTimeOffset.Now.ToLocalTime().ToUnixTimeSeconds().ToString();
string nonce = Guid.NewGuid().ToString("N");

View File

@ -30,7 +30,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Ads
FlurlClient.BaseUrl = options.Endpoints ?? WechatAdsEndpoints.DEFAULT;
FlurlClient.WithTimeout(TimeSpan.FromMilliseconds(options.Timeout));
Interceptors.Add(new Interceptors.WechatAdsAgencyTokenInterceptor(
Interceptors.Add(new Interceptors.WechatAdsRequestAgencyTokenInterceptor(
agencyId: options.AgencyId,
agencyApiKey: options.AgencyApiKey
));

View File

@ -19,13 +19,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
/// <param name="callbackSignature">微信回调通知中的 Wechatpay-Signature 字段。</param>
/// <param name="callbackSerialNumber">微信回调通知中的 Wechatpay-Serial 字段。</param>
/// <returns></returns>
public static bool VerifyEventSignature(
this WechatTenpayClient client,
string callbackTimestamp,
string callbackNonce,
string callbackBody,
string callbackSignature,
string callbackSerialNumber)
public static bool VerifyEventSignature(this WechatTenpayClient client, string callbackTimestamp, string callbackNonce, string callbackBody, string callbackSignature, string callbackSerialNumber)
{
return VerifyEventSignature(client, callbackTimestamp, callbackNonce, callbackBody, callbackSignature, callbackSerialNumber, out _);
}
@ -44,14 +38,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
/// <param name="error"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
public static bool VerifyEventSignature(
this WechatTenpayClient client,
string callbackTimestamp,
string callbackNonce,
string callbackBody,
string callbackSignature,
string callbackSerialNumber,
out Exception? error)
public static bool VerifyEventSignature(this WechatTenpayClient client, string callbackTimestamp, string callbackNonce, string callbackBody, string callbackSignature, string callbackSerialNumber, out Exception? error)
{
if (client == null) throw new ArgumentNullException(nameof(client));
if (callbackTimestamp == null) throw new ArgumentNullException(nameof(callbackTimestamp));

View File

@ -40,11 +40,55 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
if (client == null) throw new ArgumentNullException(nameof(client));
if (response == null) throw new ArgumentNullException(nameof(response));
return VerifyResponseSignature(client, response.WechatpayTimestamp, response.WechatpayNonce, Encoding.UTF8.GetString(response.RawBytes), response.WechatpaySignature, response.WechatpayCertificateSerialNumber, out error);
}
/// <summary>
/// <para>验证响应签名。</para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_1.shtml </para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/wechatpay/wechatpay4_1.shtml </para>
/// </summary>
/// <param name="client"></param>
/// <param name="responseTimestamp"></param>
/// <param name="responseNonce">。</param>
/// <param name="responseBody"></param>
/// <param name="responseSignature"></param>
/// <param name="responseSerialNumber"></param>
/// <returns></returns>
public static bool VerifyResponseSignature(this WechatTenpayClient client, string responseTimestamp, string responseNonce, string responseBody, string responseSignature, string responseSerialNumber)
{
return VerifyResponseSignature(client, responseTimestamp, responseNonce, responseBody, responseSignature, responseSerialNumber, out _);
}
/// <summary>
/// <para>验证响应签名。</para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_1.shtml </para>
/// <para>REF: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/wechatpay/wechatpay4_1.shtml </para>
/// </summary>
/// <typeparam name="TResponse"></typeparam>
/// <param name="client"></param>
/// <param name="responseTimestamp"></param>
/// <param name="responseNonce">。</param>
/// <param name="responseBody"></param>
/// <param name="responseSignature"></param>
/// <param name="responseSerialNumber"></param>
/// <param name="error"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
public static bool VerifyResponseSignature(this WechatTenpayClient client, string responseTimestamp, string responseNonce, string responseBody, string responseSignature, string responseSerialNumber, out Exception? error)
{
if (client == null) throw new ArgumentNullException(nameof(client));
if (responseTimestamp == null) throw new ArgumentNullException(nameof(responseTimestamp));
if (responseNonce == null) throw new ArgumentNullException(nameof(responseNonce));
if (responseBody == null) throw new ArgumentNullException(nameof(responseBody));
if (responseSignature == null) throw new ArgumentNullException(nameof(responseSignature));
if (responseSerialNumber == null) throw new ArgumentNullException(nameof(responseSerialNumber));
if (client.PlatformCertificateManager != null)
{
try
{
var cert = client.PlatformCertificateManager.GetEntry(response.WechatpayCertificateSerialNumber)!;
var cert = client.PlatformCertificateManager.GetEntry(responseSerialNumber)!;
if (!cert.HasValue)
{
error = new Exceptions.WechatTenpayResponseVerificationException("Verify signature of response failed, because there is no platform certificate matched the serial number.");
@ -54,8 +98,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
error = null;
return Utilities.RSAUtility.VerifyWithSHA256ByCertificate(
certificate: cert.Value.Certificate,
plainText: GetPlainTextForSignature(response),
signature: response.WechatpaySignature
plainText: GetPlainTextForSignature(timestamp: responseTimestamp, nonce: responseNonce, body: responseBody),
signature: responseSignature
);
}
catch (Exception ex)
@ -69,11 +113,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
return false;
}
private static string GetPlainTextForSignature(WechatTenpayResponse response)
private static string GetPlainTextForSignature(string timestamp, string nonce, string body)
{
string timestamp = response.WechatpayTimestamp;
string nonce = response.WechatpayNonce;
string body = Encoding.UTF8.GetString(response.RawBytes);
return $"{timestamp}\n{nonce}\n{body}\n";
}
}

View File

@ -6,14 +6,14 @@ using Flurl.Http;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Interceptors
{
internal class WechatTenpaySignInterceptor : FlurlHttpCallInterceptor
internal class WechatTenpayRequestSignatureInterceptor : FlurlHttpCallInterceptor
{
private readonly string _scheme;
private readonly string _mchId;
private readonly string _mchCertSn;
private readonly string _mchCertPk;
public WechatTenpaySignInterceptor(string scheme, string mchId, string mchCertSn, string mchCertPk)
public WechatTenpayRequestSignatureInterceptor(string scheme, string mchId, string mchCertSn, string mchCertPk)
{
_scheme = scheme;
_mchId = mchId;
@ -24,6 +24,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Interceptors
public override async Task BeforeCallAsync(FlurlCall flurlCall)
{
if (flurlCall == null) throw new ArgumentNullException(nameof(flurlCall));
if (flurlCall.Completed) throw new Exceptions.WechatTenpayRequestSignatureException("This interceptor must be called before request completed.");
string method = flurlCall.HttpRequestMessage.Method.ToString().ToUpper();
string url = flurlCall.HttpRequestMessage.RequestUri?.PathAndQuery ?? string.Empty;
@ -68,8 +69,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Interceptors
}
string auth = $"mchid=\"{_mchId}\",nonce_str=\"{nonce}\",signature=\"{signText}\",timestamp=\"{timestamp}\",serial_no=\"{_mchCertSn}\"";
flurlCall.Request.Headers.Remove("Authorization");
flurlCall.Request.WithHeader("Authorization", $"{_scheme} {auth}");
flurlCall.Request.Headers.Remove(Contants.HttpHeaders.Authorization);
flurlCall.Request.WithHeader(Contants.HttpHeaders.Authorization, $"{_scheme} {auth}");
}
}
}

View File

@ -55,7 +55,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
FlurlClient.WithHeader(Contants.HttpHeaders.UserAgent, options.UserAgent);
FlurlClient.WithTimeout(TimeSpan.FromMilliseconds(options.Timeout));
Interceptors.Add(new Interceptors.WechatTenpaySignInterceptor(
Interceptors.Add(new Interceptors.WechatTenpayRequestSignatureInterceptor(
scheme: options.SignAlgorithm,
mchId: options.MerchantId,
mchCertSn: options.MerchantCertificateSerialNumber,