Google Calendar Api Enigma Solved Successfully

Yes, you read it correct. It felt nothing less than an enigma to integrate Google Calendar Api (may be, for others, despite being simple). It was more troublesome as I didn’t find much material for the same. Also, I believe, the documentation available for Google Calendar could be improved, personal views though. This article is for the developers who might be going through some agony of integrating Google Calendar Api, which I can completely understand.

Use Case

I have a web application, where I need to schedule event and invite the same to some participants. Then, as a participant updates their rsvp, the application should record the same and notify (email) for the same to the creator of the calendar.

Following are the list of objectives:

1- Create an google calendar event.

2- Invite the participant for the event.
2.1 – The invite should send an email to the participants.

3 – For every response from invitees, it should notify the creator and record.

Now, Google Calendar Api can be integrated with any application in following three ways:
1- Api Key
2- OAuth
3- Service Account

API Key : First method is ruled out here, as event creation needs authentication. Api Key can be used to integrate application only to list or access public data. Event Creation Api can not be used here as an event can be created only on behalf of a google calendar account.

With Oauth authorization method, it asks for authorization from the user for scheduling an event. The catch here is that, a user might mot have a google account(a website email, like [email protected] / yahoo / etc). I wouldn’t want my user, to leave my application, to create a google account first, before they can schedule the event. That would be very user unfriendly.

Service Account: This method looked fine. You can set up a service account to create event. It would do the authorization with their credentials. Then, you can set up attendees in the api and set sendNotifications flag to switch on notifications for the event creation.
So I implemented this one first. Everything worked almost fine. An event gets created. Sends email to almost all participants. Yes, not all the participants were receiving email for the event creation. So, an attendee with gmail/yahoo/rediffmail email account were receiving email successfully, but I had some domains with zoho email server setup, which never received any email.

Agony Phase

Why wouldn’t zoho email receive calendar invite? Also I checked the recipients in the email which received email. The emails were clearly listed there, so, what I could make out of it is, an email is definitely being sent but not being received. Also, there shouldn’t be anything done to zoho, as I can fix my zoho email settings but not of my users.
Google Calendar Api
With some google searches, I found a comment mentioning, sendNotifcations flag of event creation google calendar api is not supported by Zoho. The worst part is that it was a dead conversation dated 2 years ago.

https://help.zoho.com/portal/zohocorp/community/topic/google-calendar-invite-notifications

Google Calendar Api

Then I wandered around for sometime, scratched head, (on the verge of baldness :D).

Hack Time

I, then, recalled the very first page of documentation for google calendar api and its example implementation.
https://developers.google.com/calendar/quickstart/php
https://github.com/gsuitedevs/php-samples/blob/master/calendar/quickstart/quickstart.php

In the above url, they have mentioned a php terminal implementation with OAuth method. For the first time, it asks user(you, the developer, in the example) to authorize the url given, and then after authorization, saves the authorization file(credentials.json) to the server(localhost here). For subsequent requests, it refreshes the same file for the authorizing user(you, the developer, in the example).

Now, what you can do, is save that(credentials.json) for a general account, with which you would want to create events. That’t it for the bottleneck of the OAuth method. Now when your user, attempts to create an event, it can authorize with your credentials.json file and create event on your account behalf. It wouldn’t need all the users to have google account. Also, with the OAuth method, all of the email accounts were receiving email including zoho(have not checked exhaustively all email servers).

Solution

1- Generate credentials.json following the third step here, https://developers.google.com/calendar/quickstart/php

2- Create Event


function getClient() {
try {
$client = new Google_Client();
$client->setApplicationName('calender');
$client->setScopes(Google_Service_Calendar::CALENDAR);
$client->setAuthConfig('client_secret.json');
$client->setAccessType('offline');
// Load previously authorized credentials from a file.
$credentialsPath = 'path/credentials.json';
if (file_exists($credentialsPath)) {
$accessToken = json_decode(file_get_contents($credentialsPath), true);
} else {}
$client->setAccessToken($accessToken);

// Refresh the token if it's expired.
if ($client->isAccessTokenExpired()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
file_put_contents($credentialsPath, json_encode($client->getAccessToken()));
}
return $client;
} catch(Exception $e) {
/*print_r($e->getMessage());*/
return false;
}
}


function calendar_invite($events=null) {
$event_detail = array();
if (is_null($events)) {
return false;
}
if (isset($events['summary'])) {
$events = array($events);
}
foreach ($events as $tmpevent) {
try {
$client = getClient();
if (!$client) {
continue;
}
$service = new Google_Service_Calendar($client);

$calendarId = '[email protected]';

$event = new Google_Service_Calendar_Event($tmpevent);

$event = $service->events->insert($calendarId, $event, array('sendNotifications' => true, 'maxAttendees' => 10, 'conferenceDataVersion' => 1));

$watch = new Google_Service_Calendar_Channel(array('type' => 'web_hook', 'id' => $event->id, 'token' => $calendarId, 'address' => 'https://54c99e89.ngrok.io/watchapi/calendar_update'));
$watch = $service->events->watch($calendarId, $watch);

array_push($event_detail, array(
'event_hash' => $event->id,
'calendar_hash' => $calendarId
)
);
} catch(Exception $e) {
// print_r($e->getMessage());
// print_r($e->getTraceAsString());
}
}
return $event_detail;
}

3- Create Watch Api for the watch event.
Now, as the rsvp updates for any attendee, you can record it.

Note:
1- Don’t create a new calendar for all events, as then the creator for the event would change, and you might receive email for the event updates.

2- For the watch events, only https urls are allowed. You can use ngrok to create https url for your localhost for the development purpose. The https restriction (may be), you can think of as google servers would make requests to the watch api you provide. And it could be the case that, those servers can be made to request to their own server(remember, localhost) instead of developers server.

3- All the best

Leave a Reply