$state */ public static function encode(array $state): string { $payload = [ 'v' => self::VERSION, 'state' => $state, ]; $json = json_encode($payload, JSON_THROW_ON_ERROR); return self::base64UrlEncode($json); } /** * @return array|null */ public static function decode(string $token): ?array { $token = trim($token); if ($token === '') { return null; } $json = self::base64UrlDecode($token); if ($json === null) { return null; } try { $decoded = json_decode($json, true, flags: JSON_THROW_ON_ERROR); } catch (JsonException) { return null; } if (! is_array($decoded)) { return null; } $version = $decoded['v'] ?? null; $version = is_int($version) ? $version : (is_numeric($version) ? (int) $version : null); if ($version !== self::VERSION) { return null; } $state = $decoded['state'] ?? null; return is_array($state) ? $state : null; } private static function base64UrlEncode(string $value): string { return rtrim(strtr(base64_encode($value), '+/', '-_'), '='); } private static function base64UrlDecode(string $value): ?string { $padded = strtr($value, '-_', '+/'); $padding = strlen($padded) % 4; if ($padding !== 0) { $padded .= str_repeat('=', 4 - $padding); } $decoded = base64_decode($padded, true); return is_string($decoded) ? $decoded : null; } }