using service account to access google calendar but answer variables are empty - php

I have created a service account to access a certain google calendar. this service account user also got the permission in the calendar settings as is described in this blog: "allow my user to add meeting in my calendar with Google Calendar API with PHP without auth".
As I can see in Google Cloud Platform under APIs + Services -> Credentials in the Service Account section the created service account is used with all services (last 30 days) every time, when I fire this php script, but in the browser window I get no error, that there would be a problem with authentication but: Uncaught Error: Call to a member function getSummary() on null in line... of the php-script
Script and Settings in Google Cloud Platform are as described in the mentioned post.
Any idea what could be the problem? Has there anything changed with google calendar api since this post in 2019?
require '../google-api-php-client/vendor/autoload.php';
ini_set('display_errors', 1);
$client = new Google_Client();
$client->addScope("https://www.googleapis.com/auth/calendar");
$client->setAuthConfig(dirname(__FILE__).'/credentials/credentials.json');
$service = new Google_Service_Calendar($client);
$calendarList = $service->calendarList->listCalendarList();
while(true) {
foreach ($calendarList->getItems() as $calendarListEntry) {
echo $calendarListEntry->getSummary();
echo "\n------------------------------\n\n";
// get events
$events = $service->events->listEvents($calendarListEntry->id);
foreach ($events->getItems() as $event) {
echo "- " . $event->getSummary() . "\n";
echo "- " . $event->getStart()->getDateTime() . "\n\n";
}
}
$pageToken = $calendarList->getNextPageToken();
if ($pageToken) {
$optParams = array('pageToken' => $pageToken);
$calendarList = $service->calendarList->listCalendarList($optParams);
} else {
echo "break";
break;
}
}
echo "calendar summary: " . $calendarListEntry->getSummary();
echo "\ncalendar id: " . $calendarListEntry->getId();
echo "\n------------------------------\n\n";
Obviously the $calendarList and $calendarListEntry is empty....

The reason why function getSummary() cannot render any results (is null or empty) is because a new service account user has an empty calendarList. By giving permission in any other calendar to the service account user does not automatically insert this calender to the calendarList of the service account user.
So you first have to insert / create a calenderList for the service account:
$calendarListEntry = new Google_Service_Calendar_CalendarListEntry();
$calendarListEntry->setId("calendar_address_you_want_to_add");
$createdCalendarListEntry = $service->calendarList->insert($calendarListEntry);
echo $createdCalendarListEntry->getSummary();
When using the first script now you will get results of calendarEvents (as far as there are any coming events posted in the calendar) the getSummary() function and the getId() function.

Related

Google API Calendar with Cron

I am trying to access to a calendar created by my application via cron, and I get a calendar with the same name that the calendar the application creates, but the id is absolutely different... This is my code:
public function cronTest()
{
$this->g_client = new Google_Client();
$this->g_client->setApplicationName($this->config->item("APPLICATION_NAME"));
$service = $this->getCronService("CalendarTest-46bde015a16.p12");
$calendar = $this->getCalendar($service);
}
private function getCronService($file)
{
$key = file_get_contents(CREDENTIALS_PATH.$file);
$cred = new Google_Auth_AssertionCredentials($this->config->item("google_service_id"), SCOPES, $key);
$this->g_client->setAssertionCredentials($cred);
if($this->g_client->getAuth()->isAccessTokenExpired())
$this->g_client->getAuth()->refreshTokenWithAssertion($cred);
return new Google_Service_Calendar($this->g_client);
}
private function getCalendar($service)
{
$calendarList = $service->calendarList->listCalendarList();
echo "getCalendar<br>";
foreach ($calendarList->getItems() as $calendarListEntry)
{
echo $calendarListEntry->getSummary()." with id:".$calendarListEntry->getId()."<br>";
echo "<br>";
if($calendarListEntry->getSummary()=="Auto-Citas")
echo "found";
//return $calendarListEntry->getId();
}
die;
}
When I execute it from the command line (simulating the cron):
wget www.domain.com/prototipo/alien/cronTest
I get this:
Calendar
Auto-Citas with id:h0gefmo7vjqlr4lp0r2n93vk9c#group.calendar.google.com
found
But, the id of calendar created with this application doesn´t match with this id...
Before this attempt with ron, I had to learn how to use the API, in this way I needed to remove sometimes the same calendar. So what I do, was remove one more time the Auto-Citas on my calendar, and call the function on my app to create a new calendar with a different name, then I made again the request of the "simulated cron" (wget www.domain.com/prototipo/alien/cronTest) and the result is the same than before: only one calendar called Auto-Citas, but nothing about the new calendar.
The functionality is to create a module anti-absenteeism, sending an email or sms to the user two hours before the appointment(cita=appointment)
For this tasks I have to function more... but they aren´t important for the case:
$events = $this->getDates($service,$calendar,$min,$max);
$this->transformDates($events, $service, ",phone");
Ok... I find solution just here (the google official docs). I need to use the option of user_to_impersonate.
$client_email = '1234567890-a1b2c3d4e5f6g7h8i#developer.gserviceaccount.com';
$private_key = file_get_contents('MyProject.p12');
$scopes = implode(' ', array(Google_Service_Calendar::CALENDAR));
$user_to_impersonate = 'user#example.org';
$credentials = new Google_Auth_AssertionCredentials(
$client_email,
$scopes,
$private_key,
'notasecret', // Default P12 password
'http://oauth.net/grant_type/jwt/1.0/bearer', // Default grant type
$user_to_impersonate,
);

Google Analytics API V3 with PHP returns blank page

I'm trying to display some basic Google Analytics information about my website using the Google Analytics Reporting API and Oauth 2.0. I've been trying to make it work for hours, but in vain.
I've copied and edited the code from this topic. Everything should work correctly, but somehow when I view the page in my browser, I only see a blank page.
I have:
Created a Service Account in the Google API Console.
Enabled the Google Analytics API in the Google API Console.
Added the e-mail address of the service account to Google Analytics.
The code ('XXXX' means I've filtered out personal information):
<?php
require_once 'google-api/src/Google/Client.php';
require_once 'google-api/src/Google/Service/Analytics.php';
$keyfile = 'XXXX.p12';
// Initialise the Google Client object
$client = new Google_Client();
$client->setApplicationName('Application Name');
$client->setAssertionCredentials(
new Google_AssertionCredentials(
'XXXX#developer.gserviceaccount.com',
array('https://www.googleapis.com/auth/analytics.readonly'),
file_get_contents($keyfile)
)
);
// Get this from the Google Console, API Access page
$client->setClientId('XXXX.apps.googleusercontent.com');
$client->setAccessType('offline_access');
$analytics = 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 = 'XXXX';
$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 struggled with this for a very long time, any help would be greatly appreciated!

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>";
}

Google Calendar API v3 domain wide delegated service account on PHP

I've been hitting my head to the wall for a few hours now, and I've tried to search all over the internet without success. My problem is I can't get the domain-wide delegation to work using Google API PHP Client (downloaded from GitHub). I assume authentication is working, because I'm able to read a calendar if the calendar has been shared to the service account's email (xxx##developer.gserviceaccount.com).
I want to be able to read and write to all users calendars in our domain (Google Apps for Business) without having to share individual calendars to the service account. I'm able to read the calendars if I share my (or a somebody else's) calendar to the service account's email (xxx##developer.gserviceaccount.com).
This is what I've done:
I created a project in Developer Console.
I created a service account and downloaded the .p12 file.
I went to admin.google.com and added the newly created Client ID to Security --> Advanced settings --> Manage OAuth Client Access - and I added the newly created Client ID as the Cliend Name and added https://www.google.com/calendar/feeds/ as the Scope. After that I clicked "Authorize".
Downloaded the latest Google API PHP Client.
Modified the included example (service-account.php) to match what I wanted.
When I run the script, I get a "404 Not found".
After I share the calendar (via Gmail --> calendar) to the service account's email, it starts to work. <-- This is the step I don't want all users to do.
Here's the code:
<?php
session_start();
include_once "templates/base.php";
set_include_path("../src/" . PATH_SEPARATOR . get_include_path());
require_once 'Google/Client.php';
require_once 'Google/Service/Calendar.php';
$client_id = 'xxxx.apps.googleusercontent.com';
$service_account_name = 'xxxx#developer.gserviceaccount.com';
$key_file_location = '/home/LALALA/public_html/xxxx-privatekey.p12';
echo pageHeader("Service Account Access");
if ($client_id == '<CLIENT_ID>'
|| !strlen($service_account_name)
|| !strlen($key_file_location)) {
echo missingServiceAccountDetailsWarning();
}
$client = new Google_Client();
$client->setApplicationName("Calendar");
$client->setClientId($client_id);
$client->setClientSecret("notasecret");
//$bookService = new Google_Service_Books($client);
$service = new Google_Service_Calendar($client);
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();
$events = $service->events->listEvents('some.email#our.domain.com');
while(true) {
foreach ($events->getItems() as $event) {
echo $event->getSummary()."<br />";
}
$pageToken = $events->getNextPageToken();
if ($pageToken) {
$optParams = array('pageToken' => $pageToken);
$events = $service->events->listEvents('primary', $optParams);
} else {
break;
}
}
?>
So now I'm looking for some genius who could help me out with this. I'd be most grateful and even willing to make a small donation for someone who could get this to work.
Try this:
$cred = new Google_Auth_AssertionCredentials(
$service_account_name,,
array('https://www.googleapis.com/auth/calendar'),
$key,
'notasecret',
'http://oauth.net/grant_type/jwt/1.0/bearer',
'some.email#our.domain.com'
);
Tell Google who is the person you want to impersonate, and then you will be able to operate everything of google calendar for this user.

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.

Categories