{"record":{"id":"de7f32bb211eadd1","repo":"JeffreySu/WeiXinMPSDK","slug":"openhardwarecallbackcryptexception-encrypt-failed","errorCode":null,"errorMessage":"OpenHardwareCallbackCryptException (encrypt failed, WXBizMsgCrypt error code)","messagePattern":"OpenHardwareCallbackCryptException \\(encrypt failed, WXBizMsgCrypt error code\\)","errorType":"error_code","errorClass":"OpenHardwareCallbackCryptException","httpStatus":null,"severity":"error","filePath":"src/Senparc.Weixin.Work/Senparc.Weixin.Work/AdvancedAPIs/OpenHardware/OpenHardwareCallbackHandler.cs","lineNumber":203,"sourceCode":"        /// <exception cref=\"OpenHardwareCallbackCryptException\">加密或生成签名失败时抛出。</exception>\n        public static OpenHardwareEncryptedCallbackReply EncryptResponse(\n            string token, string encodingAesKey, string receiveId,\n            string timestamp, string nonce, string plaintext)\n        {\n            EnsureNotEmpty(token, nameof(token));\n            EnsureNotEmpty(encodingAesKey, nameof(encodingAesKey));\n            EnsureNotEmpty(receiveId, nameof(receiveId));\n            EnsureNotEmpty(timestamp, nameof(timestamp));\n            EnsureNotEmpty(nonce, nameof(nonce));\n            EnsureNotEmpty(plaintext, nameof(plaintext));\n\n            var crypt = new WXBizMsgCrypt(token, encodingAesKey, receiveId);\n            BotEncryptedReply encryptedReply = null;\n            var errorCode = crypt.EncryptJsonMsg(plaintext, timestamp, nonce,\n                ref encryptedReply);\n            if (errorCode != 0)\n            {\n                throw new OpenHardwareCallbackCryptException(errorCode);\n            }\n\n            return new OpenHardwareEncryptedCallbackReply\n            {\n                encrypt = encryptedReply.encrypt,\n                msgsignature = encryptedReply.msgsignature,\n                timestamp = timestamp,\n                nonce = encryptedReply.nonce\n            };\n        }\n\n        private static TMessage Deserialize<TMessage>(string plaintext)\n            where TMessage : OpenHardwareCallbackMessageBase\n            => JsonConvert.DeserializeObject<TMessage>(plaintext);\n\n        private static void EnsureNotEmpty(string value, string parameterName)\n        {\n            if (string.IsNullOrWhiteSpace(value))","sourceCodeStart":185,"sourceCodeEnd":221,"githubUrl":"https://github.com/JeffreySu/WeiXinMPSDK/blob/be573f6f94bdbf718dd5f6cdecb137fbc7ff651e/src/Senparc.Weixin.Work/Senparc.Weixin.Work/AdvancedAPIs/OpenHardware/OpenHardwareCallbackHandler.cs#L185-L221","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Verify encodingAesKey is the exact 43-character EncodingAESKey from the WeChat Work console (no padding/whitespace)","Verify token and receiveId match the callback configuration in the WeChat Work OpenHardware settings","Read exception.ErrorCode and cross-check against the WXBizMsgCrypt error-code table (e.g. illegal aeskey length, signature verification failure)","Ensure timestamp and nonce passed to EncryptResponse are the same values received in the callback request"],"exampleFix":"// before\nvar crypt = EncryptResponse(token, aesKey32CharWrong, corpId, ts, nonce, reply);\n// after\nstring aesKey = config.EncodingAESKey.Trim(); // exact 43-char key from console\nvar crypt = EncryptResponse(token, aesKey, corpId, ts, nonce, reply);","handlingStrategy":"try-catch","validationCode":"bool aesKeyOk = !string.IsNullOrWhiteSpace(aesKey) && aesKey.Trim().Length == 43;\nif (!aesKeyOk) throw new InvalidOperationException(\"EncodingAESKey must be the 43-char console value\");","typeGuard":null,"tryCatchPattern":"try { var enc = OpenHardwareCallbackHandler.EncryptResponse(token, aesKey, receiveId, ts, nonce, reply); }\ncatch (OpenHardwareCallbackCryptException ex) { logger.LogError(ex, \"Encrypt failed, code {Code}\", ex.ErrorCode); return StatusCode(500); }","preventionTips":["Copy EncodingAESKey and Token directly from the WeChat Work console without trimming characters","Keep token/aesKey/receiveId in one config section so they rotate together","Log the WXBizMsgCrypt error code from the exception for diagnosis"],"tags":["encryption","signature","configuration","wechat-work"],"backgroundTag":"api-error-response","analyzedSha":"be573f6f94bdbf718dd5f6cdecb137fbc7ff651e","analyzedAt":"2026-09-12T10:01:50.733Z","contentChangedAt":"2026-09-12T10:01:50.733Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}