已完成OAuth授权,异步拉取Google日历忙闲信息遇403错误求助
问题:调用Google日历FreeBusy API返回403权限错误
已完成用户OAuth授权并获取日历只读权限,但运行以下PHP代码拉取忙闲信息时,收到403错误提示「请求缺少有效的API密钥」。
运行代码
$client = new Client(); $client->setClientId(config('services.google.client_id')); $client->setClientSecret(config('services.google.client_secret')); $client->setRedirectUri(config('services.google.redirect')); $client->setScopes(['https://www.googleapis.com/auth/calendar.readonly']); $service = new \Google\Service\Calendar($client); $item = new \Google\Service\Calendar\FreeBusyRequestItem(); $item->setId('<calendar_id'); $freebusy_req = new \Google\Service\Calendar\FreeBusyRequest(); $freebusy_req->setTimeMin(date(DateTime::ATOM, strtotime('2022/01/28'))); $freebusy_req->setTimeMax(date(DateTime::ATOM, strtotime('2022/01/29'))); $freebusy_req->setTimeZone('Europe/Madrid'); $freebusy_req->setItems([$item]); $query = $service->freebusy ->query($freebusy_req);
错误信息
{ "error": { "code": 403, "message": "The request is missing a valid API key.", "errors": [ { "message": "The request is missing a valid API key.", "domain": "global", "reason": "forbidden" } ], "status": "PERMISSION_DENIED" } }
问题原因
代码仅配置了OAuth的客户端ID和密钥,但未加载用户授权生成的访问令牌(access_token)。Google API无法识别当前请求的授权身份,因此默认要求使用API密钥认证,进而抛出权限错误。
解决方法
1. 确保存储用户授权令牌
OAuth授权流程完成后,会返回access_token和refresh_token,需将这些值存储到数据库或其他持久化存储中。
2. 修改代码加载令牌并处理过期
在初始化Client后,添加令牌加载逻辑,同时处理令牌过期自动刷新:
$client = new Client(); $client->setClientId(config('services.google.client_id')); $client->setClientSecret(config('services.google.client_secret')); $client->setRedirectUri(config('services.google.redirect')); $client->setScopes(['https://www.googleapis.com/auth/calendar.readonly']); // 从存储中取出用户的access_token $client->setAccessToken($userStoredAccessToken); // 检查令牌是否过期,自动刷新并更新存储 if ($client->isAccessTokenExpired()) { $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken()); // 将新的access_token存回存储,供下次使用 saveNewAccessTokenToDatabase($client->getAccessToken()); } $service = new \Google\Service\Calendar($client); $item = new \Google\Service\Calendar\FreeBusyRequestItem(); $item->setId('<calendar_id>'); // 修正原代码未闭合的括号问题 $freebusy_req = new \Google\Service\Calendar\FreeBusyRequest(); $freebusy_req->setTimeMin(date(DateTime::ATOM, strtotime('2022/01/28'))); $freebusy_req->setTimeMax(date(DateTime::ATOM, strtotime('2022/01/29'))); $freebusy_req->setTimeZone('Europe/Madrid'); $freebusy_req->setItems([$item]); $query = $service->freebusy->query($freebusy_req);
额外注意事项
- 原代码中
$item->setId('<calendar_id')存在语法错误,需修正为<calendar_id> - 授权时需确保请求包含
access_type=offline参数,这样才能获取到refresh_token,用于后续自动刷新过期的access_token
内容的提问来源于stack exchange,提问作者bilogic
相关产品推荐
相关产品推荐

