Как создать запись в календаре Google без пользователя?

Недавно я решил предоставить пользователям на своем сайте следующую функциональность: онлайн-бронирование временных интервалов в календарях моих сотрудников. У всех сотрудников есть аккаунты Google, связанные с нашим доменом в Google Apps (бесплатная версия). Пользователи делают бронирование в каком-либо интерфейсе (например, не напрямую в календарях сотрудников Google), затем запрос обрабатывается на нашем PHP-сервере, и, если он правильный, сервер должен иметь возможность создавать новую запись календаря в выбранном календаре Google сотрудника. Примечание - ни пользователь, ни сотрудник не должны запрашивать аутентификацию при бронировании.

Я отсканировал API и форумы Google Calendar v3 и до сих пор не получил ни четкого ответа, ни кратких примеров - возможен ли такой сценарий с календарем Google? Может ли кто-нибудь помочь мне ответить на вопрос (и, если возможно, поделиться ссылкой с соответствующим примером)?

1 ответ

Решение

Вы знакомы с добавлением события с аутентификацией? Как я ответил здесь.
И как в коде ниже. Если вы... вы можете перейти на следующий уровень;)

(Вы можете скачать Php-клиент Google Api на этой странице. На этой странице есть учебник. Он предназначен для Google+, но принцип тот же)

В первый раз вам всегда понадобится аутентификация. Обойти это невозможно. В приведенном ниже примере вы получите token обратно после аутентификации, которая включает access_token и refresh_token. Access_token действителен только в течение 3600 секунд и используется для прямого доступа. По истечении срока действия access_token вы получаете ошибку 401 и можете использовать refresh_token (вместе с client_id, client_secret и правильным grant_type), чтобы запросить новый access_token.

Вы можете найти дополнительную информацию на этой странице (внизу "Использование маркера обновления"). Существуют некоторые ограничения по количеству запросов, упомянутые на этой странице внизу.


Это тестовый код, который я сделал в последний раз, когда помогал кому-то с этим. Это только показывает получение аутентификации и сохранение token в печенье. Он не запрашивает новый access_token после истечения срока его действия.

Но, как я уже сказал, вам нужно хранить token (в базе данных?) и когда вы получаете 401, вам нужно запросить новый access_token с client_id, client_secret, правильный grant_type и refresh_token. Для этого не требуется (повторная) аутентификация.

<?php
error_reporting(E_ALL);
require_once 'google-api-php-client/src/Google_Client.php';
require_once 'google-api-php-client/src/contrib/Google_CalendarService.php';
session_start();

if ((isset($_SESSION)) && (!empty($_SESSION))) {
   echo "There are cookies<br>";
   echo "<pre>";
   print_r($_SESSION);
   echo "</pre>";
}

$client = new Google_Client();
$client->setApplicationName("Google Calendar PHP Starter Application");
$client->setClientId('###');
$client->setClientSecret('###');
$client->setRedirectUri('http://###/add_calendar.php'); // <- registered web-page
//$client->setDeveloperKey('###'); // <- not always needed
$cal = new Google_CalendarService($client);

if (isset($_GET['logout'])) {
  echo "<br><br><font size=+2>Logging out</font>";
  unset($_SESSION['token']);
}

if (isset($_GET['code'])) {
  echo "<br>I got a code from Google = ".$_GET['code']; // You won't see this if redirected later
  $client->authenticate(); // $_GET['code']
  $_SESSION['token'] = $client->getAccessToken();
  header('Location: http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']);
  // not strictly necessary to redirect but cleaner for the url in address-bar
  echo "<br>I got the token = ".$_SESSION['token']; // <-- not needed to get here unless location uncommented
}

if (isset($_SESSION['token'])) {
  echo "<br>Getting access";
  $client->setAccessToken($_SESSION['token']);
}

if ($client->getAccessToken()){
  echo "<hr><font size=+1>I have access to your calendar</font>";
  $event = new Google_Event();
  $event->setSummary('=== I ADDED THIS ===');
  $event->setLocation('The Neighbourhood');
  $start = new Google_EventDateTime();
  $start->setDateTime('2013-11-29T10:00:00.000-05:00');
  $event->setStart($start);
  $end = new Google_EventDateTime();
  $end->setDateTime('2013-11-29T10:25:00.000-05:00');
  $event->setEnd($end);
  $createdEvent = $cal->events->insert('###', $event); // <- ### = email of calendar
  echo "<br><font size=+1>Event created</font>";

  echo "<hr><br><font size=+1>Already connected</font> (No need to login)";

} else {

  $authUrl = $client->createAuthUrl();
  print "<hr><br><font size=+2><a href='$authUrl'>Connect Me!</a></font>";

}

$url = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
echo "<br><br><font size=+2><a href=$url?logout>Logout</a></font>";

?>

Редактировать:

Если вы не хотите первоначальной аутентификации, у Google есть "Сервисные учетные записи", как вы указали.
(Я не знал об этом:)

Я выкопал несколько ссылок, где вы можете найти код для использования после того, как вы получили файл ключа.

Изменить события календаря Google из учетной записи службы Google: 403
Доступ к событиям календаря Google из учетной записи службы: {"error": "access_denied"}. Нет приложений Google
Учетная запись службы Google OAuth 2.0 - API календаря (клиент PHP)
https://groups.google.com/forum/
https://groups.google.com/forum/?fromgroups


Редактировать № 2: ДА, все заработало. (даже с моей бесплатной учетной записью Google;)

Вот рабочий код:

<?
error_reporting(E_ALL);
require_once 'google-api-php-client/src/Google_Client.php';
require_once 'google-api-php-client/src/contrib/Google_CalendarService.php';
session_start();

echo "Busy<br>";

const CLIENT_ID = 'xxxxxxxxxx.apps.googleusercontent.com';
const SERVICE_ACCOUNT_NAME = 'xxxxxxxxxxx@developer.gserviceaccount.com';
const KEY_FILE = 'xxxxxxxxxxxxxxxxxxx-privatekey.p12';
const CALENDAR_NAME = 'xxxxxxx@gmail.com';

$client = new Google_Client();
$client->setApplicationName("mycal");

if (isset($_SESSION['token'])) {
 $client->setAccessToken($_SESSION['token']);
}

$key = file_get_contents(KEY_FILE);
$client->setClientId(CLIENT_ID);
$client->setAssertionCredentials(new Google_AssertionCredentials(
  SERVICE_ACCOUNT_NAME,
  array('https://www.google.com/calendar/feeds/'),
  $key)
);

$client->setClientId(CLIENT_ID);
$service = new Google_CalendarService($client);

$event = new Google_Event();
$event->setSummary('=== I MADE THIS ===');
$event->setLocation('Somewhere else');
$start = new Google_EventDateTime();
$start->setDateTime('2013-11-30T10:00:00.000-02:00');
$event->setStart($start);
$end = new Google_EventDateTime();
$end->setDateTime('2013-11-30T10:25:00.000-02:00');
$event->setEnd($end);

$createdEvent = $service->events->insert(CALENDAR_NAME, $event);

echo "Done<br>";

?>

Мне нужно было сделать "новый проект" на https://cloud.google.com/console. Я не мог использовать существующий. После активации "Calendar API" и регистрации нового веб-приложения с сертификатом мне нужно было только поделиться своим календарем с кодом xxxx@developer.gserviceaccount.com и выше, который работал
(без аутентификации).

Редактирование #3: и теперь оно также работает в стандартном проекте Google+ API по умолчанию

Другие вопросы по тегам