using System;
using System.Text;
namespace SKIT.FlurlHttpClient.Wechat.TenpayV3
{
///
/// 为 提供响应签名验证的扩展方法。
///
public static class WechatTenpayClientResponseVerificationExtensions
{
///
/// 验证响应签名。
/// REF: https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_1.shtml
/// REF: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/wechatpay/wechatpay4_1.shtml
///
///
///
///
///
public static bool VerifyResponseSignature(this WechatTenpayClient client, TResponse response)
where TResponse : WechatTenpayResponse
{
return VerifyResponseSignature(client, response, out _);
}
///
/// 验证响应签名。
/// REF: https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_1.shtml
/// REF: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/wechatpay/wechatpay4_1.shtml
///
///
///
///
///
///
///
public static bool VerifyResponseSignature(this WechatTenpayClient client, TResponse response, out Exception? error)
where TResponse : WechatTenpayResponse
{
if (client == null) throw new ArgumentNullException(nameof(client));
if (response == null) throw new ArgumentNullException(nameof(response));
if (client.CertificateManager != null)
{
try
{
var cert = client.CertificateManager.GetEntry(response.WechatpayCertSerialNumber)!;
if (!cert.HasValue)
{
error = new Exceptions.WechatTenpayResponseVerificationException("Verify signature of response failed, because there is no platform certificate matched the serial number.");
return false;
}
error = null;
return Utilities.RSAUtility.VerifyWithSHA256ByCertificate(
certificate: cert.Value.Certificate,
plainText: GetPlainTextForSignature(response),
signature: response.WechatpaySignature
);
}
catch (Exception ex)
{
error = new Exceptions.WechatTenpayResponseVerificationException("Verify signature of response failed. Please see the `InnerException` for more details.", ex);
return false;
}
}
error = new Exceptions.WechatTenpayResponseVerificationException("Verify signature of response failed, because there is no platform certificate in the manager.");
return false;
}
private static string GetPlainTextForSignature(WechatTenpayResponse response)
{
string timestamp = response.WechatpayTimestamp;
string nonce = response.WechatpayNonce;
string body = Encoding.UTF8.GetString(response.RawBytes);
return $"{timestamp}\n{nonce}\n{body}\n";
}
}
}