JeffreySu/WeiXinMPSDK · error · ArgumentException
收银台 API 调用密钥不能为空。
Error message
收银台 API 调用密钥不能为空。
What it means
CreateSignature throws this ArgumentException when payToolApiSecret is null or empty. The signature is computed as HMAC-style signing over the sorted request key/value pairs using this secret, so an absent secret makes signing impossible. PrepareRequest invokes CreateSignature when it must generate sig itself, which propagates this error.
Solutions
- Provide the cashier API secret from your WeChat Work merchant configuration.
- Add a startup config check that fails fast when the secret is missing/empty.
- Confirm you are using the correct secret for the PayTool cashier API (not other WeChat Work tokens).
Example fix
// before
var sig = PayToolSignatureHelper.CreateSignature(request, config.PayToolSecret); // PayToolSecret == ""
// after
if (string.IsNullOrEmpty(config.PayToolSecret))
throw new InvalidOperationException("请在配置中填写收银台 API 调用密钥");
var sig = PayToolSignatureHelper.CreateSignature(request, config.PayToolSecret); Defensive patterns
Strategy: validation
Validate before calling
if (string.IsNullOrEmpty(payToolApiSecret)) throw new InvalidOperationException("收银台 API 密钥未配置"); Try / catch
try { var sig = CreateSignature(request, secret); } catch (ArgumentException ex) when (ex.ParamName == nameof(payToolApiSecret)) { logger.LogError(ex, "签名密钥为空"); throw new ConfigurationException("请配置收银台 API 调用密钥"); } Prevention
- Validate all required secrets at application startup, not at first API call.
- Keep secrets in a single config section with load-time assertions.
- Document which secret belongs to which API surface (cashier vs. other WeChat Work credentials).
When it happens
Trigger: Calling CreateSignature (directly or via PrepareRequest without a sig in the request) with payToolApiSecret set to null or "".
Common situations: Missing cashier API secret in configuration files, environment variable not set, or secret left as empty string after copying config templates, or upgraded library versions that newly require the secret parameter.
Related errors
- 请求未提供 sig 时必须提供收银台 API 调用密钥。
- 方法路径不能为空
- 商品券图片仅支持 JPG、JPEG、BMP 或 PNG。
- ArgumentOutOfRangeException (length must be >= 0)
- BotID 不能为空。
AI-assisted analysis of JeffreySu/WeiXinMPSDK@be573f6f94 (2026-09-12).
Data as JSON: /api/errors/64b997717df08929.
Report an issue: GitHub.
Appendix: source
Thrown at src/Senparc.Weixin.Work/Senparc.Weixin.Work/AdvancedAPIs/PayTool/PayToolSignatureHelper.cs:89
}
/// <summary>
/// 按企业微信规则递归展开非空叶子参数、按完整 key=value 字符串升序排列,
/// 再使用收银台 API 调用密钥计算 HMAC-SHA256 并进行 Base64 编码。
/// </summary>
/// <param name="request">请求对象;任意层级名为 sig 的字段不参与签名。</param>
/// <param name="payToolApiSecret">收银台 API 调用密钥。</param>
/// <returns>Base64 编码的数字签名。</returns>
public static string CreateSignature(object request, string payToolApiSecret)
{
if (request == null)
{
throw new ArgumentNullException(nameof(request));
}
if (string.IsNullOrEmpty(payToolApiSecret))
{
throw new ArgumentException("收银台 API 调用密钥不能为空。",
nameof(payToolApiSecret));
}
var pairs = new List<string>();
CollectPairs(null, JToken.FromObject(request), pairs);
pairs.Sort(StringComparer.Ordinal);
var signingText = string.Join("&", pairs);
using (var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(payToolApiSecret)))
{
return Convert.ToBase64String(
hmac.ComputeHash(Encoding.UTF8.GetBytes(signingText)));
}
}
private static void CollectPairs(string key, JToken token, ICollection<string> pairs)
{
if (token == null || token.Type == JTokenType.Null ||View on GitHub (pinned to be573f6f94)