2022-11-13 23:17:18 +08:00
using System ;
2024-02-06 11:23:04 +08:00
using System.Threading ;
using System.Threading.Tasks ;
2022-05-09 19:28:47 +08:00
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
{
2024-02-05 10:53:59 +08:00
using SKIT.FlurlHttpClient.Primitives ;
2024-02-06 11:23:04 +08:00
using SKIT.FlurlHttpClient.Wechat.TenpayV3.Constants ;
2023-03-30 21:40:48 +08:00
using SKIT.FlurlHttpClient.Wechat.TenpayV3.Settings ;
2024-01-29 23:12:37 +08:00
internal static class WechatTenpayClientSigningExtensions
2022-05-09 19:28:47 +08:00
{
2024-02-05 15:58:42 +08:00
public static ErroredResult VerifySignature ( this WechatTenpayClient client , string strTimestamp , string strNonce , string strContent , string strSignature , string strSignScheme , string strSerialNumber )
2022-05-09 19:28:47 +08:00
{
2024-01-29 23:12:37 +08:00
if ( client is null ) throw new ArgumentNullException ( nameof ( client ) ) ;
2022-05-09 19:28:47 +08:00
2024-02-06 11:23:04 +08:00
CertificateEntry ? entry = client . PlatformCertificateManager . GetEntry ( strSerialNumber ) ;
if ( ! entry . HasValue )
{
2024-07-18 15:56:20 +08:00
return ErroredResult . Fail ( new Exception ( $"The platform certificate manager does not contain a certificate matched the serial number \" { strSerialNumber } \ "." ) ) ;
2024-02-06 11:23:04 +08:00
}
return GenerateSignatureResultByCertificate (
scheme : strSignScheme ,
certificate : entry . Value . Certificate ,
message : GenerateMessageForSignature ( timestamp : strTimestamp , nonce : strNonce , body : strContent ) ,
signature : strSignature
) ;
}
public static async Task < ErroredResult > VerifySignatureAsync ( this WechatTenpayClient client , string strTimestamp , string strNonce , string strContent , string strSignature , string strSignScheme , string strSerialNumber , CancellationToken cancellationToken = default )
{
if ( client is null ) throw new ArgumentNullException ( nameof ( client ) ) ;
if ( client . PlatformCertificateManager is not ICertificateManagerAsync )
{
// 降级为同步调用
return VerifySignature ( client , strTimestamp , strNonce , strContent , strSignature , strSignScheme , strSerialNumber ) ;
}
CertificateEntry ? entry = await ( ( ICertificateManagerAsync ) client . PlatformCertificateManager ) . GetEntryAsync ( strSerialNumber , cancellationToken ) . ConfigureAwait ( false ) ;
if ( ! entry . HasValue )
{
2024-07-18 15:56:20 +08:00
return ErroredResult . Fail ( new Exception ( $"The platform certificate manager does not contain a certificate matched the serial number \" { strSerialNumber } \ "." ) ) ;
2024-02-06 11:23:04 +08:00
}
return GenerateSignatureResultByCertificate (
scheme : strSignScheme ,
certificate : entry . Value . Certificate ,
message : GenerateMessageForSignature ( timestamp : strTimestamp , nonce : strNonce , body : strContent ) ,
signature : strSignature
) ;
}
private static string GenerateMessageForSignature ( string timestamp , string nonce , string body )
{
return $"{timestamp}\n{nonce}\n{body}\n" ;
}
private static ErroredResult GenerateSignatureResultByCertificate ( string scheme , string certificate , string message , string signature )
{
2024-02-05 15:58:42 +08:00
ErroredResult result ;
2024-02-06 11:23:04 +08:00
switch ( scheme )
2022-11-13 23:17:18 +08:00
{
2024-02-06 11:23:04 +08:00
case SignSchemes . WECHATPAY2_RSA_2048_WITH_SHA256 :
2022-11-13 23:17:18 +08:00
{
2024-02-05 15:58:42 +08:00
try
2022-11-13 23:17:18 +08:00
{
2024-05-21 16:01:20 +08:00
bool valid = Utilities . RSAUtility . VerifyWithSHA256ByCertificate (
2024-02-06 11:23:04 +08:00
certificatePem : certificate ,
messageData : message ,
encodingSignature : new EncodedString ( signature , EncodingKinds . Base64 )
2022-11-13 23:17:18 +08:00
) ;
2024-02-05 15:58:42 +08:00
if ( valid )
result = ErroredResult . Ok ( ) ;
else
2024-02-06 11:23:04 +08:00
result = ErroredResult . Fail ( new Exception ( $"Signature does not match. Maybe \" { signature } \ " is an illegal signature." ) ) ;
2022-11-13 23:17:18 +08:00
}
catch ( Exception ex )
{
2024-02-05 15:58:42 +08:00
result = ErroredResult . Fail ( ex ) ;
2022-11-13 23:17:18 +08:00
}
}
2024-02-05 15:58:42 +08:00
break ;
2022-11-13 23:17:18 +08:00
2024-02-06 11:23:04 +08:00
case SignSchemes . WECHATPAY2_SM2_WITH_SM3 :
2022-05-09 19:28:47 +08:00
{
2024-02-05 15:58:42 +08:00
try
2022-05-09 19:28:47 +08:00
{
2024-02-05 15:58:42 +08:00
bool valid = Utilities . SM2Utility . VerifyWithSM3ByCertificate (
2024-02-06 11:23:04 +08:00
certificatePem : certificate ,
messageData : message ,
encodingSignature : new EncodedString ( signature , EncodingKinds . Base64 )
2022-11-13 23:17:18 +08:00
) ;
2024-02-05 15:58:42 +08:00
if ( valid )
result = ErroredResult . Ok ( ) ;
else
2024-02-06 11:23:04 +08:00
result = ErroredResult . Fail ( new Exception ( $"Signature does not match. Maybe \" { signature } \ " is an illegal signature." ) ) ;
2022-11-13 23:17:18 +08:00
}
catch ( Exception ex )
{
2024-02-05 15:58:42 +08:00
result = ErroredResult . Fail ( ex ) ;
2022-11-13 23:17:18 +08:00
}
2022-05-09 19:28:47 +08:00
}
2024-02-05 15:58:42 +08:00
break ;
2022-05-09 19:28:47 +08:00
default :
{
2024-02-06 11:23:04 +08:00
result = ErroredResult . Fail ( new Exception ( $"Unsupported signing scheme: \" { scheme } \ "." ) ) ;
2022-05-09 19:28:47 +08:00
}
2024-02-05 15:58:42 +08:00
break ;
2022-05-09 19:28:47 +08:00
}
2024-02-05 15:58:42 +08:00
return result ;
2022-05-09 19:28:47 +08:00
}
}
}