JeffreySu/WeiXinMPSDK · error · InvalidOperationException
通知中不包含 resource 节点。
Error message
通知中不包含 resource 节点。
What it means
The notification carries no `resource` node, which is where the encrypted business payload lives, so there is nothing to decrypt. The library throws InvalidOperationException to signal the message entity was populated without the required encrypted payload.
Solutions
- Check resource != null before calling DecryptResource and skip decryption when absent
- Verify the incoming notification actually is an encrypted mini-program payment event by inspecting the raw callback body
- If parsing from XML, confirm the deserialization maps the resource node onto the entity correctly
Example fix
// before var plain = message.DecryptResource(aesKey); // after var plain = message.Resource == null ? null : message.DecryptResource(aesKey);
Defensive patterns
Strategy: validation
Validate before calling
if (message.Resource == null)
{
log.Info("Notification has no resource node; skipping decryption");
return;
} Type guard
static bool HasDecryptableResource(RequestMessageEvent_MiniProgramPay m) => m?.Resource != null;
Try / catch
try { var plain = msg.DecryptResource(aesKey); }
catch (InvalidOperationException ex) when (ex.Message.Contains("resource")) { log.Warn("No resource node in notification"); } Prevention
- Check Resource before decrypting; some events ship without an encrypted payload
- Validate the raw callback body contains the resource block during webhook integration testing
- Keep deserialization mappings for the resource node up to date with SDK upgrades
When it happens
Trigger: Calling DecryptResource on a RequestMessageEvent_MiniProgramPay whose Resource property is null — e.g. the entity was created manually or deserialized from a message without the resource field.
Common situations: Testing with hand-crafted callback XML/JSON missing the resource block, or handling a different event type whose payload is unencrypted and mistakenly calling DecryptResource on it.
Related errors
AI-assisted analysis of JeffreySu/WeiXinMPSDK@be573f6f94 (2026-09-12).
Data as JSON: /api/errors/95d66b49589f9915.
Report an issue: GitHub.
Appendix: source
Thrown at src/Senparc.Weixin.Work/Senparc.Weixin.Work/Entities/Request/Event/RequestMessageEvent_MiniProgramPay.cs:77
/// <summary>
/// 使用“对外收款”应用回调配置中的 EncodingAESKey 解密业务资源。
/// .NET Framework 与 netstandard2.0 不提供平台 AES-GCM 实现,将抛出
/// <see cref="PlatformNotSupportedException"/>;这些目标仍可接收完整加密通知模型。
/// </summary>
public string DecryptResource(string encodingAesKey)
{
#if NET462 || NETSTANDARD2_0
throw new PlatformNotSupportedException(
"当前目标框架不提供 AES-GCM。请在 netstandard2.1、netcoreapp3.1 或更新目标中解密通知资源。");
#else
if (string.IsNullOrEmpty(encodingAesKey) || encodingAesKey.Length != 43)
{
throw new ArgumentException("EncodingAESKey 必须为 43 个字符。", nameof(encodingAesKey));
}
if (resource == null)
{
throw new InvalidOperationException("通知中不包含 resource 节点。");
}
if (!string.Equals(resource.algorithm, "AEAD_AES_256_GCM", StringComparison.OrdinalIgnoreCase))
{
throw new NotSupportedException($"不支持的通知资源加密算法:{resource.algorithm}");
}
var key = Convert.FromBase64String(encodingAesKey + "=");
var encrypted = Convert.FromBase64String(resource.ciphertext);
const int tagSize = 16;
if (encrypted.Length <= tagSize)
{
throw new CryptographicException("通知资源密文长度无效。");
}
var ciphertext = new byte[encrypted.Length - tagSize];
var tag = new byte[tagSize];
var plaintext = new byte[ciphertext.Length];View on GitHub (pinned to be573f6f94)