PHP中使用服务账号调用Google Calendar API遇权限问题
解决PHP服务账号读写个人Google日历的问题
问题原因分析
用个人邮箱作为
CALENDAR_ID时报错unauthorized_client:- 普通个人Google账号不支持域范围委派,
setSubject()方法是Google Workspace(原G Suite)用户专属功能,用于模拟域内用户身份,个人账号调用该方法会直接导致授权失败。 - 服务账号未被授权访问你的个人日历,即便和个人账号同属一个Google账号,也需要手动为服务账号分配日历共享权限。
- 普通个人Google账号不支持域范围委派,
用服务账号邮箱作为
CALENDAR_ID返回空:- 服务账号拥有独立的空白日历,你未在该日历中创建任何事件,因此返回空列表是正常现象,这并非你需要操作的个人日历。
具体解决步骤
1. 给个人日历共享权限给服务账号
- 打开Google日历网页版,找到目标日历(默认日历对应你的个人邮箱),点击日历名称右侧的「⋮」→「设置和共享」。
- 在「共享特定人员」区域点击「添加人员」,输入服务账号的完整邮箱(如
ss-calender@XXXXXXXXXX.iam.gserviceaccount.com)。 - 权限选择「更改和管理事件」(仅需读取权限可选择「查看所有事件」),点击「发送」完成共享。
2. 修正代码
移除错误的setSubject()调用,同时补全未定义的$start变量:
require_once __DIR__ . '/vendor/autoload.php'; define('CALENDAR_ID', '你的个人谷歌邮箱'); define('CREDENTIALS_PATH', 'service-account.json'); // 服务账号密钥文件路径 define('SCOPES', Google_Service_Calendar::CALENDAR); $googleClient = new Google_Client(); $googleClient->setApplicationName("Google Calendar PHP API"); $googleClient->setAuthConfig(CREDENTIALS_PATH); $googleClient->setScopes([SCOPES]); // 移除setSubject(),普通个人账号不支持域范围委派 $calendarService = new Google_Service_Calendar($googleClient); // 获取事件 $optParams = [ 'maxResults' => 10, 'orderBy' => 'startTime', 'singleEvents' => TRUE, 'timeMin' => date(DATE_RFC3339) ]; $events = $calendarService->events->listEvents(CALENDAR_ID, $optParams)->getItems(); foreach ($events as $event) { // 获取事件开始时间,区分全天事件和定时事件 $start = $event->getStart()->getDateTime() ?: $event->getStart()->getDate(); print_r($event->getSummary() . " " . $start . "\n"); }
3. 验证权限
共享完成后等待1-2分钟让权限生效,再运行代码即可正常读取个人日历事件。若需创建/修改事件,直接调用$calendarService->events->insert()或update()方法即可,权限已通过共享授予。
内容的提问来源于stack exchange,提问作者Yogesh Saroya
相关产品推荐
相关产品推荐

