Symfony环境下使用Google People API查看谷歌联系人时出现「Invalid token format」错误求助
我之前在使用Google People API时也遇到过一模一样的问题,结合你的代码片段,咱们一步步来排查:
首先,定位错误根源
这个错误几乎都是因为传递给setAccessToken()的内容不是Google API客户端期望的格式——它需要包含access_token、token_type等键的数组,或者合法的JSON字符串。咱们先从你的代码里找可能的问题:
1. 检查Session中存储的Token格式
你的代码直接把fetchAccessTokenWithAuthCode()返回的数组存进了Session,但PHP Session的序列化/反序列化偶尔会出问题(比如特殊字符干扰),导致取出来的内容不是完整的数组。
你可以在读取Session的地方加个调试代码,看看实际拿到的是什么:
if (!empty($_SESSION['upload_token'])) { var_dump($_SESSION['upload_token']); // 打印出来看看 exit; // ... 原代码 }
如果输出不是包含access_token、expires_in的数组,而是字符串、null或者残缺的数组,那就是存储/读取Session时出了问题。
2. 确认fetchAccessTokenWithAuthCode()的返回值
有时候授权码无效(比如重复使用、过期),这个方法会返回一个包含error键的错误数组,而不是有效Token。如果直接把这个错误数组存进Session,后续调用setAccessToken()就会触发格式错误。
针对性解决方案
方案1:改用JSON字符串存储Token
把数组转成JSON字符串存储可以避免Session序列化的问题,更稳定:
// 获取Token并存储的部分 if (isset($_GET['code'])) { $token = $client->fetchAccessTokenWithAuthCode($_GET['code']); // 先检查是否获取成功 if (isset($token['error'])) { die("授权失败:{$token['error']}"); } $client->setAccessToken($token); // 转成JSON字符串存Session $_SESSION['upload_token'] = json_encode($token); header('Location: ' . filter_var('http://localhost:8000/', FILTER_SANITIZE_URL)); exit; // 一定要加exit,防止后续代码执行 } // 读取Token的部分 if (!empty($_SESSION['upload_token'])) { $token = json_decode($_SESSION['upload_token'], true); // 检查JSON解析是否正常 if (json_last_error() !== JSON_ERROR_NONE) { unset($_SESSION['upload_token']); } else { $client->setAccessToken($token); // 优化过期处理:尝试用刷新Token续期,而不是直接清空 if ($client->isAccessTokenExpired()) { if (isset($token['refresh_token'])) { $newToken = $client->fetchAccessTokenWithRefreshToken($token['refresh_token']); $_SESSION['upload_token'] = json_encode($newToken); $client->setAccessToken($newToken); } else { unset($_SESSION['upload_token']); } } } } else { $authUrl = $client->createAuthUrl(); }
方案2:检查Google Client的初始化配置
确保你初始化Google_Client时,client_id、client_secret、redirect_uri和Google Cloud控制台里的配置完全一致——哪怕一个字符错了,都可能导致获取的Token无效,进而触发格式错误。
比如初始化代码应该类似:
$client = new Google_Client(); $client->setApplicationName('你的应用名称'); $client->setScopes(Google_Service_People::CONTACTS_READONLY); // 根据你的需求设置权限 $client->setAuthConfig('credentials.json'); // 或者手动设置client_id和client_secret $client->setAccessType('offline'); // 要获取refresh_token必须设置这个 $client->setPrompt('select_account consent');
最后验证
做完上面的修改后,先清空浏览器的Session(或者直接删除$_SESSION['upload_token']),重新走一遍授权流程,应该就能解决这个错误了。
内容的提问来源于stack exchange,提问作者Envyworen

