JeffreySu/WeiXinMPSDK · error · ArgumentNullException
brandApiCredentials
Error message
brandApiCredentials
What it means
Same DecryptBrandGetObjectAsync flow as the brandApiKey guard: the method also requires TenPayBrandApiCredentials, which carry the WeChat Pay public key needed to verify the callback signature before decryption. A null credentials object means signature verification cannot be performed, so the method throws ArgumentNullException naming brandApiCredentials. Callers must provide the brand's credentials containing its public key.
Solutions
- Construct TenPayBrandApiCredentials (serial number + key material) before calling the decrypt method
- Bind brand credentials from configuration at startup and fail fast if missing
- Null-check the credentials object before invoking the method
- Ensure the DI container registers TenPayBrandApiCredentials correctly
Example fix
// before await handler.DecryptBrandGetObjectAsync<T>(apiKey, null); // after var creds = new TenPayBrandApiCredentials(serialNumber, privateKey); await handler.DecryptBrandGetObjectAsync<T>(apiKey, creds);
Defensive patterns
Strategy: type-guard
Validate before calling
if (brandApiCredentials is null)
throw new InvalidOperationException("TenPayBrandApiCredentials 未初始化。"); Type guard
bool HasBrandCredentials(TenPayBrandApiCredentials? c) => c is not null;
Try / catch
try { var obj = await handler.DecryptBrandGetObjectAsync<T>(apiKey, creds); }
catch (ArgumentNullException ex) when (ex.ParamName == nameof(brandApiCredentials)) { logger.LogError(ex, "品牌凭据为空"); } Prevention
- Register brand credentials in DI with validation on construction
- Fail fast at startup if required credential material is missing
When it happens
Trigger: Invoking DecryptBrandGetObjectAsync with brandApiCredentials not constructed (null), typically when credential creation earlier failed silently.
Common situations: Config binding failures leaving credentials null, conditional wiring where brand credentials are only created for some environments, or refactoring that removed credential construction.
Related errors
- httpContext
- 品牌 API 密钥不能为空。
- 通知正文中缺少加密资源 resource。
- buttonGroupBase不可以为空!
- WeixinPayInfoCollection尚未注册Partner:
AI-assisted analysis of JeffreySu/WeiXinMPSDK@be573f6f94 (2026-09-12).
Data as JSON: /api/errors/309dbd4cc485a308.
Report an issue: GitHub.
Appendix: source
Thrown at src/Senparc.Weixin.TenPay/Senparc.Weixin.TenPayV3/HttpHandlers/TenPayNotifyHandler.cs:358
/// </summary>
/// <typeparam name="T">解密后的强类型通知模型。</typeparam>
/// <param name="brandApiKey">品牌 API 密钥。</param>
/// <param name="brandApiCredentials">品牌 API 鉴权凭据,其中包含回调验签所需的微信支付公钥。</param>
/// <param name="nonce">加密随机串;为空时读取通知资源中的值。</param>
/// <param name="associatedData">附加数据;为空时读取通知资源中的值。</param>
/// <returns>验签并解密后的品牌通知。</returns>
public Task<T> DecryptBrandGetObjectAsync<T>(string brandApiKey,
TenPayBrandApiCredentials brandApiCredentials,
string nonce = null, string associatedData = null)
where T : ReturnJsonBase, new()
{
if (string.IsNullOrWhiteSpace(brandApiKey))
{
throw new ArgumentException("品牌 API 密钥不能为空。",
nameof(brandApiKey));
}
_ = brandApiCredentials ?? throw new ArgumentNullException(
nameof(brandApiCredentials));
var resource = NotifyRequest?.resource ?? throw new InvalidDataException(
"通知正文中缺少加密资源 resource。");
var wechatpayTimestamp =
_httpContext.Request.Headers?["Wechatpay-Timestamp"].ToString();
var wechatpayNonce =
_httpContext.Request.Headers?["Wechatpay-Nonce"].ToString();
var wechatpaySignature =
_httpContext.Request.Headers?["Wechatpay-Signature"].ToString();
var wechatpaySerial =
_httpContext.Request.Headers?["Wechatpay-Serial"].ToString();
if (!string.Equals(wechatpaySerial,
brandApiCredentials.WechatpayPublicKeyId,
StringComparison.Ordinal))
{
throw new InvalidOperationException(View on GitHub (pinned to be573f6f94)