binarywang/WxJava · error · WxErrorException

msg err ret {}

Error message

msg err ret {}

What it means

Thrown when the native WeChat Finance SDK's Finance.DecryptData() returns a non-zero code while decrypting chat-archive ciphertext. The SDK takes an encrypt_key (obtained by RSA-decrypting encrypt_random_key with your private key) and uses it to decrypt encrypt_chat_msg into plaintext. A non-zero return means the decryption step itself failed inside the C library.

Source

Thrown at weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpMsgAuditServiceImpl.java:213

  public String decryptChatData(long sdk, WxCpChatDatas.WxCpChatData chatData, Integer pkcs1) throws Exception {
    // 企业获取的会话内容,使用企业自行配置的消息加密公钥进行加密,企业可用自行保存的私钥解开会话内容数据。
    // msgAuditPriKey 会话存档私钥不能为空
    String priKey = cpService.getWxCpConfigStorage().getMsgAuditPriKey();
    if (StringUtils.isEmpty(priKey)) {
      throw new WxErrorException("请配置会话存档私钥【msgAuditPriKey】");
    }

    String decryptByPriKey = WxCpCryptUtil.decryptPriKey(chatData.getEncryptRandomKey(), priKey, pkcs1);
    // 每次使用DecryptData解密会话存档前需要调用NewSlice获取一个slice,在使用完slice中数据后,还需要调用FreeSlice释放。
    long msg = Finance.NewSlice();

    // 解密会话存档内容
    // sdk不会要求用户传入rsa私钥,保证用户会话存档数据只有自己能够解密。
    // 此处需要用户先用rsa私钥解密encrypt_random_key后,作为encrypt_key参数传入sdk来解密encrypt_chat_msg获取会话存档明文。
    int ret = Finance.DecryptData(sdk, decryptByPriKey, chatData.getEncryptChatMsg(), msg);
    if (ret != 0) {
      Finance.FreeSlice(msg);
      throw new WxErrorException("msg err ret " + ret);
    }

    // 明文
    String plainText = Finance.GetContentFromSlice(msg);
    Finance.FreeSlice(msg);
    return plainText;
  }

  @Override
  public String getChatPlainText(@NonNull long sdk, WxCpChatDatas.@NonNull WxCpChatData chatData,
                                 @NonNull Integer pkcs1) throws Exception {
    return this.decryptChatData(sdk, chatData, pkcs1);
  }

  @Override
  public void getMediaFile(@NonNull long sdk, @NonNull String sdkfileid, String proxy, String passwd,
                           @NonNull long timeout, @NonNull String targetFilePath) throws WxErrorException {
    /**

View on GitHub (pinned to 1c43293a3c)

Solutions

  1. Verify that msgAuditPriKey matches the RSA private key paired with the public key uploaded to the WeChat Work admin console under 会话存档 settings
  2. Ensure the pkcs1 parameter matches your key encoding (1 for PKCS#1, 8 for PKCS#8) and that the key string includes correct PEM boundaries
  3. Re-initialize the SDK handle via getOrInitThreadLocalSdk() if the access_token may have expired, then re-fetch chat records with the correct seq
  4. Check the native return code value: code 1 typically indicates wrong key/params, code 10001/10002 indicate SDK initialization or token issues
  5. Confirm the chatData object came from a fresh getChatRecords() call and its encryptRandomKey / encryptChatMsg fields are intact

Example fix

// before
String priKey = configStorage.getMsgAuditPriKey(); // possibly wrong or unformatted
String decryptKey = WxCpCryptUtil.decryptPriKey(chatData.getEncryptRandomKey(), priKey, pkcs1);
int ret = Finance.DecryptData(sdk, decryptKey, chatData.getEncryptChatMsg(), msg);

// after — validate key presence and format before calling DecryptData
String priKey = configStorage.getMsgAuditPriKey();
if (StringUtils.isBlank(priKey) || !priKey.contains("-----BEGIN")) {
  throw new WxErrorException("msgAuditPriKey 格式不正确,应为含 PEM 头的 RSA 私钥");
}
// ensure pkcs1 matches the actual key format
int ret = Finance.DecryptData(sdk, decryptKey, chatData.getEncryptChatMsg(), msg);
if (ret != 0) {
  log.error("DecryptData 失败 ret={}, 可能是私钥不匹配或 SDK token 过期", ret);
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate private key and SDK handle before decrypting
String priKey = configStorage.getMsgAuditPriKey();
if (StringUtils.isBlank(priKey)) {
  throw new IllegalStateException("msgAuditPriKey 未配置,无法解密会话存档");
}
if (!priKey.contains("PRIVATE KEY")) {
  throw new IllegalStateException("msgAuditPriKey 格式不正确,应为 PEM 格式 RSA 私钥");
}
if (sdk == 0) {
  throw new IllegalStateException("SDK 句柄无效,请重新初始化");
}

Try / catch

try {
  String plaintext = msgAuditService.decryptChatData(sdk, chatData, pkcs1);
} catch (WxErrorException e) {
  log.error("会话存档解密失败: {}", e.getMessage());
  // ret=1 typically means key mismatch; re-init SDK or verify RSA key pair
  if (e.getMessage().contains("ret 1")) {
    log.error("疑似 RSA 私钥与公钥不匹配,请检查企业微信管理后台配置");
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling decryptChatData() or getChatPlainText() / getDecryptData() after getChatRecords(). The Finance.DecryptData call returns non-zero when the RSA-derived encrypt_key is wrong, the private key (msgAuditPriKey) does not match the public key configured in the WeChat admin console, the SDK handle (sdk) is stale/uninitialized, or encrypt_chat_msg payload is truncated/corrupted.

Common situations: Wrong RSA key pair (used the public key instead of the private key, or a key from a different corp), key format mismatch (PKCS#1 vs PKCS#8), the msgAuditPriKey was set without the proper PEM header/footer, the SDK was initialized with Finance.NewSdk() but the access token expired and was not refreshed, or the chatData seq/limit returned stale data from a different session.

Related errors


AI-assisted analysis of binarywang/WxJava@1c43293a3c (2026-08-14). Data as JSON: /api/errors/b2c54af5d36175ae. Report an issue: GitHub.