You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP实现Discord OAuth2登录回调后无法获取token问题求助

Discord OAuth2登录问题修复方案

核心问题排查

  • apiRequest函数逻辑顺序错误:函数内初始化curl后多执行了一次无用的curl_exec,此时还未配置POST参数和请求头,导致请求Discord接口时参数缺失,无法正常获取token。
  • 缺少错误校验逻辑:获取token请求后没有判断接口返回是否合法,当Discord返回错误信息(如密钥不匹配、回调地址不一致)时,直接读取不存在的access_token属性会导致session赋值为空。
  • 代码顺序错误:未定义$user变量时就提前在script标签中输出该变量的属性,可能抛出PHP警告干扰header跳转逻辑。
  • 可选优化:Discord官方API域名已从discordapp.com迁移到discord.com,建议更新接口地址避免后续旧域名失效。

修复后的代码

<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
ini_set('max_execution_time', 300);
error_reporting(E_ALL);

define('OAUTH2_CLIENT_ID', 'XXXXXXXXXXXXXXXXXXXXXX'); // 替换为你的客户端ID
define('OAUTH2_CLIENT_SECRET', 'XXXXXXXXXXXXXXXXXXXXXX'); // 替换为你的客户端密钥

$authorizeURL = 'https://discord.com/api/oauth2/authorize';
$tokenURL = 'https://discord.com/api/oauth2/token';
$apiURLBase = 'https://discord.com/api/users/@me';

session_start();

// 登录逻辑
if(get('action') == 'login') {
  header('Location: https://discord.com/api/oauth2/authorize?client_id=873917693953191946&redirect_uri=http%3A%2F%2Fbouncerbot.go-atcode.com%2Fauth.php&response_type=code&scope=identify%20email%20connections%20guilds%20gdm.join%20guilds.join%20rpc%20rpc.notifications.read%20rpc.voice.read%20rpc.voice.write');
  die();
}

// 回调处理逻辑
if(get('code')) {
  $token = apiRequest($tokenURL, array(
    "grant_type" => "authorization_code",
    'client_id' => OAUTH2_CLIENT_ID,
    'client_secret' => OAUTH2_CLIENT_SECRET,
    'redirect_uri' => 'http://bouncerbot.go-atcode.com/auth.php',
    'code' => get('code')
  ));
  // 增加返回值判断
  if(isset($token->access_token)){
    $_SESSION['access_token'] = $token->access_token;
    $_SESSION['logout_token'] = $token->access_token;
  }
  header('Location: ' . $_SERVER['PHP_SELF']);
  die();
}

// 登录状态展示
if(session('access_token')) {
  $user = apiRequest($apiURLBase);
  // 把script标签移到这里,避免调用未定义变量
  echo '<script> console.log('.json_encode($user->username).')</script>';
  echo '<h3>Logged In</h3>';
  echo '<h4>Welcome, ' . $user->username . '</h4>';
  echo '<pre>';
  print_r($user);
  echo '</pre>';
} else {
  echo '<h3>Not logged in</h3>';
  echo '<p><a href="?action=login">Log In</a></p>';
}

// 登出逻辑
if(get('action') == 'logout') {
  $params = array(
    'access_token' => session('logout_token')
  );
  header('Location: https://discord.com/api/oauth2/token/revoke' . '?' . http_build_query($params));
  die();
}

// 修复后的apiRequest函数
function apiRequest($url, $post=FALSE, $headers=array()) {
  $ch = curl_init($url);
  curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);

  if($post) {
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post));
  }

  $headers[] = 'Accept: application/json';
  if(session('access_token')) {
    $headers[] = 'Authorization: Bearer ' . session('access_token');
  }
  curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

  $response = curl_exec($ch);
  // 增加curl错误判断
  if(curl_errno($ch)){
    error_log('CURL错误: ' . curl_error($ch));
    return null;
  }
  curl_close($ch);
  return json_decode($response);
}

function get($key, $default=NULL) {
  return array_key_exists($key, $_GET) ? $_GET[$key] : $default;
}

function session($key, $default=NULL) {
  return array_key_exists($key, $_SESSION) ? $_SESSION[$key] : $default;
}
?>

额外校验项

如果修复后仍有问题,请检查以下配置:

  1. Discord开发者后台中填写的回调地址必须和代码中redirect_uri完全一致,包括http/https协议、域名、路径、端口都不能有差异
  2. 确认使用的客户端ID和客户端密钥没有填错,没有多余的空格或特殊字符
  3. 确认服务器可以正常访问Discord的API接口,没有被防火墙拦截

内容的提问来源于stack exchange,提问作者Conta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 19:15:04