w7corp/easywechat · error · InvalidArgumentException
Decrypt AES CBC error.
Error message
Decrypt AES CBC error.
What it means
Support\AesCbc::decrypt() returns false from openssl_decrypt (bad key, bad IV, or corrupted ciphertext) and throws InvalidArgumentException with openssl_error_string() or the fallback 'Decrypt AES CBC error.'. In EasyWeChat this helper backs MiniApp\Decryptor::decrypt(), which rewraps the failure as DecryptException('The given payload is invalid: ...') — the classic symptom of a wrong or expired WeChat session_key when decrypting wx.getUserProfile / phone-number payloads.
Source
Thrown at src/Kernel/Support/AesCbc.php:44
return base64_encode($ciphertext);
}
/**
* @throws InvalidArgumentException
*/
public static function decrypt(string $ciphertext, string $key, ?string $iv = null): string
{
$plaintext = openssl_decrypt(
base64_decode($ciphertext),
'aes-128-cbc',
$key,
OPENSSL_RAW_DATA,
(string) $iv
);
if ($plaintext === false) {
throw new InvalidArgumentException(openssl_error_string() ?: 'Decrypt AES CBC error.');
}
return $plaintext;
}
}
View on GitHub (pinned to f0cf0a8b83)
Solutions
- Re-run the login flow (code2session) to obtain a fresh session_key, store it keyed by openid, then retry the decrypt
- Confirm iv and encryptedData come from the same client invocation (e.g. the same getPhoneNumber/getUserProfile result) as the session_key
- Check the wrapped message: DecryptException text includes the underlying reason from openssl_error_string()
Example fix
// before
$payload = Decryptor::decrypt($cachedSessionKey, $iv, $encryptedData); // DecryptException
// after
try {
$payload = Decryptor::decrypt($cachedSessionKey, $iv, $encryptedData);
} catch (DecryptException $e) {
// session_key likely rotated: force re-login on the mini program side
$session = $api->get('/sns/jscode2session', [...]);
$cachedSessionKey = $session['session_key'];
$payload = Decryptor::decrypt($cachedSessionKey, $iv, $encryptedData);
} Defensive patterns
Strategy: try-catch
Try / catch
use EasyWeChat\Kernel\Exceptions\DecryptException;
try {
$payload = \EasyWeChat\MiniApp\Decryptor::decrypt($sessionKey, $iv, $encryptedData);
} catch (DecryptException $e) {
// session_key rotated or mismatched: re-run code2session and retry once
$newSessionKey = $this->refreshSessionKey($openid); // your code2session wrapper
if ($newSessionKey !== null && $newSessionKey !== $sessionKey) {
$payload = \EasyWeChat\MiniApp\Decryptor::decrypt($newSessionKey, $iv, $encryptedData);
} else {
throw $e; // genuinely corrupt payload
}
} Prevention
- Store session_key keyed by openid with a short TTL and refresh it on every successful code2session
- Treat DecryptException as a signal to re-authenticate the mini-program user, not as a hard failure
- Ensure iv and encryptedData are forwarded from the same client API call that produced the session_key
When it happens
Trigger: Calling MiniApp Decryptor::decrypt($sessionKey, $iv, $encryptedData) where session_key is stale (user re-logged-in elsewhere, rotating the key) or does not match the code2session result used to fetch it; or the iv/encryptedData came from a different client call than the session_key.
Common situations: Cached session_key reused after the user logged in again (keys rotate per login), dev/prod appid mismatch, env or openid-keyed cache returning another user's key, passing base64 values undecoded.
Related errors
AI-assisted analysis of w7corp/easywechat@f0cf0a8b83 (2026-08-21).
Data as JSON: /api/errors/cd66ca1532f03750.
Report an issue: GitHub.