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

已完成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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 10:43:14