Spotify error: " . h((string)$_GET['error']) . ""; exit; } $code = (string)($_GET['code'] ?? ''); $state = (string)($_GET['state'] ?? ''); if ($code === '' || $state === '') { echo "
Missing code/state.\n\nGET:\n"; print_r($_GET); echo ""; exit; } $expected = (string)($_SESSION['sp_state'] ?? ''); unset($_SESSION['sp_state']); if ($expected === '' || !hash_equals($expected, $state)) { echo "
State mismatch.\nExpected: ".h($expected)."\nGot: ".h($state).""; echo "
Use the SAME host everywhere (127.0.0.1 vs localhost) or cookies won’t match.
"; exit; } if (SPOTIFY_CLIENT_ID === '' || SPOTIFY_CLIENT_SECRET === '' || SPOTIFY_REDIRECT_URI === '') { http_response_code(500); echo "Missing Spotify config."; exit; } $ch = curl_init('https://accounts.spotify.com/api/token'); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_HTTPHEADER => [ 'Authorization: Basic ' . base64_encode(SPOTIFY_CLIENT_ID . ':' . SPOTIFY_CLIENT_SECRET), 'Content-Type: application/x-www-form-urlencoded', ], CURLOPT_POSTFIELDS => http_build_query([ 'grant_type' => 'authorization_code', 'code' => $code, 'redirect_uri' => SPOTIFY_REDIRECT_URI, ]), CURLOPT_TIMEOUT => 15, ]); $raw = curl_exec($ch); $http = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE); $err = curl_error($ch); curl_close($ch); $data = is_string($raw) ? json_decode($raw, true) : null; if ($raw === false || $http < 200 || $http >= 300 || !is_array($data)) { echo "
Token exchange failed.\nHTTP: {$http}\nCurl: ".h($err ?: 'none')."\nRaw:\n".h((string)$raw)."\n";
exit;
}
$access = (string)($data['access_token'] ?? '');
$refresh = (string)($data['refresh_token'] ?? '');
$expires = time() + (int)($data['expires_in'] ?? 3600);
if ($access === '') {
echo "No access_token returned.\n"; print_r($data); echo ""; exit; } pdo()->exec(" CREATE TABLE IF NOT EXISTS spotify_tokens ( id INT PRIMARY KEY, refresh_token TEXT NULL, access_token TEXT NULL, access_expires INT NULL, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; "); pdo()->exec("INSERT IGNORE INTO spotify_tokens (id) VALUES (1)"); if ($refresh !== '') { pdo()->prepare("UPDATE spotify_tokens SET refresh_token=?, access_token=?, access_expires=? WHERE id=1") ->execute([$refresh, $access, $expires]); flash_set('success', 'Spotify connected. Refresh token saved.'); } else { pdo()->prepare("UPDATE spotify_tokens SET access_token=?, access_expires=? WHERE id=1") ->execute([$access, $expires]); flash_set('warning', 'Connected, but no refresh token returned (already authorized before). Revoke access in Spotify account settings and try again.'); } header('Location: ' . url_path('/public/admin/dashboard.php')); exit;