2021-07-20 01:20:31 +08:00
using System ;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
{
/// <summary>
/// 为 <see cref="WechatTenpayClient"/> 提供回调通知事件签名验证的扩展方法。
/// </summary>
public static class WechatTenpayClientEventVerificationExtensions
{
/// <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="callbackTimestamp">微信回调通知中的 Wechatpay-Timestamp 字段。</param>
/// <param name="callbackNonce">微信回调通知中的 Wechatpay-Nonce 字段。</param>
/// <param name="callbackBody">微信回调通知中请求正文。</param>
/// <param name="callbackSignature">微信回调通知中的 Wechatpay-Signature 字段。</param>
/// <param name="callbackSerialNumber">微信回调通知中的 Wechatpay-Serial 字段。</param>
/// <returns></returns>
2021-07-20 19:27:39 +08:00
public static bool VerifyEventSignature (
2022-01-21 14:30:17 +08:00
this WechatTenpayClient client ,
string callbackTimestamp ,
string callbackNonce ,
2021-07-20 01:20:31 +08:00
string callbackBody ,
string callbackSignature ,
string callbackSerialNumber )
2021-11-25 11:58:06 +08:00
{
return VerifyEventSignature ( client , callbackTimestamp , callbackNonce , callbackBody , callbackSignature , callbackSerialNumber , 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>
/// <param name="client"></param>
/// <param name="callbackTimestamp">微信回调通知中的 Wechatpay-Timestamp 字段。</param>
/// <param name="callbackNonce">微信回调通知中的 Wechatpay-Nonce 字段。</param>
/// <param name="callbackBody">微信回调通知中请求正文。</param>
/// <param name="callbackSignature">微信回调通知中的 Wechatpay-Signature 字段。</param>
/// <param name="callbackSerialNumber">微信回调通知中的 Wechatpay-Serial 字段。</param>
/// <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 )
2021-07-20 01:20:31 +08:00
{
if ( client = = null ) throw new ArgumentNullException ( nameof ( client ) ) ;
if ( callbackTimestamp = = null ) throw new ArgumentNullException ( nameof ( callbackTimestamp ) ) ;
if ( callbackNonce = = null ) throw new ArgumentNullException ( nameof ( callbackNonce ) ) ;
if ( callbackBody = = null ) throw new ArgumentNullException ( nameof ( callbackBody ) ) ;
if ( callbackSignature = = null ) throw new ArgumentNullException ( nameof ( callbackSignature ) ) ;
if ( callbackSerialNumber = = null ) throw new ArgumentNullException ( nameof ( callbackSerialNumber ) ) ;
2022-01-21 14:41:40 +08:00
if ( client . PlatformCertificateManager ! = null )
2021-07-20 01:20:31 +08:00
{
try
{
2022-01-21 14:41:40 +08:00
var cert = client . PlatformCertificateManager . GetEntry ( callbackSerialNumber ) ;
2021-11-25 11:58:06 +08:00
if ( ! cert . HasValue )
{
error = new Exceptions . WechatTenpayEventVerificationException ( "Verify signature of event failed, because there is no platform certificate matched the serial number." ) ;
return false ;
}
2021-07-20 01:20:31 +08:00
2021-11-25 11:58:06 +08:00
error = null ;
return Utilities . RSAUtility . VerifyWithSHA256ByCertificate (
certificate : cert . Value . Certificate ,
2021-07-20 01:20:31 +08:00
plainText : GetPlainTextForSignature ( timestamp : callbackTimestamp , nonce : callbackNonce , body : callbackBody ) ,
signature : callbackSignature
) ;
}
2021-11-25 11:58:06 +08:00
catch ( Exception ex )
{
error = new Exceptions . WechatTenpayEventVerificationException ( "Verify signature of event failed. Please see the `InnerException` for more details." , ex ) ;
return false ;
}
2021-07-20 01:20:31 +08:00
}
2021-08-02 22:06:22 +08:00
2021-11-25 11:58:06 +08:00
error = new Exceptions . WechatTenpayEventVerificationException ( "Verify signature of event failed, because there is no platform certificate in the manager." ) ;
2021-08-02 22:06:22 +08:00
return false ;
2021-07-20 01:20:31 +08:00
}
private static string GetPlainTextForSignature ( string timestamp , string nonce , string body )
{
return $"{timestamp}\n{nonce}\n{body}\n" ;
}
}
}