w7corp/easywechat · error · DecryptException
The given payload is invalid: %s
Error message
The given payload is invalid: %s
What it means
Any failure inside MiniApp\Decryptor::decrypt() — AesCbc::decrypt throwing (wrong sessionKey/iv or corrupted ciphertext fails the AES-128-CBC padding check) or json_decode not yielding an array — is re-thrown as this DecryptException with the underlying message appended. It is the standard failure when decrypting wx.getUserProfile/getPhoneNumber-style encryptedData, and in practice almost always means the sessionKey does not correspond to the encryptedData being decrypted.
Source
Thrown at src/MiniApp/Decryptor.php:38
*
* @throws DecryptException
*/
public static function decrypt(string $sessionKey, string $iv, string $ciphertext): array
{
try {
$decrypted = AesCbc::decrypt(
$ciphertext,
base64_decode($sessionKey, false),
base64_decode($iv, false)
);
$decrypted = json_decode($decrypted, true);
if (! $decrypted || ! is_array($decrypted)) {
throw new DecryptException('The given payload is invalid.');
}
} catch (Throwable $e) {
throw new DecryptException(sprintf('The given payload is invalid: %s', $e->getMessage()));
}
return $decrypted;
}
}
View on GitHub (pinned to f0cf0a8b83)
Solutions
- Re-run codeToSession with a fresh code and retry decryption with the new session_key.
- Persist session_key keyed by openid and refresh it on every login.
- Verify the appid matches the mini program that produced the data.
- Check iv base64-decodes to 16 bytes and encryptedData is the untouched client string.
Example fix
// before: decrypting with a session_key from an earlier login
$data = Decryptor::decrypt($oldSessionKey, $iv, $encryptedData);
// after: refresh via code2Session on failure and retry once
try {
$data = Decryptor::decrypt($sessionKey, $iv, $encryptedData);
} catch (DecryptException $e) {
$session = $app->getUtils()->codeToSession($code);
Cache::put("sk:{$session['openid']}", $session['session_key'], 300);
$data = Decryptor::decrypt($session['session_key'], $iv, $encryptedData);
} Defensive patterns
Strategy: retry
Validate before calling
if (strlen((string) base64_decode($sessionKey, true)) !== 24) { throw new InvalidArgumentException('session_key must base64-decode to 24 bytes'); }
if (strlen((string) base64_decode($iv, true)) !== 16) { throw new InvalidArgumentException('iv must base64-decode to 16 bytes'); } Try / catch
try { $data = \EasyWeChat\MiniApp\Decryptor::decrypt($sessionKey, $iv, $encryptedData); } catch (\EasyWeChat\Kernel\Exceptions\DecryptException $e) { // one controlled retry with a refreshed session_key $fresh = $app->getUtils()->codeToSession($code); return \EasyWeChat\MiniApp\Decryptor::decrypt($fresh['session_key'], $iv, $encryptedData); } Prevention
- Treat session_key as volatile: refresh it on every login
- Use one cache key per openid for session_key
- Have the client fetch encryptedData+iv together with a fresh login code
When it happens
Trigger: Using a stale session_key (the user logged in again, so code2Session issued a new one); iv from a different client call than encryptedData; appid of the issuing client different from the configured MiniApp; ciphertext/iv corrupted or URL-decoded so base64 padding was stripped.
Common situations: Calling code2Session twice and keeping the first session_key; session_key cached under a wrong or shared key across users; test data generated in dev tools used against production credentials; GET-parameter truncation of trailing '=' characters.
Related errors
- The given payload is invalid.
- Decrypt AES CBC error.
- Decrypt AES ECB failed.
- Decrypt failed
- Request ciphertext must not be empty.
AI-assisted analysis of w7corp/easywechat@f0cf0a8b83 (2026-08-21).
Data as JSON: /api/errors/a6dd367dfc705d72.
Report an issue: GitHub.