使用Google服务账号(Server-to-Server)获取日历事件列表失败
问题排查与修复方案
你的代码核心问题在于误用了服务账号自身的primary日历——服务账号的主日历默认是空的,而你实际要访问的是目标用户/共享日历的事件,所以才会返回无结果。以下是具体修复步骤:
1. 替换目标日历ID
把代码里的$calendarId = 'primary';替换为你要访问的目标日历ID:
- 个人日历:直接用目标用户的邮箱(比如
xxx@gmail.com) - 共享日历:在日历设置里找到的唯一ID(格式类似
abc123...@group.calendar.google.com)
2. 确认权限配置
再次确认服务账号邮箱(XXX@XXX.iam.gserviceaccount.com)已被添加到目标日历的权限列表中,权限级别至少设置为「查看所有事件」。
3. 清理冗余代码
服务端到服务端调用不需要会话支持,直接删除session_start();这行无用代码。
修改后的完整代码
require_once __DIR__.'/vendor/autoload.php'; putenv('GOOGLE_APPLICATION_CREDENTIALS=XXX.json'); $client = new Google\Client(); $client->useApplicationDefaultCredentials(); $client->addScope('https://www.googleapis.com/auth/calendar.events.readonly'); // 替换为你的目标日历ID $calendarId = 'xxx@gmail.com'; $optParams = array( 'maxResults' => 10, 'orderBy' => 'startTime', 'singleEvents' => TRUE, 'timeMin' => date('c'), ); $service = new Google_Service_Calendar($client); try { $results = $service->events->listEvents($calendarId, $optParams); if (count($results->getItems()) == 0) { print "No upcoming events found.\n"; } else { print "Upcoming events:\n"; foreach ($results->getItems() as $event) { $start = $event->start->dateTime; if (empty($start)) { $start = $event->start->date; } printf("%s (%s)\n", $event->getSummary(), $start); } } } catch (Exception $e) { // 捕获错误信息方便排查 print "Error fetching events: " . $e->getMessage() . "\n"; }
额外排查点
- 检查
date('c')的时区是否与目标日历事件的时区一致,时区偏差可能导致过滤掉未来事件 - 确认服务账号密钥文件(
XXX.json)路径正确,且PHP进程有读取权限 - 登录谷歌云控制台,确认Calendar API已启用且未触发调用限额
内容的提问来源于stack exchange,提问作者teo2600
相关产品推荐
相关产品推荐

