JeffreySu/WeiXinMPSDK · error · OpenHardwareCallbackCryptException

OpenHardwareCallbackCryptException (encrypt failed…

Error message

OpenHardwareCallbackCryptException (encrypt failed, WXBizMsgCrypt error code)

What it means

EncryptResponse delegates the actual AES encryption/signing to WXBizMsgCrypt.EncryptJsonMsg. When that call returns a non-zero error code (e.g. invalid encodingAesKey, bad signature inputs), the library wraps the code in OpenHardwareCallbackCryptException to signal encryption of the callback reply failed.

Solutions

  1. Verify encodingAesKey is the exact 43-character EncodingAESKey from the WeChat Work console (no padding/whitespace)
  2. Verify token and receiveId match the callback configuration in the WeChat Work OpenHardware settings
  3. Read exception.ErrorCode and cross-check against the WXBizMsgCrypt error-code table (e.g. illegal aeskey length, signature verification failure)
  4. Ensure timestamp and nonce passed to EncryptResponse are the same values received in the callback request

Example fix

// before
var crypt = EncryptResponse(token, aesKey32CharWrong, corpId, ts, nonce, reply);
// after
string aesKey = config.EncodingAESKey.Trim(); // exact 43-char key from console
var crypt = EncryptResponse(token, aesKey, corpId, ts, nonce, reply);
Defensive patterns

Strategy: try-catch

Validate before calling

bool aesKeyOk = !string.IsNullOrWhiteSpace(aesKey) && aesKey.Trim().Length == 43;
if (!aesKeyOk) throw new InvalidOperationException("EncodingAESKey must be the 43-char console value");

Try / catch

try { var enc = OpenHardwareCallbackHandler.EncryptResponse(token, aesKey, receiveId, ts, nonce, reply); }
catch (OpenHardwareCallbackCryptException ex) { logger.LogError(ex, "Encrypt failed, code {Code}", ex.ErrorCode); return StatusCode(500); }

Prevention

When it happens

Trigger: Calling EncryptResponse with an encodingAesKey that does not match the 43-char Base64 key configured in the WeChat Work OpenHardware console, a token/receiveId (CorpId) mismatch, or malformed timestamp/nonce — any condition where WXBizMsgCrypt.EncryptJsonMsg returns an error code != 0.

Common situations: Copy-pasting the EncodingAESKey with extra whitespace or missing characters; using the callback token/aesKey of a different app; receiveId not matching the corpId configured on the WeChat side; rotating keys in the console without redeploying.

Related errors


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

Appendix: source

Thrown at src/Senparc.Weixin.Work/Senparc.Weixin.Work/AdvancedAPIs/OpenHardware/OpenHardwareCallbackHandler.cs:203

        /// <exception cref="OpenHardwareCallbackCryptException">加密或生成签名失败时抛出。</exception>
        public static OpenHardwareEncryptedCallbackReply EncryptResponse(
            string token, string encodingAesKey, string receiveId,
            string timestamp, string nonce, string plaintext)
        {
            EnsureNotEmpty(token, nameof(token));
            EnsureNotEmpty(encodingAesKey, nameof(encodingAesKey));
            EnsureNotEmpty(receiveId, nameof(receiveId));
            EnsureNotEmpty(timestamp, nameof(timestamp));
            EnsureNotEmpty(nonce, nameof(nonce));
            EnsureNotEmpty(plaintext, nameof(plaintext));

            var crypt = new WXBizMsgCrypt(token, encodingAesKey, receiveId);
            BotEncryptedReply encryptedReply = null;
            var errorCode = crypt.EncryptJsonMsg(plaintext, timestamp, nonce,
                ref encryptedReply);
            if (errorCode != 0)
            {
                throw new OpenHardwareCallbackCryptException(errorCode);
            }

            return new OpenHardwareEncryptedCallbackReply
            {
                encrypt = encryptedReply.encrypt,
                msgsignature = encryptedReply.msgsignature,
                timestamp = timestamp,
                nonce = encryptedReply.nonce
            };
        }

        private static TMessage Deserialize<TMessage>(string plaintext)
            where TMessage : OpenHardwareCallbackMessageBase
            => JsonConvert.DeserializeObject<TMessage>(plaintext);

        private static void EnsureNotEmpty(string value, string parameterName)
        {
            if (string.IsNullOrWhiteSpace(value))

View on GitHub (pinned to be573f6f94)