JeffreySu/WeiXinMPSDK · error · TenpayApiRequestException
RequestAsync 签名验证失败:
Error message
RequestAsync 签名验证失败:
What it means
VerifyResponseMessage verifies the Wechatpay-Signature on the API response using the public key resolved for the Wechatpay-Serial. Any failure inside that process (missing/unknown serial, bad public key, signature mismatch, network error fetching the key) is wrapped into a TenpayApiRequestException with the prefix 'RequestAsync 签名验证失败:' followed by the inner exception message.
Solutions
- Read the inner exception message to identify the root cause (unknown serial vs. signature mismatch).
- Update/download the current WeChat Pay platform certificates or public key so the serial in Wechatpay-Serial can be resolved.
- Ensure no proxy rewrites the response body or strips Wechatpay-* headers; bypass intermediaries to test.
- If TenPayV3_TenPayPubKeyEnable is toggled, confirm it matches your merchant platform mode (public key mode vs certificate mode).
Example fix
// before (catching generic)
catch (Exception ex) { log(ex.Message); }
// after
catch (TenpayApiRequestException ex)
{
log("Response signature verify failed: " + ex.InnerException?.Message);
// refresh platform certs / public key, then retry
} Defensive patterns
Strategy: try-catch
Validate before calling
// Ensure key material is current before the call
var serial = response.Headers.TryGetValues("Wechatpay-Serial", out var v) ? v.First() : null;
if (serial != null && !await keyStore.ContainsSerialAsync(serial)) await keyStore.RefreshAsync(); Try / catch
try { var result = await client.SendAsync(...); }
catch (TenpayApiRequestException ex) when (ex.Message.StartsWith("RequestAsync 签名验证失败"))
{ logger.LogWarning(ex.InnerException, "Response signature verification failed"); /* refresh certs, retry once */ } Prevention
- Periodically refresh WeChat Pay platform certificates/public keys.
- Ensure proxies don't rewrite response bodies or strip Wechatpay-* headers.
- Keep server clocks synchronized (NTP) to avoid timestamp checks failing.
When it happens
Trigger: Calling any TenPayV3 API through SendAsync where the response signature cannot be verified: the Wechatpay-Serial does not match a known key, GetAPIv3PublicKeyAsync fails or returns the wrong key, the response body was altered/proxied, or the timestamp/nonce headers were missing.
Common situations: A reverse proxy or gateway rewrites the response (breaking the signature); merchant switched between platform certificates and public key mode so the serial lookup fails; expired platform certificate after WeChat rotation; clock skew making timestamp verification fail.
Related errors
- 下载微信支付文件失败,HTTP ( ):
- 证书中未包含 RSA 公钥。
- 品牌 API 响应的微信支付公钥 ID 与配置不匹配。
- RequestAsync 签名验证失败:
- 品牌 API 通知的微信支付公钥 ID 与配置不匹配。
AI-assisted analysis of JeffreySu/WeiXinMPSDK@be573f6f94 (2026-09-12).
Data as JSON: /api/errors/e85d77780bf1a0d7.
Report an issue: GitHub.
Appendix: source
Thrown at src/Senparc.Weixin.TenPay/Senparc.Weixin.TenPayV3/TenPayHttpClient/TenPayHttpClient.cs:295
{
return VerifyResponseMessage(responseMessage, content, CancellationToken.None);
}
protected async Task<bool> VerifyResponseMessage(HttpResponseMessage responseMessage, string content, CancellationToken cancellationToken)
{
var wechatpayTimestamp = responseMessage.Headers.GetValues("Wechatpay-Timestamp").First();
var wechatpayNonce = responseMessage.Headers.GetValues("Wechatpay-Nonce").First();
var wechatpaySignatureBase64 = responseMessage.Headers.GetValues("Wechatpay-Signature").First();//后续需要base64解码
var wechatpaySerial = responseMessage.Headers.GetValues("Wechatpay-Serial").First();
try
{
var pubKey = await TenPayV3InfoCollection.GetAPIv3PublicKeyAsync(this._tenpayV3Setting, wechatpaySerial, cancellationToken).ConfigureAwait(false);
return _verifier.Verify(wechatpayTimestamp, wechatpayNonce, wechatpaySignatureBase64, content, pubKey, this._tenpayV3Setting.TenPayV3_TenPayPubKeyEnable);
}
catch (Exception ex)
{
throw new TenpayApiRequestException("RequestAsync 签名验证失败:" + ex.Message, ex);
}
}
/// <summary>
/// 获取实例
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="throwIfFaild"></param>
/// <returns></returns>
private T GetInstance<T>(bool throwIfFaild)
where T : ReturnJsonBase
{
if (typeof(T).IsClass)
{
return Senparc.CO2NET.Helpers.ReflectionHelper.CreateInstance<T>(typeof(T).FullName, typeof(T).Assembly.GetName().Name);
}
else if (throwIfFaild)
{View on GitHub (pinned to be573f6f94)