97 lines
3.2 KiB
PHP
97 lines
3.2 KiB
PHP
<?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 won’t 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;
|