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

  1. Check resource != null before calling DecryptResource and skip decryption when absent
  2. Verify the incoming notification actually is an encrypted mini-program payment event by inspecting the raw callback body
  3. 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

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)