JeffreySu/WeiXinMPSDK · error · ArgumentException

品牌 API 密钥不能为空。

Error message

品牌 API 密钥不能为空。

What it means

DecryptBrandGetObjectAsync decrypts WeChat Pay brand-notification resources (AES-GCM) and verifies the callback signature. It throws when brandApiKey is null/empty: without the brand-specific API key the encrypted resource cannot be decrypted, so processing the notification is impossible. The offending input is the brandApiKey parameter; callers must supply the key configured for the brand in the WeChat Pay merchant platform.

Solutions

  1. Provide the Brand API v3 key obtained from the WeChat merchant platform (品牌接口密钥) when calling the method
  2. Load the brand API key from configuration and validate it at startup
  3. Guard the call: only invoke DecryptBrandGetObjectAsync when the key is present
  4. Distinguish the brand API key from the merchant APIv3 key — ensure the right credential is bound

Example fix

// before
await handler.DecryptBrandGetObjectAsync<T>(null, credentials);
// after
await handler.DecryptBrandGetObjectAsync<T>(brandApiKey: config["TenpayV3:BrandApiKey"], credentials);
Defensive patterns

Strategy: validation

Validate before calling

if (string.IsNullOrWhiteSpace(brandApiKey))
    throw new InvalidOperationException("品牌 API 密钥未配置。");

Type guard

bool HasBrandApiKey(string? key) => !string.IsNullOrWhiteSpace(key);

Try / catch

try { var obj = await handler.DecryptBrandGetObjectAsync<T>(brandApiKey, creds); }
catch (ArgumentException ex) when (ex.ParamName == nameof(brandApiKey)) { logger.LogError(ex, "品牌 API 密钥缺失"); }

Prevention

When it happens

Trigger: Calling DecryptBrandGetObjectAsync with null/empty brandApiKey while decrypting a brand notification resource.

Common situations: Brand API key not stored in configuration, copying generic V3 decryption sample code that omits the brand key, or key name mismatch in appsettings.

Understand the failure class

Background: "API key is required" / "API key not found" / "No API key was set": the missing-api-key error family across 16 libraries — this error's family across 16 libraries.

Related errors


AI-assisted analysis of JeffreySu/WeiXinMPSDK@be573f6f94 (2026-09-12). Data as JSON: /api/errors/4837e55e0b007657. Report an issue: GitHub.

Appendix: source

Thrown at src/Senparc.Weixin.TenPay/Senparc.Weixin.TenPayV3/HttpHandlers/TenPayNotifyHandler.cs:354

        }

        /// <summary>
        /// 使用品牌 API 专用密钥解密通知资源,并使用品牌关联的微信支付公钥验签。
        /// </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,

View on GitHub (pinned to be573f6f94)