Files
aj-portfolio/public/admin/spotify_callback.php
2025-12-23 13:18:58 +02:00

97 lines
3.2 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
declare(strict_types=1);
require __DIR__ . '/../../includes/bootstrap.php';
require_admin_login();
function h(string $s): string { return htmlspecialchars($s, ENT_QUOTES, 'UTF-8'); }
if (!empty($_GET['error'])) {
echo "<pre>Spotify error: " . h((string)$_GET['error']) . "</pre>";
exit;
}
$code = (string)($_GET['code'] ?? '');
$state = (string)($_GET['state'] ?? '');
if ($code === '' || $state === '') {
echo "<pre>Missing code/state.\n\nGET:\n"; print_r($_GET); echo "</pre>";
exit;
}
$expected = (string)($_SESSION['sp_state'] ?? '');
unset($_SESSION['sp_state']);
if ($expected === '' || !hash_equals($expected, $state)) {
echo "<pre>State mismatch.\nExpected: ".h($expected)."\nGot: ".h($state)."</pre>";
echo "<p>Use the SAME host everywhere (127.0.0.1 vs localhost) or cookies wont match.</p>";
exit;
}
if (SPOTIFY_CLIENT_ID === '' || SPOTIFY_CLIENT_SECRET === '' || SPOTIFY_REDIRECT_URI === '') {
http_response_code(500);
echo "<pre>Missing Spotify config.</pre>";
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 "<pre>Token exchange failed.\nHTTP: {$http}\nCurl: ".h($err ?: 'none')."\nRaw:\n".h((string)$raw)."\n</pre>";
exit;
}
$access = (string)($data['access_token'] ?? '');
$refresh = (string)($data['refresh_token'] ?? '');
$expires = time() + (int)($data['expires_in'] ?? 3600);
if ($access === '') {
echo "<pre>No access_token returned.\n"; print_r($data); echo "</pre>";
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;