How to watch Google Calendar Push notifications channel using PHP - php

I'm following these guides:
https://developers.google.com/calendar/quickstart/php
https://developers.google.com/calendar/v3/push
I'm using these libraries:
https://github.com/googleapis/google-api-php-client-services
https://github.com/googleapis/google-api-php-client
Here's my current code:
// Get the API client and construct the service object.
// this comes from the Quickstart example:
// https://developers.google.com/calendar/quickstart/php
$client = getClient();
$service = new Google_Service_Calendar($client);
// My code to start watching a channel:
$channel = new Google_Service_Calendar_Channel($client);
// where do I get this ID?
//$channel->setId('20fdedbf0-a845-11e3-1515e2-0800200c9a6689000');
$channel->setType("web_hook");
$channel->setToken('target=myApp-myCalendarChannelDest2');
$channel->setAddress("https://beta.example.com/incoming");
$timetoExpire = time()+360000;
$optParams = array(
'ttl' => $timetoExpire,
);
$channel->setParams($optParams);
$calendarId = 'developer#example.com';
$watchEvent = $service->events->watch($calendarId ,$channel);
Questions:
How do I start watching the channel for my calendar using those libraries?
Where do I get resourcePath for my calendar? (which is to be used in the above setId() method?

Related

Google Calendar How to fix "You need to have writer access to this calendar"?

I'm trying to access & write my dummy calendar make new functionality of the website but something prevents me from making changes to my dummy calendar.
So far when I try to used this code:
$event = $calendar->calendars->get(xxxxxx.com_dsjiub0krm61i5vu1mvee8rh9o#group.calendar.google.com);
The result is similar to the Googles Calendar's API explore.
My Calendar API
$calendarId2 = 'xxxxxx.com_dsjiub0krm61i5vu1mvee8rh9o#group.calendar.google.com';
$jobname = "Tesla";
$joblocation = "USA";
$jobdescription = "Interview with Elon Musk.";
$startofjob = "2019-03-29T10:00:00.000+00:00";
$endofjob = "2019-03-30T18:00:00.000+00:00";
try {
$client = GetGoogleClient();
$calendar = new \Google_Service_Calendar($client);
$event = new \Google_Service_Calendar_Event(array(
'summary' => $jobname,
'location' => $joblocation,
'description' => $jobdescription,
'end' => array(
'dateTime' => $endofjob,
'timeZone' => 'Asia/Manila',
),
'start' => array(
'dateTime' => $startofjob,
'timeZone' => 'Asia/Manila',
),
));
$event = $calendar->events->insert($calendarId2, $event);
}
catch(\Exception $e) {
return ["error" => $e->getMessage()];
}
The message would always say this "You need to have writer access to this calendar." even though I have shared the calendar to the Service Account with permission Make changes to events or Make changes and manage sharing
Additional info
function GetGoogleClient(){
$client = new Google_Client();
//$client->setAuthConfig($credentialsFile);
$client->addScope("https://www.googleapis.com/auth/drive", Google_Service_Sheets::SPREADSHEETS);
$client->addScope("https://www.googleapis.com/auth/calendar");
//$client->addScope("https://www.googleapis.com/auth/calendar.events"); //same error result event with or without
$client->setAuthConfig(CONST_GOOGLE_SERVICE_ACCOUNT_KEY);
$client->setSubject(CONST_GOOGLE_SERVICE_ACCOUNT_EMAIL);
$client->useApplicationDefaultCredentials();
return $client;
}
Check that the settings are correct in Google Admin Console. One reason that you would not be able to change the settings on an individual calendar is that the ability to make changes has been restricted on a domain wide basis.
If you are want to use a service account on GSuite organization you have to:
login with a Gsuite normal account (also not administrator)
create an API Project
enable calendar api
manage credentials and add a service account
download the json authorization file of the service account and copy the client_id in the json file
enable domain wide delegation for the service account in the console from the account that created the service account.
enable calendar API
login with a domain administrator account and go to Google Admin Console and go to Security -> API Controls -> Domain Wide Delegation
than add New API Client, insert the client_id at point 4 and the scope https://www.googleapis.com/auth/calendar (or one from: calendar.events, calendar.events.readonly, calendar.readonly, calendar.settings.readonly)
now that service account can impersonate anyone.
This is a sample code:
<?php
## composer require google/apiclient:^2.0
require __DIR__ . '/vendor/autoload.php';
/* the path of the auth file downloaded from google */
const AUTH_JSON_FILE = 'service-account-test-12345678.json';
/* the subject to impersonate */
const SUBJECT_TO_IMPERSONATE = 'acmeuser#mydomain.com';
/* take calendar id from calendar settings > embed calendar (the default calendar has the same as SUBJECT_TO_IMPERSONATE */
const CALENDAR_ID = "a_abcde123456fghijk789....#group.calendar.google.com";
/* date of the test event*/
const TEST_EVENT_DATE = '2021-01-26';
function getClient() {
$googleClient = new Google_Client();
$googleClient->setApplicationName("Anything you want");
$googleClient->setAuthConfig(AUTH_JSON_FILE);
$googleClient->setScopes([Google_Service_Calendar::CALENDAR]);
$googleClient->setSubject(SUBJECT_TO_IMPERSONATE);
return $googleClient;
}
// Get the API client and construct the service object.
$client = getClient();
$service = new Google_Service_Calendar($client);
/* Create a test event on 2021-01-26 */
$event = new Google_Service_Calendar_Event();
$event->setSummary("Test event title");
$event->setDescription("Test description.....");
$start = new Google_Service_Calendar_EventDateTime();
$start->setDate(TEST_EVENT_DATE);
$event->setStart($start);
$end = new Google_Service_Calendar_EventDateTime();
$end->setDate(TEST_EVENT_DATE);
$event->setEnd($end);
$createdEvent = $service->events->insert(CALENDAR_ID, $event);
echo $createdEvent->getId();
"You need to have writer access to this calendar."
You may have shared it with the service account but did you give it write access? or just read access? I think you should double check this its normally the cause of the issue. Remember this is only going to give it access to this one calendar.
Also i think you should check your scopes just use
$client->addScope("https://www.googleapis.com/auth/calendar");
I think they are clobbering each other. Take a step back make sure calendar works then add your drive stuff

How to send batch request with Google Indexing API

I'm following Google indexing API
And I want to send batch request with Google_Service_Indexing.
In PHP, please help me. How to do it.
In Google document, this is Google_Service_Books.
I tried with PHP like :
//set google client
$client = new Google_Client();
$client->setAuthConfig('my_key.json');
$client->addScope('https://www.googleapis.com/auth/indexing');
$client->setUseBatch(true);
//set batch
$batch = new Google_Http_Batch($client);
//set service
$service = new Google_Service_Indexing($client);
$postBody = new Google_Service_Indexing_UrlNotification();
$postBody->setType('URL_UPDATED');
$postBody->setUrl('https://my_job_detail');
$service->urlNotifications->publish($postBody);
$batch ->add($service);
$results = $batch->execute();
And I stuck in error :
Argument 1 passed to Google_Http_Batch::add() must implement interface Psr\Http\Message\RequestInterface, instance of Google_Service_Indexing_UrlNotification given, called in /Applications/MAMP/htdocs/Jukukoushi/src/Controller/ToppagesController.php on line 340
Request URL: /
I tried with PHP and completed.
//init google client
$client = new Google_Client();
$client->setAuthConfig('your_path_to_key.json');
$client->addScope('https://www.googleapis.com/auth/indexing');
$client->setUseBatch(true);
//init google batch and set root URL
$batch = new Google_Http_Batch($client,false,'https://indexing.googleapis.com');
//init service Notification to sent request
$postBody = new Google_Service_Indexing_UrlNotification();
$postBody->setType('URL_UPDATED');
$postBody->setUrl('https://your_job_detail');
//init service Indexing ( like updateJobPosting )
$service = new Google_Service_Indexing($client);
//create request
//$service->urlNotifications->createRequestUri('https://indexing.googleapis.com/batch');
$request_kame = $service->urlNotifications->publish($postBody);
//add request to batch
$batch ->add($request_kame);

Inserting Google Calendar Entries with Service Account

I'm trying to use a service account to create entries on a Google calendar. I'm really close on this, but the very last line won't work. I get a 500 Internal Service Error when I let this run. Otherwise, the program runs error free, for whatever that is worth.
The Calendar.php file contents can be found here. The insert() method that I am trying to call begins on line 1455 of that file.
<?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);
}
?>
I figured this out. Since I don't see any complete examples of using service accounts with API v3, I'm just going to post my complete solution for reference. There are a few of things that you need to do in addition to implementing the code, however:
1) You need to go to the Google Developer's console and mark your account as a 'service account'. This will differentiate it from a web application. The important difference is that nobody will be prompted to log in to their account before the events are added since the account will belong to your application, not an end user. For more information see this article, starting on page 5.
2) You need to create a public/private key pair. From the developer's console, click on Credentials. Under you service account, click on 'Generate new P12 key'. You'll need to store this somewhere. That file location becomes the $key_file_location variable string in the code below.
3) Also from the developer's console, you need to enable the Calendar API. From your project, on the left margin you'll see APIs. Select that and find the Calendar API. Click it, accept the terms of service, and verify that it is now displayed under Enabled APIs with a status of On
4) In Google Calendar that you want to add events to, under settings, click Calendar Settings then on 'Share this Calendar' at the top. Under 'Share with specific people' in the 'Person' field, paste in the email address from the service account credentials. Change the permission settings to 'Make changes to events'. Don't forget to save the change.
Then, implement this code somewhere.
Comment if something is confusing or omitted. Good luck!
<?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();
}
?>
Some helpful resources:
Github example for service accounts
Google Developers Console for inserting events in API v3
Using OAuth 2.0 to Access Google APIs
Here is the Google API Client 2.0 way to do
Follow Alex's Answer Go Google Developer's console to create Service Account, but create credential in JSON
Follow Google API Client Upgrade Guide, install by composer and include in the way of
require_once 'vendor/autoload.php';
Follow Alex's Answer to go to Google Calendar to share the calendar with Service Account ID
xxxxx#yyyy.iam.gserviceaccount.com
Take Ref. to below coding and the most important one is the calendar id should be the email of calendar creator, but not primary
<?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>";
}

Service Applications and Google Analytics API V3: Error 101 (net::ERR_CONNECTION_RESET)

I'm trying to get some info of my Google Analytics account using PHP. I already followed the steps for creating a Service Account in the Google Console API in this answer. I'm using the Google API Client for PHP.
This is the code I've got so far:
<?php
$path_to_src = 'src';
// These files are in /src, upload its contents to your web server
require_once $path_to_src . '/Google_Client.php';
require_once $path_to_src . '/contrib/Google_AnalyticsService.php';
$path_to_keyfile = '***'; //my private key
// Initialise the Google Client object
$client = new Google_Client();
// Your 'Product name'
$client->setApplicationName('My App Name');
$client->setAssertionCredentials(
new Google_AssertionCredentials(
'**', //gserviceaccount mail
array('https://www.googleapis.com/auth/analytics.readonly'),
file_get_contents($path_to_keyfile)
)
);
// Get this from the Google Console, API Access page
$client->setClientId('***'); // my cliente ID
$client->setAccessType('offline_access');
$analytics = new Google_AnalyticsService($client);
// create service and get data
$service = new Google_AnalyticsService($client);
// We have finished setting up the connection,
// now get some data and output the number of visits this week.
// Your analytics profile id. (Admin -> Profile Settings -> Profile ID)
$analytics_id = 'ga:****'; // my profile id
$lastWeek = date('Y-m-d', strtotime('-1 week'));
$today = date('Y-m-d');
try {
$results = $analytics->data_ga->get($analytics_id,
$lastWeek,
$today,'ga:visits');
echo '<b>Number of visits this week:</b> ';
echo $results['totalsForAllResults']['ga:visits'];
} catch(Exception $e) {
echo 'There was an error : - ' . $e->getMessage();
}
I've enabled the openssl extension in PHP:
When browsing to the location of the php script, I just get a almost forever loading and the following error:
I'm using PHP 5.4.7:
After debuging the Google API Client code, it looks like the script is breaking at this line:
if (!openssl_sign($data, $signature, $this->privateKey, "sha256"))
Anything below this line does not get called. Looks like the error happens in this line. Is there a incompatibility here, or something?
One thing for starters you should change:
You instantiate the AnalyticsService twice. Take out the one you're not using:
$service = new Google_AnalyticsService($client);
See if that helps your problem at all.

Adding a Google Calendar using apiClient

I'm finally able to get an Access Token, now I'm very confused as how to add a Calendar using only Google's provided apiClient.
$apiClient = SiteController::getApiClient();
$service = new apiCalendarService($apiClient);
$calendar = new Calendar();
$calendar->description = "What";
$service->calendars->insert($calendar);
This produces:
Error calling POST https://www.googleapis.com/calendar/v3/calendars?key=mykey: (400) Required
Is there some documentation/examples on adding a Calendar? There are a ton of examples, it seems like, for simply adding an Event.
I'm a little closer now, I get
apiServiceException
Error calling POST
https://www.googleapis.com/calendar/v3/users/me/calendarList?key=mykey: (404) Not Found
Using the boilerplate code they gave on the documentation
$calendarListEntry = new CalendarListEntry();
$calendarListEntry->setId("calendarId");
$createdCalendarListEntry = $service->calendarList->insert($calendarListEntry);
echo $createdCalendarListEntry->getSummary();
Inserting a new calendarEntry in google calendar API v3 returns a 404
How do I change my request URL from
https://www.googleapis.com/calendar/v3/users/me/calendarList?key=mykey
to
https://www.googleapis.com/calendar/v3/calendars
This worked:
// Create new calendar
$apiClient = SiteController::getApiClient();
$service = new apiCalendarService($apiClient);
$calendar = new Calendar();
$calendar->setSummary(Home::model()->count() . '-' . $model->name);
$createdCalendar = $service->calendars->insert($calendar);
You can reference Google Calendar API v1 Developers' Guide.

Categories