mirror of
https://gitee.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat.git
synced 2025-07-17 10:41:58 +08:00
feat(tenpayv3): 基于 ErroredResult 改造验签相关扩展方法
This commit is contained in:
parent
1c42f912ef
commit
c631ece274
@ -2,6 +2,8 @@ using System;
|
||||
|
||||
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
|
||||
{
|
||||
using SKIT.FlurlHttpClient.Primitives;
|
||||
|
||||
public static class WechatTenpayClientEventVerificationExtensions
|
||||
{
|
||||
/// <summary>
|
||||
@ -16,7 +18,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
|
||||
/// <param name="webhookSignature">微信回调通知中的 "Wechatpay-Signature" 请求标头。</param>
|
||||
/// <param name="webhookSerialNumber">微信回调通知中的 "Wechatpay-Serial" 请求标头。</param>
|
||||
/// <returns></returns>
|
||||
public static bool VerifyEventSignature(this WechatTenpayClient client, string webhookTimestamp, string webhookNonce, string webhookBody, string webhookSignature, string webhookSerialNumber)
|
||||
public static ErroredResult VerifyEventSignature(this WechatTenpayClient client, string webhookTimestamp, string webhookNonce, string webhookBody, string webhookSignature, string webhookSerialNumber)
|
||||
{
|
||||
return VerifyEventSignature(
|
||||
client,
|
||||
@ -42,80 +44,19 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
|
||||
/// <param name="webhookSignatureType">微信回调通知中的 "Wechatpay-Signature-Type" 请求标头。</param>
|
||||
/// <param name="webhookSerialNumber">微信回调通知中的 "Wechatpay-Serial" 请求标头。</param>
|
||||
/// <returns></returns>
|
||||
public static bool VerifyEventSignature(this WechatTenpayClient client, string webhookTimestamp, string webhookNonce, string webhookBody, string webhookSignature, string webhookSignatureType, string webhookSerialNumber)
|
||||
{
|
||||
return VerifyEventSignature(
|
||||
client,
|
||||
webhookTimestamp: webhookTimestamp,
|
||||
webhookNonce: webhookNonce,
|
||||
webhookBody: webhookBody,
|
||||
webhookSignature: webhookSignature,
|
||||
webhookSignatureType: webhookSignatureType,
|
||||
webhookSerialNumber: webhookSerialNumber,
|
||||
out _
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>验证回调通知事件签名。</para>
|
||||
/// <para>REF: https://pay.weixin.qq.com/docs/merchant/development/interface-rules/signature-verification.html </para>
|
||||
/// <para>REF: https://pay.weixin.qq.com/docs/partner/development/interface-rules/signature-verification.html </para>
|
||||
/// </summary>
|
||||
/// <param name="client"></param>
|
||||
/// <param name="webhookTimestamp">微信回调通知中的 "Wechatpay-Timestamp" 请求标头。</param>
|
||||
/// <param name="webhookNonce">微信回调通知中的 "Wechatpay-Nonce" 请求标头。</param>
|
||||
/// <param name="webhookBody">微信回调通知中请求正文。</param>
|
||||
/// <param name="webhookSignature">微信回调通知中的 "Wechatpay-Signature" 请求标头。</param>
|
||||
/// <param name="webhookSerialNumber">微信回调通知中的 "Wechatpay-Serial" 请求标头。</param>
|
||||
/// <param name="error"></param>
|
||||
/// <returns></returns>
|
||||
public static bool VerifyEventSignature(this WechatTenpayClient client, string webhookTimestamp, string webhookNonce, string webhookBody, string webhookSignature, string webhookSerialNumber, out Exception? error)
|
||||
{
|
||||
return VerifyEventSignature(
|
||||
client,
|
||||
webhookTimestamp: webhookTimestamp,
|
||||
webhookNonce: webhookNonce,
|
||||
webhookBody: webhookBody,
|
||||
webhookSignature: webhookSignature,
|
||||
webhookSignatureType: Constants.SignSchemes.WECHATPAY2_RSA_2048_WITH_SHA256,
|
||||
webhookSerialNumber: webhookSerialNumber,
|
||||
out error
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>验证回调通知事件签名。</para>
|
||||
/// <para>REF: https://pay.weixin.qq.com/docs/merchant/development/interface-rules/signature-verification.html </para>
|
||||
/// <para>REF: https://pay.weixin.qq.com/docs/partner/development/interface-rules/signature-verification.html </para>
|
||||
/// </summary>
|
||||
/// <param name="client"></param>
|
||||
/// <param name="webhookTimestamp">微信回调通知中的 "Wechatpay-Timestamp" 请求标头。</param>
|
||||
/// <param name="webhookNonce">微信回调通知中的 "Wechatpay-Nonce" 请求标头。</param>
|
||||
/// <param name="webhookBody">微信回调通知中请求正文。</param>
|
||||
/// <param name="webhookSignature">微信回调通知中的 "Wechatpay-Signature" 请求标头。</param>
|
||||
/// <param name="webhookSignatureType">微信回调通知中的 "Wechatpay-Signature-Type" 请求标头。</param>
|
||||
/// <param name="webhookSerialNumber">微信回调通知中的 "Wechatpay-Serial" 请求标头。</param>
|
||||
/// <param name="error"></param>
|
||||
/// <returns></returns>
|
||||
public static bool VerifyEventSignature(this WechatTenpayClient client, string webhookTimestamp, string webhookNonce, string webhookBody, string webhookSignature, string webhookSignatureType, string webhookSerialNumber, out Exception? error)
|
||||
public static ErroredResult VerifyEventSignature(this WechatTenpayClient client, string webhookTimestamp, string webhookNonce, string webhookBody, string webhookSignature, string webhookSignatureType, string webhookSerialNumber)
|
||||
{
|
||||
if (client is null) throw new ArgumentNullException(nameof(client));
|
||||
|
||||
bool ret = WechatTenpayClientSigningExtensions.VerifySignature(
|
||||
return WechatTenpayClientSigningExtensions.VerifySignature(
|
||||
client,
|
||||
strTimestamp: webhookTimestamp,
|
||||
strNonce: webhookNonce,
|
||||
strContent: webhookBody,
|
||||
strSignature: webhookSignature,
|
||||
strSignScheme: webhookSignatureType,
|
||||
strSerialNumber: webhookSerialNumber,
|
||||
out error
|
||||
strSerialNumber: webhookSerialNumber
|
||||
);
|
||||
|
||||
if (!ret)
|
||||
error ??= new Exception($"Failed to verify webhook event. Maybe the raw signature \"{webhookSignature}\" is invalid.");
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,8 @@ using System.Text;
|
||||
|
||||
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
|
||||
{
|
||||
using SKIT.FlurlHttpClient.Primitives;
|
||||
|
||||
public static class WechatTenpayClientResponseVerificationExtensions
|
||||
{
|
||||
/// <summary>
|
||||
@ -14,23 +16,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
|
||||
/// <param name="client"></param>
|
||||
/// <param name="response"></param>
|
||||
/// <returns></returns>
|
||||
public static bool VerifyResponseSignature<TResponse>(this WechatTenpayClient client, TResponse response)
|
||||
where TResponse : WechatTenpayResponse
|
||||
{
|
||||
return VerifyResponseSignature(client, response, out _);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>验证响应签名。</para>
|
||||
/// <para>REF: https://pay.weixin.qq.com/docs/merchant/development/interface-rules/signature-verification.html </para>
|
||||
/// <para>REF: https://pay.weixin.qq.com/docs/partner/development/interface-rules/signature-verification.html </para>
|
||||
/// </summary>
|
||||
/// <typeparam name="TResponse"></typeparam>
|
||||
/// <param name="client"></param>
|
||||
/// <param name="response"></param>
|
||||
/// <param name="error"></param>
|
||||
/// <returns></returns>
|
||||
public static bool VerifyResponseSignature<TResponse>(this WechatTenpayClient client, TResponse response, out Exception? error)
|
||||
public static ErroredResult VerifyResponseSignature<TResponse>(this WechatTenpayClient client, TResponse response)
|
||||
where TResponse : WechatTenpayResponse
|
||||
{
|
||||
if (client is null) throw new ArgumentNullException(nameof(client));
|
||||
@ -43,8 +29,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
|
||||
responseBody: Encoding.UTF8.GetString(response.GetRawBytes()),
|
||||
responseSignature: response.WechatpaySignature,
|
||||
responseSignatureType: response.WechatpaySignatureType,
|
||||
responseSerialNumber: response.WechatpayCertificateSerialNumber,
|
||||
out error
|
||||
responseSerialNumber: response.WechatpayCertificateSerialNumber
|
||||
);
|
||||
}
|
||||
|
||||
@ -60,7 +45,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
|
||||
/// <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)
|
||||
public static ErroredResult VerifyResponseSignature(this WechatTenpayClient client, string responseTimestamp, string responseNonce, string responseBody, string responseSignature, string responseSerialNumber)
|
||||
{
|
||||
return VerifyResponseSignature(
|
||||
client,
|
||||
@ -69,7 +54,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
|
||||
responseBody: responseBody,
|
||||
responseSignature: responseSignature,
|
||||
responseSignatureType: Constants.SignSchemes.WECHATPAY2_RSA_2048_WITH_SHA256,
|
||||
responseSerialNumber: responseSerialNumber
|
||||
responseSerialNumber
|
||||
);
|
||||
}
|
||||
|
||||
@ -86,80 +71,19 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
|
||||
/// <param name="responseSignatureType"></param>
|
||||
/// <param name="responseSerialNumber"></param>
|
||||
/// <returns></returns>
|
||||
public static bool VerifyResponseSignature(this WechatTenpayClient client, string responseTimestamp, string responseNonce, string responseBody, string responseSignature, string responseSignatureType, string responseSerialNumber)
|
||||
{
|
||||
return VerifyResponseSignature(
|
||||
client,
|
||||
responseTimestamp: responseTimestamp,
|
||||
responseNonce: responseNonce,
|
||||
responseBody: responseBody,
|
||||
responseSignature: responseSignature,
|
||||
responseSignatureType: responseSignatureType,
|
||||
responseSerialNumber,
|
||||
out _
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>验证响应签名。</para>
|
||||
/// <para>REF: https://pay.weixin.qq.com/docs/merchant/development/interface-rules/signature-verification.html </para>
|
||||
/// <para>REF: https://pay.weixin.qq.com/docs/partner/development/interface-rules/signature-verification.html </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>
|
||||
/// <param name="error"></param>
|
||||
/// <returns></returns>
|
||||
public static bool VerifyResponseSignature(this WechatTenpayClient client, string responseTimestamp, string responseNonce, string responseBody, string responseSignature, string responseSerialNumber, out Exception? error)
|
||||
{
|
||||
return VerifyResponseSignature(
|
||||
client,
|
||||
responseTimestamp: responseTimestamp,
|
||||
responseNonce: responseNonce,
|
||||
responseBody: responseBody,
|
||||
responseSignature: responseSignature,
|
||||
responseSignatureType: Constants.SignSchemes.WECHATPAY2_RSA_2048_WITH_SHA256,
|
||||
responseSerialNumber,
|
||||
out error
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>验证响应签名。</para>
|
||||
/// <para>REF: https://pay.weixin.qq.com/docs/merchant/development/interface-rules/signature-verification.html </para>
|
||||
/// <para>REF: https://pay.weixin.qq.com/docs/partner/development/interface-rules/signature-verification.html </para>
|
||||
/// </summary>
|
||||
/// <param name="client"></param>
|
||||
/// <param name="responseTimestamp"></param>
|
||||
/// <param name="responseNonce">。</param>
|
||||
/// <param name="responseBody"></param>
|
||||
/// <param name="responseSignature"></param>
|
||||
/// <param name="responseSignatureType"></param>
|
||||
/// <param name="responseSerialNumber"></param>
|
||||
/// <param name="error"></param>
|
||||
/// <returns></returns>
|
||||
public static bool VerifyResponseSignature(this WechatTenpayClient client, string responseTimestamp, string responseNonce, string responseBody, string responseSignature, string responseSignatureType, string responseSerialNumber, out Exception? error)
|
||||
public static ErroredResult VerifyResponseSignature(this WechatTenpayClient client, string responseTimestamp, string responseNonce, string responseBody, string responseSignature, string responseSignatureType, string responseSerialNumber)
|
||||
{
|
||||
if (client is null) throw new ArgumentNullException(nameof(client));
|
||||
|
||||
bool ret = WechatTenpayClientSigningExtensions.VerifySignature(
|
||||
return WechatTenpayClientSigningExtensions.VerifySignature(
|
||||
client,
|
||||
strTimestamp: responseTimestamp,
|
||||
strNonce: responseNonce,
|
||||
strContent: responseBody,
|
||||
strSignature: responseSignature,
|
||||
strSignScheme: responseSignatureType,
|
||||
strSerialNumber: responseSerialNumber,
|
||||
out error
|
||||
strSerialNumber: responseSerialNumber
|
||||
);
|
||||
|
||||
if (!ret)
|
||||
error ??= new Exception($"Failed to verify response. Maybe the raw signature \"{responseSignature}\" is invalid.");
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,92 +7,90 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
|
||||
|
||||
internal static class WechatTenpayClientSigningExtensions
|
||||
{
|
||||
public static bool VerifySignature(this WechatTenpayClient client, string strTimestamp, string strNonce, string strContent, string strSignature, string strSignScheme, string strSerialNumber, out Exception? error)
|
||||
public static ErroredResult VerifySignature(this WechatTenpayClient client, string strTimestamp, string strNonce, string strContent, string strSignature, string strSignScheme, string strSerialNumber)
|
||||
{
|
||||
if (client is null) throw new ArgumentNullException(nameof(client));
|
||||
|
||||
ErroredResult result;
|
||||
|
||||
switch (strSignScheme)
|
||||
{
|
||||
case Constants.SignSchemes.WECHATPAY2_RSA_2048_WITH_SHA256:
|
||||
{
|
||||
if (client.PlatformCertificateManager is null)
|
||||
{
|
||||
error = new Exception("The platform certificate manager is not initialized.");
|
||||
return false;
|
||||
}
|
||||
|
||||
CertificateEntry? entry = client.PlatformCertificateManager.GetEntry(strSerialNumber);
|
||||
if (!entry.HasValue)
|
||||
{
|
||||
error = new Exception($"The platform certificate manager does not contain a certificate with serial number \"{strSerialNumber}\".");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CertificateEntry.ALGORITHM_TYPE_RSA.Equals(entry.Value.AlgorithmType))
|
||||
{
|
||||
error = new Exception($"The platform certificate with serial number \"{strSerialNumber}\" is not for RSA.");
|
||||
return false;
|
||||
}
|
||||
|
||||
error = null;
|
||||
try
|
||||
{
|
||||
return Utilities.RSAUtility.VerifyByCertificate(
|
||||
if (client.PlatformCertificateManager is null)
|
||||
{
|
||||
result = ErroredResult.Fail(new Exception("The platform certificate manager is not initialized."));
|
||||
break;
|
||||
}
|
||||
|
||||
CertificateEntry? entry = client.PlatformCertificateManager.GetEntry(strSerialNumber);
|
||||
if (!entry.HasValue)
|
||||
{
|
||||
result = ErroredResult.Fail(new Exception($"The platform certificate manager does not contain a certificate with serial number \"{strSerialNumber}\"."));
|
||||
break;
|
||||
}
|
||||
|
||||
bool valid = Utilities.RSAUtility.VerifyByCertificate(
|
||||
certificatePem: entry.Value.Certificate,
|
||||
message: GenerateMessageForSignature(timestamp: strTimestamp, nonce: strNonce, body: strContent),
|
||||
encodingSignature: new EncodedString(strSignature, EncodingKinds.Base64)
|
||||
);
|
||||
if (valid)
|
||||
result = ErroredResult.Ok();
|
||||
else
|
||||
result = ErroredResult.Fail(new Exception($"Signature does not match. Maybe \"{strSignature}\" is an illegal signature."));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
error = ex;
|
||||
return false;
|
||||
result = ErroredResult.Fail(ex);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Constants.SignSchemes.WECHATPAY2_SM2_WITH_SM3:
|
||||
{
|
||||
if (client.PlatformCertificateManager is null)
|
||||
{
|
||||
error = new Exception("The platform certificate manager is not initialized.");
|
||||
return false;
|
||||
}
|
||||
|
||||
CertificateEntry? entry = client.PlatformCertificateManager.GetEntry(strSerialNumber);
|
||||
if (!entry.HasValue)
|
||||
{
|
||||
error = new Exception($"The platform certificate manager does not contain a certificate with serial number \"{strSerialNumber}\".");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CertificateEntry.ALGORITHM_TYPE_SM2.Equals(entry.Value.AlgorithmType))
|
||||
{
|
||||
error = new Exception($"The platform certificate with serial number \"{strSerialNumber}\" is not for SM2.");
|
||||
return false;
|
||||
}
|
||||
|
||||
error = null;
|
||||
try
|
||||
{
|
||||
return Utilities.SM2Utility.VerifyWithSM3ByCertificate(
|
||||
if (client.PlatformCertificateManager is null)
|
||||
{
|
||||
result = ErroredResult.Fail(new Exception("The platform certificate manager is not initialized."));
|
||||
break;
|
||||
}
|
||||
|
||||
CertificateEntry? entry = client.PlatformCertificateManager.GetEntry(strSerialNumber);
|
||||
if (!entry.HasValue)
|
||||
{
|
||||
result = ErroredResult.Fail(new Exception($"The platform certificate manager does not contain a certificate with serial number \"{strSerialNumber}\"."));
|
||||
break;
|
||||
}
|
||||
|
||||
bool valid = Utilities.SM2Utility.VerifyWithSM3ByCertificate(
|
||||
certificatePem: entry.Value.Certificate,
|
||||
message: GenerateMessageForSignature(timestamp: strTimestamp, nonce: strNonce, body: strContent),
|
||||
encodingSignature: new EncodedString(strSignature, EncodingKinds.Base64)
|
||||
);
|
||||
if (valid)
|
||||
result = ErroredResult.Ok();
|
||||
else
|
||||
result = ErroredResult.Fail(new Exception($"Signature does not match. Maybe \"{strSignature}\" is an illegal signature."));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
error = ex;
|
||||
return false;
|
||||
result = ErroredResult.Fail(ex);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
error = new Exception($"Unsupported signing scheme: \"{strSignScheme}\".");
|
||||
return false;
|
||||
result = ErroredResult.Fail(new Exception($"Unsupported signing scheme: \"{strSignScheme}\"."));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static string GenerateMessageForSignature(string timestamp, string nonce, string body)
|
||||
|
Loading…
Reference in New Issue
Block a user