i need to add events to the google calendar with the api, on my localhost i made it work, however i cant remember where the token comes from, can you guys remind me this? the toke.json file
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
// If you've used composer to include the library
require 'vendor/autoload.php';
/*
if (php_sapi_name() != 'cli') {
throw new Exception('This application must be run on the command line.');
}
*/
/**
* Returns an authorized API client.
* #return Google_Client the authorized client object
*/
function getClient()
{
$client = new Google_Client();
$client->setApplicationName('Calendar API Test');
$client->setScopes( ['https://www.googleapis.com/auth/calendar'] );
// $client->setScopes(Google_Service_Calendar::CALENDAR_READONLY);
$client->setAuthConfig('credentials.json');
$client->setAccessType('offline');
$client->setPrompt('select_account consent');
// Load previously authorized token from a file, if it exists.
// and refresh tokens, and is created automatically when the authorization flow completes for the first time.
$tokenPath = 'token.json';
if (file_exists($tokenPath)) {
$accessToken = json_decode(file_get_contents($tokenPath), true);
$client->setAccessToken($accessToken);
}
// If there is no previous token or it's expired.
if ($client->isAccessTokenExpired()) {
// Refresh the token if possible, else fetch a new one.
if ($client->getRefreshToken()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
} else {
// Request authorization from the user.
$authUrl = $client->createAuthUrl();
printf("Open the following link in your browser:\n%s\n", $authUrl);
print 'Enter verification code: ';
// Check Param on redirected URL, for ?code=#############
// you have to copy only ?code= $_GET parms data and paste in console
$authCode = trim(fgets(STDIN)); // Get code after Authentication
// Exchange authorization code for an access token.
$accessToken = $client->fetchAccessTokenWithAuthCode($authCode);
$client->setAccessToken($accessToken);
// Check to see if there was an error.
if (array_key_exists('error', $accessToken)) {
throw new Exception(join(', ', $accessToken));
}
}
// Save the token to a file.
if (!file_exists(dirname($tokenPath))) {
mkdir(dirname($tokenPath), 0700, true);
}
file_put_contents($tokenPath, json_encode($client->getAccessToken()));
}
return $client;
}
$client = getClient();
$accessToken = $client->getAccessToken();
$service = new Google_Service_Calendar($client);
$summary = $_POST['summary'];
$description = $_POST['description'];
$fecha_inicio = $_POST['fecha_inicio'];
$hora_inicio = $_POST['hora_inicio'];
$fecha_fin = $_POST['fecha_fin'];
$h_inicio = explode(" ",$hora_inicio);
$hora = $h_inicio[0].":00";
$minutos = "00:30:00";
$secs = strtotime($minutos)-strtotime("00:00:00");
$result = date("H:i:s",strtotime($hora)+$secs);
$inicio = $fecha_inicio."T".$hora_inicio;
$fin = $fecha_fin."T".$result;
$attendee = $_POST['attendee'];
$_info = array(
'summary' => $summary,
'location' => 'address',
'description' => $description,
'start' => array(
'dateTime' => $inicio,
'timeZone' => 'America/Bogota',
),
'end' => array(
'dateTime' => $fin,
'timeZone' => 'America/Bogota',
),
'attendees' => array(
array('email' => $attendee)
),
'reminders' => array(
'useDefault' => FALSE,
'overrides' => array(
array('method' => 'email', 'minutes' => 24 * 60),
array('method' => 'popup', 'minutes' => 10),
),
),
);
//die(var_dump($_info));
$event = new Google_Service_Calendar_Event($_info);
$opts = array('sendNotifications' => true, 'conferenceDataVersion' => true); // send Notification immediately by Mail or Stop Hangout Call Link
$event = $service->events->insert( 'primary', $event, $opts );
die(var_dump($event));
printf('Event created: %s\n', $event->htmlLink);
?>
When your code runs the first time the user will be asked to consent to your application accessing their data. If the user consents then your code is storing the access token and refresh token in a file called token.json.
The next time the code runs it will check isAccessTokenExpired if it is it will use the refresh token stored in token.json to request a new access token and grant you access to the users data.
The way your code is written this will only be working for a single user as you are only storing to a single token.json file.
Related
I would like to share and add events to my own google calendar from my website.
So, I don't want the oauth prompt. Because users who visite my website can also add event to my calendar.
I think I did the right thing but I have this error : Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested
So, I don't sur if I need a paid workspace account to do that.
If not, I can't understand where I failed ?
here is my code :
$client = new Google\Client();
$client->setAuthConfig('./secret.json');
$client->setApplicationName('app name');
$client->addScope(Google\Service\Calendar::CALENDAR_EVENTS);
$client->setSubject('mail#gmail.com');
$client->setAccessType('offline');
$service = new Google\Service\Calendar($client);
$event = new Google\Service\Calendar\Event(array(
'summary' => 'summary',
'location' => 'street bla bla',
'description' => 'first event',
'start' => array(
'dateTime' => '2021-11-30T10:00:00.000-05:00',
'timeZone' => 'Europe/Brussels',
),
'end' => array(
'dateTime' => '2021-11-30T10:00:00.000-05:00',
'timeZone' => 'Europe/Brussels',
)
));
$service->events->insert('calendar_id', $event);
Thanks
The issue is that you are trying to set the subject or delegate to a normally Gmail email address $client->setSubject('mail#gmail.com');
Service accounts only work with Google workspace domain accounts and only after you have properly set up delegation to a user on the domain.
Im sorry to tell you that you will not be able to use a service account with your gmail email address.
What you could do is run the code from the Sample project which uses an installed application and stores the refresh token. This code will be single user. You will have to monitor it a little as refresh tokens can expire although its not that common once your project is set into prodctuion.
require __DIR__ . '/vendor/autoload.php';
if (php_sapi_name() != 'cli') {
throw new Exception('This application must be run on the command line.');
}
/**
* Returns an authorized API client.
* #return Google_Client the authorized client object
*/
function getClient()
{
$client = new Google_Client();
$client->setApplicationName('Google Calendar API PHP Quickstart');
$client->setScopes(Google_Service_Calendar::CALENDAR_READONLY);
$client->setAuthConfig('credentials.json');
$client->setAccessType('offline');
$client->setPrompt('select_account consent');
// Load previously authorized token from a file, if it exists.
// The file token.json stores the user's access and refresh tokens, and is
// created automatically when the authorization flow completes for the first
// time.
$tokenPath = 'token.json';
if (file_exists($tokenPath)) {
$accessToken = json_decode(file_get_contents($tokenPath), true);
$client->setAccessToken($accessToken);
}
// If there is no previous token or it's expired.
if ($client->isAccessTokenExpired()) {
// Refresh the token if possible, else fetch a new one.
if ($client->getRefreshToken()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
} else {
// Request authorization from the user.
$authUrl = $client->createAuthUrl();
printf("Open the following link in your browser:\n%s\n", $authUrl);
print 'Enter verification code: ';
$authCode = trim(fgets(STDIN));
// Exchange authorization code for an access token.
$accessToken = $client->fetchAccessTokenWithAuthCode($authCode);
$client->setAccessToken($accessToken);
// Check to see if there was an error.
if (array_key_exists('error', $accessToken)) {
throw new Exception(join(', ', $accessToken));
}
}
// Save the token to a file.
if (!file_exists(dirname($tokenPath))) {
mkdir(dirname($tokenPath), 0700, true);
}
file_put_contents($tokenPath, json_encode($client->getAccessToken()));
}
return $client;
}
// Get the API client and construct the service object.
$client = getClient();
$service = new Google_Service_Calendar($client);
// Print the next 10 events on the user's calendar.
$calendarId = 'primary';
$optParams = array(
'maxResults' => 10,
'orderBy' => 'startTime',
'singleEvents' => true,
'timeMin' => date('c'),
);
$results = $service->events->listEvents($calendarId, $optParams);
$events = $results->getItems();
if (empty($events)) {
print "No upcoming events found.\n";
} else {
print "Upcoming events:\n";
foreach ($events as $event) {
$start = $event->start->dateTime;
if (empty($start)) {
$start = $event->start->date;
}
printf("%s (%s)\n", $event->getSummary(), $start);
}
}
My goal is to retrieve events from google calendar in cron function, I need to do that without authorizing the requests every 1 hour since the access token expires.
From many related stack overflow questions I understood that in the beginning I gain an access token from authorizing the request, then the token get written in a token.json file. After the first access, every time I need to access the calendar the function fGetClient control if the token is expired or not, IF I PREVIOUSLY SET
$client->setAccessType('offline');
the function should refresh the token and i should access the calendar's event without authorizing any further request.
My problem is that i can't get the refreshed token, it expires in an hour and then i need to manually copy the link ,authorize the request and then copy and paste the verification code.
I leave the code below.
public function fGoogleCalendar($operazione=null){
//require_once $this->config["googlecalendardir"].'vendor/autoload.php';
// Get the API client and construct the service object.
$client = $this->fGCGetClient();
$service = new Google_Service_Calendar($client);
// Print the next 10 events on the user's calendar.
$calendarId = 'primary';
$optParams = array(
'maxResults' => 10,
'orderBy' => 'startTime',
'singleEvents' => true,
'timeMin' => date('c'),
);
$results = $service->events->listEvents($calendarId, $optParams);
$events = $results->getItems();
if (empty($events)) {
$aEventi="0 events found";
} else {
// "Upcoming events:\n";
foreach ($events as $event) {
$start = $event->start->dateTime;
if (empty($start)) {
$start = $event->start->date;
}
$end = $event->end->dateTime;
if (empty($end)) {
$end = $event->end->date;
}
$aEventi[]=array(
"nome" => $event->getSummary(),
"startdate" => $start,
"enddate" => $end
);
$start);
}
}
return $aEventi;
}
public function fGCGetClient(){
require_once $this->config["googlecalendardir"].'vendor/autoload.php';
$client = new Google_Client();
//die("ok");
$client->setApplicationName('Google Calendar API PHP Quickstart');
$client->setScopes(Google_Service_Calendar::CALENDAR_READONLY);
$client->setAuthConfig($this->config["googlecalendardir"].'credentials.json');
$client->setAccessType('offline');
//$client->setApprovalPrompt('auto');
$client->setPrompt('consent');
// Load previously authorized token from a file, if it exists.
// The file token.json stores the user's access and refresh tokens, and is
// created automatically when the authorization flow completes for the first
// time.
$tokenPath = $this->config["googlecalendardir"].'token.json';
if (file_exists($tokenPath)) {
$accessToken = json_decode(file_get_contents($tokenPath), true);
$client->setAccessToken($accessToken);
}
// If there is no previous token or it's expired.
//if (true) {
if ($client->isAccessTokenExpired()) {
// Refresh the token if possible, else fetch a new one.
if ($client->getRefreshToken()) {
//$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
$client->setAccessToken($client->getAccessToken());
} else {
// Request authorization from the user.
$authUrl = $client->createAuthUrl();
printf("Open the following link in your browser:\n%s\n", $authUrl);
print 'Enter verification code: ';
$authCode = trim(fgets(STDIN));
// Exchange authorization code for an access token.
$accessToken = $client->fetchAccessTokenWithAuthCode($authCode);
$client->setAccessToken($accessToken);
// Check to see if there was an error.
if (array_key_exists('error', $accessToken)) {
throw new Exception(join(', ', $accessToken));
}
}
// Save the token to a file.
if (!file_exists(dirname($tokenPath))) {
mkdir(dirname($tokenPath), 0700, true);
}
file_put_contents($tokenPath, json_encode($client->getAccessToken()));
}
return $client;
}
if you follow php quick start you will notice that it request offline access this means that the first time the user authorizes this application that the refresh token will be returned its then stored in $tokenPath
<?php
require __DIR__ . '/vendor/autoload.php';
if (php_sapi_name() != 'cli') {
throw new Exception('This application must be run on the command line.');
}
/**
* Returns an authorized API client.
* #return Google_Client the authorized client object
*/
function getClient()
{
$client = new Google_Client();
$client->setApplicationName('Google Calendar API PHP Quickstart');
$client->setScopes(Google_Service_Calendar::CALENDAR_READONLY);
$client->setAuthConfig('credentials.json');
$client->setAccessType('offline');
$client->setPrompt('select_account consent');
// Load previously authorized token from a file, if it exists.
// The file token.json stores the user's access and refresh tokens, and is
// created automatically when the authorization flow completes for the first
// time.
$tokenPath = 'token.json';
if (file_exists($tokenPath)) {
$accessToken = json_decode(file_get_contents($tokenPath), true);
$client->setAccessToken($accessToken);
}
// If there is no previous token or it's expired.
if ($client->isAccessTokenExpired()) {
// Refresh the token if possible, else fetch a new one.
if ($client->getRefreshToken()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
} else {
// Request authorization from the user.
$authUrl = $client->createAuthUrl();
printf("Open the following link in your browser:\n%s\n", $authUrl);
print 'Enter verification code: ';
$authCode = trim(fgets(STDIN));
// Exchange authorization code for an access token.
$accessToken = $client->fetchAccessTokenWithAuthCode($authCode);
$client->setAccessToken($accessToken);
// Check to see if there was an error.
if (array_key_exists('error', $accessToken)) {
throw new Exception(join(', ', $accessToken));
}
}
// Save the token to a file.
if (!file_exists(dirname($tokenPath))) {
mkdir(dirname($tokenPath), 0700, true);
}
file_put_contents($tokenPath, json_encode($client->getAccessToken()));
}
return $client;
}
// Get the API client and construct the service object.
$client = getClient();
$service = new Google_Service_Calendar($client);
// Print the next 10 events on the user's calendar.
$calendarId = 'primary';
$optParams = array(
'maxResults' => 10,
'orderBy' => 'startTime',
'singleEvents' => true,
'timeMin' => date('c'),
);
$results = $service->events->listEvents($calendarId, $optParams);
$events = $results->getItems();
if (empty($events)) {
print "No upcoming events found.\n";
} else {
print "Upcoming events:\n";
foreach ($events as $event) {
$start = $event->start->dateTime;
if (empty($start)) {
$start = $event->start->date;
}
printf("%s (%s)\n", $event->getSummary(), $start);
}
}
In your current directory delete this file token.json
It's where the token is saved if you delete the file your program won't find the token therefore create a new token.
$client->setAccessToken($_SESSION['access_token']);
$service = new Google_Service_Docs($client);
$title = $_SESSION['class'].' - '.date("Y-m-d");
$document = new Google_Service_Docs_Document(array(
'title' => $title
));
//everything works until here. For some reason, this line doesn't run. It doesn't even proceed.
$document = $service->documents->create($document);
//this line isn't even printed
print_r("success!");
$documentId = $document->documentId;
header('Location: https://docs.google.com/document/d/'.$documentId);
exit();
I've been scratching my head over this for hours. I have no idea why I can't create a new Google Doc. There's absolutely no examples of this online other than from Google and most of the code here is copied straight from them.
This is what I get when I print $document after assigning the title but before executing the service to create a new document.
Google_Service_Docs_Document Object
(
[bodyType:protected] => Google_Service_Docs_Body
[bodyDataType:protected] =>
[documentId] =>
[documentStyleType:protected] => Google_Service_Docs_DocumentStyle
[documentStyleDataType:protected] =>
[footersType:protected] => Google_Service_Docs_Footer
[footersDataType:protected] => map
[footnotesType:protected] => Google_Service_Docs_Footnote
[footnotesDataType:protected] => map
[headersType:protected] => Google_Service_Docs_Header
[headersDataType:protected] => map
[inlineObjectsType:protected] => Google_Service_Docs_InlineObject
[inlineObjectsDataType:protected] => map
[listsType:protected] => Google_Service_Docs_DocsList
[listsDataType:protected] => map
[namedRangesType:protected] => Google_Service_Docs_NamedRanges
[namedRangesDataType:protected] => map
[namedStylesType:protected] => Google_Service_Docs_NamedStyles
[namedStylesDataType:protected] =>
[positionedObjectsType:protected] => Google_Service_Docs_PositionedObject
[positionedObjectsDataType:protected] => map
[revisionId] =>
[suggestedDocumentStyleChangesType:protected] => Google_Service_Docs_SuggestedDocumentStyle
[suggestedDocumentStyleChangesDataType:protected] => map
[suggestedNamedStylesChangesType:protected] => Google_Service_Docs_SuggestedNamedStyles
[suggestedNamedStylesChangesDataType:protected] => map
[suggestionsViewMode] =>
[title] => Computer 9 - Charity - 2021-01-04
[internal_gapi_mappings:protected] => Array
(
)
[modelData:protected] => Array
(
)
[processed:protected] => Array
(
)
)
PHP Quickstart provides full tutorial on how to read Google Document using Google Docs API.
To create new document, use the example above and replace:
$documentId = '195j9eDD3ccgjQRttHhJPymLJUCOUjs-jmwTrekvdjFE';
$doc = $service->documents->get($documentId);
printf("The document title is: %s\n", $doc->getTitle());
with:
$title = 'My Document';
$document = new Google_Service_Docs_Document(array(
'title' => $title
));
$document = $service->documents->create($document);
printf("Created document with title: %s\n", $document->title);
Also, Make sure to change the SCOPE of your project to Google_Service_Docs::DOCUMENTS and before running your code, delete the Token.json to restart the process of verification and to create a new token with the scope you've specified.
Your code should look like these:
<?php
require __DIR__ . '/vendor/autoload.php';
/**
* Returns an authorized API client.
* #return Google_Client the authorized client object
*/
function getClient()
{
$client = new Google_Client();
$client->setApplicationName('Google Docs API PHP Quickstart');
$client->setScopes(Google_Service_Docs::DOCUMENTS);
$client->setAuthConfig('credentials.json');
$client->setAccessType('offline');
// Load previously authorized credentials from a file.
$credentialsPath = expandHomeDirectory('token.json');
if (file_exists($credentialsPath)) {
$accessToken = json_decode(file_get_contents($credentialsPath), true);
} else {
// Request authorization from the user.
$authUrl = $client->createAuthUrl();
printf("Open the following link in your browser:\n%s\n", $authUrl);
print 'Enter verification code: ';
$authCode = trim(fgets(STDIN));
// Exchange authorization code for an access token.
$accessToken = $client->fetchAccessTokenWithAuthCode($authCode);
// Store the credentials to disk.
if (!file_exists(dirname($credentialsPath))) {
mkdir(dirname($credentialsPath), 0700, true);
}
file_put_contents($credentialsPath, json_encode($accessToken));
printf("Credentials saved to %s\n", $credentialsPath);
}
$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;
}
/**
* Expands the home directory alias '~' to the full path.
* #param string $path the path to expand.
* #return string the expanded path.
*/
function expandHomeDirectory($path)
{
$homeDirectory = getenv('HOME');
if (empty($homeDirectory)) {
$homeDirectory = getenv('HOMEDRIVE') . getenv('HOMEPATH');
}
return str_replace('~', realpath($homeDirectory), $path);
}
// Get the API client and construct the service object.
$client = getClient();
$service = new Google_Service_Docs($client);
$title = 'My Document';
$document = new Google_Service_Docs_Document(array(
'title' => $title
));
$document = $service->documents->create($document);
printf("Created document with title: %s\n", $document->title);
Reference:
DocsScopes
Creating Document
I am trying to use Google's calendar API to create calendars and save them into my google calendar directly through my app, I would also like to create events but I cant seem to get this to work, there's no error whatsoever but still I don't see the calendar in my list.
$client = new \Google_Client();
$client->setApplicationName("GOOGLE CALENDAR");
$client->addScope(\Google_Service_Calendar::CALENDAR);
$client->setAuthConfig('pr-test-4ad4a00e3031.json');
$client->setAccessType("offline");
$service = new \Google_Service_Calendar($client);
$calenders = new \Google_Service_Calendar_Calendar();
$calenders->setDescription('ramzi');
$calenders->setSummary('test');
$service->calendars->insert($calenders);
print_r($calenders);
the JSON file has the credentials.
And this is the output I get when I print the variable $calenders
Google_Service_Calendar_Calendar Object
(
[conferencePropertiesType:protected] => Google_Service_Calendar_ConferenceProperties
[conferencePropertiesDataType:protected] =>
[description] => ramzi
[etag] =>
[id] =>
[kind] =>
[location] =>
[summary] => test
[timeZone] =>
[internal_gapi_mappings:protected] => Array
(
)
[modelData:protected] => Array
(
)
[processed:protected] => Array
(
)
)
This code will help you to achieve what you are trying to do(Create new calendars and events in them):
<?php
require __DIR__ . '/vendor/autoload.php';
function getClient(){
$client = new Google_Client();
$client->setApplicationName('Calendar API PHP');
$client->addScope(Google_Service_Calendar::CALENDAR);
$client->setAuthConfig('credentials.json');
$client->setAccessType('offline');
$client->setPrompt('select_account consent');
// Load previously authorized token from a file, if it exists.
// The file token.json stores the user's access and refresh tokens, and is
// created automatically when the authorization flow completes for the first
// time.
$tokenPath = 'token.json';
if (file_exists($tokenPath)) {
$accessToken = json_decode(file_get_contents($tokenPath), true);
$client->setAccessToken($accessToken);
}
// If there is no previous token or it's expired.
if ($client->isAccessTokenExpired()) {
// Refresh the token if possible, else fetch a new one.
if ($client->getRefreshToken()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
} else {
// Request authorization from the user.
$authUrl = $client->createAuthUrl();
printf("Open the following link in your browser:\n%s\n", $authUrl);
print 'Enter verification code: ';
$authCode = trim(fgets(STDIN));
// Exchange authorization code for an access token.
$accessToken = $client->fetchAccessTokenWithAuthCode($authCode);
$client->setAccessToken($accessToken);
// Check to see if there was an error.
if (array_key_exists('error', $accessToken)) {
throw new Exception(join(', ', $accessToken));
}
}
// Save the token to a file.
if (!file_exists(dirname($tokenPath))) {
mkdir(dirname($tokenPath), 0700, true);
}
file_put_contents($tokenPath, json_encode($client->getAccessToken()));
}
return $client;
}
function createCalendar($service){
$calendar = new Google_Service_Calendar_Calendar();
$calendar->setSummary('calendarSummary');
$calendar->setTimeZone('America/Los_Angeles');
try {
$createdCalendar = $service->calendars->insert($calendar);
echo $createdCalendar->getId();
return $createdCalendar->getId();
} catch(Exception $e) {
printf('An error occured creating the Calendar ' . $e->getMessage());
return null;
}
}
function insertMyevents($service, $calendarId){
$event = new Google_Service_Calendar_Event(array(
'summary' => 'Google I/O 2019',
'location' => '800 Howard St., San Francisco, CA 94103',
'description' => 'A chance to hear more about Google\'s developer products.',
'start' => array(
'dateTime' => '2019-11-13T09:00:00-07:00',
'timeZone' => 'America/Los_Angeles',
),
'end' => array(
'dateTime' => '2019-11-14T17:00:00-07:00',
'timeZone' => 'America/Los_Angeles',
)
));
try{
$event = $service->events->insert($calendarId, $event);
} catch(Exception $e) {
printf('An error occured inserting the Events ' . $e->getMessage());
}
}
if (php_sapi_name() != 'cli') {
throw new Exception('This application must be run on the command line.');
}
/**
* Returns an authorized API client.
* #return Google_Client the authorized client object
*/
// Get the API client and construct the service object.
$client = getClient();
$service = new Google_Service_Calendar($client);
// Creeate new calendar
$calendarId = createCalendar($service);
// Insert events into new Calendar if it was created succesfully
if($calendarId){
insertMyevents($service, $calendarId);
}
You were creating the $client in the wrong way without setting all the previous steps as it is said in the Quickstart. I also recommend you to check the next links, which bring some examples on how to use the Calendar API for PHP and the docs from all the methods you could use:
Calendars: insert
Events: insert
Calendar API - PHP
I'm trying to use Google Calendar API in PHP to access one central account. The idea is that other users can add events to this central account (they don't have to be logged in Google account) so I would like to have permanent access to the account.
Firstly, I've done Quickstart tutorial on Google's webpage. I logged in my account and everything was working for some time. Later, my access token expired and now, $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken()); throws LogicException: refresh token must be passed in or set as part of setAccessToken. I found out that $client->getRefreshToken() returns null.
Here you can see my whole code to get Google Client:
$client = new Google_Client();
$client->setApplicationName('Google Calendar API PHP Quickstart');
$client->setScopes(implode(' ', array(Google_Service_Calendar::CALENDAR) ) );
$client->setAuthConfig(__DIR__ . '/../config/client_secret.json');
$client->setAccessType('offline');
$credentialsPath = __DIR__ . '/../config/calendar-php-quickstart.json';
$accessToken = json_decode(file_get_contents($credentialsPath), true);
$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()));
}
Any idea what am I doing wrong?
Try using DalmTo's tutorial with regard to Calendar API and service accounts.
This is the refresh token implementation from her guide:
$client->setAssertionCredentials($cred);
if($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion($cred);
}
You can test the following code :
// Refresh the token if it's expired.
if ($client->isAccessTokenExpired()) {
// save refresh token to some variable
$refreshTokenSaved = $client->getRefreshToken();
// update access token
$client->fetchAccessTokenWithRefreshToken($refreshTokenSaved);
// pass access token to some variable
$accessTokenUpdated = $client->getAccessToken();
// append refresh token
$accessTokenUpdated['refresh_token'] = $refreshTokenSaved;
// save to file
file_put_contents($credentialsPath, json_encode($accessTokenUpdated));
}
I'll share my code that I finally got to work. I'm using a front end web app to get the initial authorization and then passing that code to a php web service to store in the dbase for later use.
<?php
require_once 'vendor/autoload.php';
/**
class to provide google calendar api functions.
returns information to mobile web app in json format
**/
class Calendar
{
private $client;
private $clientsecretgoogle = '{input secret here}';
private $clientIDgoogle = '{input client ID here}';
private $objDatabase;
private $queryParams;
private $params;
public function __construct($params)
{
$this->client = new Google_Client();
$this->client->setClientId($this->clientIDgoogle);
$this->client->setClientSecret($this->clientsecretgoogle);
$this->client->setAccessType('offline'); //this seems to be important for refresh tokens to update
$this->objDatabase = new Database();//connect to dbase
$this->params=$params;
}
public function getAuthorizationRefreshTokensGoogle($authCode, $userID)
{
/*
Get access_token and refresh token from returned auth code
I'm getting this on the front end and then storing in dbase table
Could have used the basic php library here but this worked so I stuck with it
*/
$oauth_url = 'https://www.googleapis.com/oauth2/v4/token?code=' . $authCode . '&client_secret=' . $this->clientsecretgoogle . '&client_id=' . $this->clientIDgoogle . '&redirect_uri=postmessage&grant_type=authorization_code';
//using curl
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $oauth_url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$return = curl_exec($ch);
curl_close($ch);
$return = json_decode($return);
// You can dump the vars to see the object
//var_dump($return);
//insert into table for later retrieval
$strSQL = "insert ignore into tbloauth(oauth_usr_id,oauth_vendor,oauth_token,oauth_refresh_token,oauth_token_expire)VALUES
(?,?,?,?,?)";
//check for existence of refresh token in response
//if not there then replace only the access_token
//if there then replace access, refresh
if(!$return->refresh_token){
$strSQL .= "ON DUPLICATE KEY UPDATE oauth_token=VALUES(oauth_token), oauth_token_expire=VALUES(oauth_token_expire)";
}else{
$strSQL .= "ON DUPLICATE KEY UPDATE oauth_token=VALUES(oauth_token),oauth_refresh_token=VALUES(oauth_refresh_token), oauth_token_expire=VALUES(oauth_token_expire)";
}
//translate expire time NOW + 3600
$expire = (time() + $return->expires_in);
if (!$return->refresh_token) {
$return->refresh_token = '';
}
$this->queryParams = array($userID, 'google', $return->access_token, $return->refresh_token, $expire);
$this->objDatabase->insertQuery($strSQL, $this->queryParams);
//you should now have a record now containing the access_token,refresh token, expire date
}
/*
List calendars
*/
function listCalendarsGoogle()
{
//1. Get tokens from database for the current user
$result=$this->getUserAccessToken($this->params['usr_id'],'google');
//2. Set access token with returned results
$this->client->setAccessToken(json_encode($result[0]));
//check for expired token and refresh if necessary
if($this->client->isAccessTokenExpired()) {
$this->client->refreshToken($result[0]['oauth_refresh_token']);
$access_token = $this->client->getAccessToken();
$strSQL="update tbloauth set oauth_token=? where oauth_vendor='google' and oauth_usr_id=? limit 1";
$this->queryParams=array($access_token,$this->params['usr_id']);
$this->objDatabase->updateQuery($strSQL,$this->queryParams);
}
//3.init calendar
$calendar = new Google_Service_Calendar($this->client);
//4. list calendars of primary
$calendarList = $calendar->calendarList->listCalendarList('primary');
return json_encode($calendarList);
}
/**
get access token for vendor(google in this case) using usr_id of user
which is passed to the class from the web app
*/
public function getUserAccessToken($usr_id,$vendor){
$strSQL="select tbloauth.*,oauth_token as access_token,oauth_refresh_token as refresh_token from tbloauth where oauth_usr_id=? and oauth_vendor=? ";
$this->queryParams=array($usr_id,$vendor);
//echo $this->objDatabase->parms($strSQL,$this->queryParams);
$aResult=$this->objDatabase->selectQuery($strSQL,$this->queryParams);
$aResult[0]['client_id']=$this->clientIDgoogle;
$aResult[0]['client_secret']=$this->clientsecretgoogle;
return $aResult;
}
/**
Insert Event into google using event info posted by web app
*/
public function insertEventGoogle(){
$result=$this->getUserAccessToken($this->params['usr_id'],'google');
$this->client->setAccessToken(json_encode($result[0]));
//check if expired
//if expired then fetch new token with current token
//update dbase with new token
//this would be cleaner separated into another method
//called before each list or insert calendar function
if($this->client->isAccessTokenExpired()) {
$this->client->refreshToken($result[0]['oauth_refresh_token']);
$access_token = $this->client->getAccessToken();
$strSQL="update tbloauth set oauth_token=? where oauth_vendor='google' and oauth_usr_id=? limit 1";
$this->queryParams=array($access_token,$this->params['usr_id']);
$this->objDatabase->updateQuery($strSQL,$this->queryParams);
}
//init calendar
$calendar = new Google_Service_Calendar($this->client);
//event info
$event = new Google_Service_Calendar_Event(array(
'summary' => $this->params['event_name'],
'location' => $this->params['event_location'],
'description' => $this->params['event_desc'],
'start' => array(
'dateTime' => date(DATE_ISO8601, strtotime($this->params['event_start_date'].' '.$this->params['event_start_time'])),
'timeZone' => 'America/New_York',
),
'end' => array(
'dateTime' => date(DATE_ISO8601, strtotime($this->params['event_end_date'].' '.$this->params['event_end_time'])),
'timeZone' => 'America/New_York',
),
'reminders' => array(
'useDefault' => FALSE,
'overrides' => array(
array('method' => 'email', 'minutes' => 24 * 60),
array('method' => 'popup', 'minutes' => 10),
),
),
));
//calendar id - default primary
$calendarId = 'primary';
//insert event
$event = $calendar->events->insert($calendarId, $event);
//return confirm msg
$msg=array('msg'=>'Event Created: '.$this->params['event_name']);
return json_encode($msg);
}
}
Hope that helps someone. The documentation was difficult to sort through.