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
- 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
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
- 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
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
- 未获取到用于安全探测的微信支付公钥或平台证书。
- 参数不能为空。
- ArgumentNullException (request is null)
- 预签名请求必须同时提供 nonce_str 和 ts。
- Section is not found.
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)