使用服务帐户插入 Google 日历条目
Posted
技术标签:
【中文标题】使用服务帐户插入 Google 日历条目【英文标题】:Inserting Google Calendar Entries with Service Account 【发布时间】:2014-11-21 17:34:52 【问题描述】:我正在尝试使用服务帐户在 Google 日历上创建条目。我真的很接近这一点,但最后一行是行不通的。当我让它运行时,我得到一个500 Internal Service Error
。否则,程序运行时不会出错,不惜一切代价。
Calendar.php
文件内容可以在here 中找到。我试图调用的 insert()
方法从该文件的第 1455 行开始。
<?php
function calendarize ($title, $desc, $ev_date, $cal_id)
session_start();
/************************************************
Make an API request authenticated with a service
account.
************************************************/
set_include_path( '../google-api-php-client/src/');
require_once 'Google/Client.php';
require_once 'Google/Service/Calendar.php';
// (not real keys)
$client_id = '843319906820-jarm3f5ctbtjj9b7lp5qdcqal54p1he6.apps.googleusercontent.com';
$service_account_name = '843319906820-jarm3f5ctbtjj7b7lp5qdcqal54p1he6@developer.gserviceaccount.com';
$key_file_location = '../google-api-php-client/calendar-249226a7a27a.p12';
// echo pageHeader("Service Account Access");
if (!strlen($service_account_name) || !strlen($key_file_location))
echo missingServiceAccountDetailsWarning();
$client = new Google_Client();
$client->setApplicationName("xxxx Add Google Calendar Entries");
if (isset($_SESSION['service_token']))
$client->setAccessToken($_SESSION['service_token']);
$key = file_get_contents($key_file_location);
$cred = new Google_Auth_AssertionCredentials(
$service_account_name,
array('https://www.googleapis.com/auth/calendar'),
$key
);
$client->setAssertionCredentials($cred);
if($client->getAuth()->isAccessTokenExpired())
$client->getAuth()->refreshTokenWithAssertion($cred);
$_SESSION['service_token'] = $client->getAccessToken();
// Prior to this, the code has mostly come from Google's example
// google-api-php-client / examples / service-account.php
// and relates to getting the access tokens.
// The rest of this is about setting up the calendar entry.
//Set the Event data
$event = new Google_Service_Calendar_Event();
$event->setSummary($title);
$event->setDescription($desc);
$start = new Google_Service_Calendar_EventDateTime();
$start->setDate($ev_date);
$event->setStart($start);
$end = new Google_Service_Calendar_EventDateTime();
$end->setDate($ev_date);
$event->setEnd($end);
$calendarService = new Google_Service_Calendar($client);
$calendarList = $calendarService->calendarList;
$events = $calendarService->events;
// if I leave this line, my code won't crash (but it won't do anything, either)
//echo "here"; die();
$events.insert($cal_id, $event, false);
?>
【问题讨论】:
你从哪里得到 $cal_id?服务帐户是否有权访问该日历? 是的。那是我尝试向其发布事件的特定 Google 日历的日历 ID。在那个日历上,我在“与特定人共享”中添加了 $client_id 值。 【参考方案1】:我想通了。由于我没有看到任何使用 API v3 的服务帐户的完整示例,因此我将发布我的完整解决方案以供参考。但是,除了实现代码之外,您还需要做一些事情:
1) 您需要转到Google Developer's console 并将您的帐户标记为“服务帐户”。这将使其与 Web 应用程序区分开来。重要的区别是在添加事件之前不会提示任何人登录他们的帐户,因为该帐户将属于您的应用程序,而不是最终用户。如需更多信息,请参阅此article,从第 5 页开始。
2) 您需要创建一个公钥/私钥对。在开发人员的控制台中,单击凭据。在您的服务帐户下,单击“生成新的 P12 密钥”。您需要将其存储在某个地方。该文件位置成为下面代码中的$key_file_location
变量字符串。
3) 同样从开发者控制台,您需要启用Calendar
API。在您的项目中,您会在左边看到APIs
。选择它并找到Calendar
API。单击它,接受服务条款,并验证它现在显示在Enabled APIs
下,状态为On
4) 在您要添加事件的 Google 日历中,在设置下点击日历设置,然后点击顶部的“共享此日历”。在“人员”字段的“与特定人员共享”下,粘贴服务帐户凭据中的电子邮件地址。将权限设置更改为“更改事件”。不要忘记保存更改。
然后,在某处实现此代码。
如果有什么令人困惑或遗漏的地方,请发表评论。祝你好运!
<?php
function calendarize ($title, $desc, $ev_date, $cal_id)
session_start();
/************************************************
Make an API request authenticated with a service
account.
************************************************/
set_include_path( '../google-api-php-client/src/');
require_once 'Google/Client.php';
require_once 'Google/Service/Calendar.php';
//obviously, insert your own credentials from the service account in the Google Developer's console
$client_id = '843319906820-xxxxxxxxxxxxxxxxxxxdcqal54p1he6.apps.googleusercontent.com';
$service_account_name = '843319906820-xxxxxxxxxxxxxxxxxxxdcqal54p1he6@developer.gserviceaccount.com';
$key_file_location = '../google-api-php-client/calendar-xxxxxxxxxxxx.p12';
if (!strlen($service_account_name) || !strlen($key_file_location))
echo missingServiceAccountDetailsWarning();
$client = new Google_Client();
$client->setApplicationName("Whatever the name of your app is");
if (isset($_SESSION['service_token']))
$client->setAccessToken($_SESSION['service_token']);
$key = file_get_contents($key_file_location);
$cred = new Google_Auth_AssertionCredentials(
$service_account_name,
array('https://www.googleapis.com/auth/calendar'),
$key
);
$client->setAssertionCredentials($cred);
if($client->getAuth()->isAccessTokenExpired())
$client->getAuth()->refreshTokenWithAssertion($cred);
$_SESSION['service_token'] = $client->getAccessToken();
$calendarService = new Google_Service_Calendar($client);
$calendarList = $calendarService->calendarList;
//Set the Event data
$event = new Google_Service_Calendar_Event();
$event->setSummary($title);
$event->setDescription($desc);
$start = new Google_Service_Calendar_EventDateTime();
$start->setDateTime($ev_date);
$event->setStart($start);
$end = new Google_Service_Calendar_EventDateTime();
$end->setDateTime($ev_date);
$event->setEnd($end);
$createdEvent = $calendarService->events->insert($cal_id, $event);
echo $createdEvent->getId();
?>
一些有用的资源:Github example for service accountsGoogle Developers Console for inserting events in API v3Using OAuth 2.0 to Access Google APIs
【讨论】:
帮助很大。谢谢! 这似乎适用于 google-api-client 库的 v1。对于现在阅读的人,如果您收到Fatal error: Class 'Google_Auth_AssertionCredentials' not found
,请务必阅读github.com/google/google-api-php-client/blob/master/…
如何获取服务账号的日历ID?【参考方案2】:
这是 Google API Client 2.0 的做法
按照 Alex 的回答 Go Google Developer's console 创建服务帐户,但在 JSON
中创建凭据关注Google API Client Upgrade Guide,由composer安装并包含在的方式
require_once 'vendor/autoload.php';
按照 Alex 的回答转到 Google 日历以使用服务帐户 ID 共享日历
xxxxx@yyyy.iam.gserviceaccount.com
参考。到下面的编码和最重要的之一是日历ID应该是日历创建者的电子邮件,但不是主要的
<?php
require_once __DIR__.'/vendor/autoload.php';
session_start();
$client = new Google_Client();
$application_creds = __DIR__.'/secret.json'; //the Service Account generated cred in JSON
$credentials_file = file_exists($application_creds) ? $application_creds : false;
define("APP_NAME","Google Calendar API PHP"); //whatever
$client->setAuthConfig($credentials_file);
$client->setApplicationName(APP_NAME);
$client->addScope(Google_Service_Calendar::CALENDAR);
$client->addScope(Google_Service_Calendar::CALENDAR_READONLY);
//Setting Complete
//Go Google Calendar to set "Share with ..." Created in Service Account (xxxxxxx@sustained-vine-198812.iam.gserviceaccount.com)
//Example of Use of API
$service = new Google_Service_Calendar($client);
$calendarId = 'xxxx@gmail.com'; //NOT primary!! , but the email of calendar creator that you want to view
$optParams = array(
'maxResults' => 10,
'orderBy' => 'startTime',
'singleEvents' => TRUE,
'timeMin' => date('c'),
);
$results = $service->events->listEvents($calendarId, $optParams);
if (count($results->getItems()) == 0)
print "No upcoming events found.\n";
else
echo "Upcoming events:";
echo "<hr>";
echo "<table>";
foreach ($results->getItems() as $event)
$start = $event->start->dateTime;
if (empty($start))
$start = $event->start->date;
echo "<tr>";
echo"<td>".$event->getSummary()."</td>";
echo"<td>".$start."</td>";
echo "</tr>";
echo "</table>";
【讨论】:
谢谢,但我有点困惑。这会写入谷歌日历的条目吗?我只看到它阅读事件。如果没有,我建议您在回答中说明这一点,以向那些阅读本文并期望它回答原始问题的人澄清。以上是关于使用服务帐户插入 Google 日历条目的主要内容,如果未能解决你的问题,请参考以下文章
从 Google 服务帐户编辑 Google 日历事件:403
Google OAuth 2.0 服务帐户 - 日历 API(PHP 客户端)