Working on a WP plugin. It's end purpose is to serve as an inspection calendar for home inspectors. We're working with a Google Calendar that is already loaded full of events.
I am authenticating via Oauth2 & a Service account. The plugin needs only to access the inspection company's data, no other private user data.
Here's the code:
// Set up identity ------------------------------------.
$client_email = "XXXXXX#XXXXXXXXXX.iam.gserviceaccount.com";
$private_key = file_get_contents( EC_INSPECT_CAL_INC . "/HE_Web_1.p12" );
$scope = [ "https://www.googleapis.com/auth/calendar","https://www.googleapis.com/auth/calendar.readonly","https://www.google.com/calendar/feeds" ];
$credentials = new \Google_Auth_AssertionCredentials(
$client_email,
$scope,
$private_key
);
// Build Config Obj ------------------------------------.
$config = new \Google_Config();
$config->setClassConfig('Google_Cache_File', array('directory' => EC_INSPECT_CAL_INC . '/tmp/cache'));
// Instantiate Client Connection ------------------------.
$client = new \Google_Client( $config );
$client->setAssertionCredentials( $credentials );
if( $client->getAuth()->isAccessTokenExpired() )
$client->getAuth()->refreshTokenWithAssertion();
$service = new \Google_Service_Calendar( $client );
$calendarList = $service->calendarList->listCalendarList();
while( true )
{
foreach( $calendarList->getItems() as $calendarListEntry )
{
// get events
$events = $service->events->listEvents( $calendarListEntry->id );
foreach( $events->getItems() as $event )
echo "-----".$event->getSummary() . "<br>";
}
$pageToken = $calendarList->getNextPageToken();
if( !$pageToken ) break;
$optParams = array('pageToken' => $pageToken);
$calendarList = $service->calendarList->listCalendarList($optParams);
}
}
If I var_dump the following:
var_dump( $service->calendarList->listCalendarList() );
It results in:
array(0) { }
My wife would like me to stop cursing in front of the dogs, but I can't seem to figure out what I'm overlooking. The calendar is loaded with content, and I (AFAIK) am authenticating ... So where's the goods??
Related
I am trying to upload files to google drive using PHP code. I can't get API response whatever it is. Incase of successful upload response should be 200 and different error codes. I just want to get receive error codes. Can anyone help me with it. Bellow I have pasted my complete code. I am using function like check if folder already exists and if it does place file in it otherwise just create new folder and place file in it. I am trying to make my code fail safe, if an error is encountered it saves the particular file and error code. right now it is just returning critical error and breaks AJAX.
function getClient(){
$authdata = array (
'web' =>
array (
'client_id' => get_option("csc_gdrive_clientid"),
'project_id' => get_option("csc_gdrive_projectid"),
'auth_uri' => "https://accounts.google.com/o/oauth2/auth",
'token_uri' => "https://oauth2.googleapis.com/token",
'auth_provider_x509_cert_url' => "https://www.googleapis.com/oauth2/v1/certs",
'client_secret' => get_option("csc_gdrive_clientsecret"),
),
);
include( plugin_dir_path( __FILE__ ) . '../vendor/autoload.php');
$client = new Google_Client();
$client->setApplicationName('Google Drive API PHP Quickstart');
$client->setScopes(Google_Service_Drive::DRIVE);
$client->setAuthConfig($authdata);
$client->setAccessType('offline');
// $client->setPrompt('select_account consent');
$client->setRedirectUri(get_option("csc_gdrive_redirecturi"));
// Load previously authorized token from a file, if it exists.
// The file key_config.txt stores the user's access and refresh tokens, and is
// created automatically when the authorization flow completes for the first
// time.
$tokenPath = plugin_dir_path( __FILE__ ) .'111key_config.txt';
if (!file_exists($tokenPath)) {
return;
} else{
$accessToken = json_decode(file_get_contents($tokenPath), true);
$client->setAccessToken($accessToken);
}
if (file_exists($tokenPath)){
// 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();
$authCode = get_option('csc_gdrive_token');
// 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));
}
}
}
}
return $client;
}enter code here
function create_folder( $folder_name, $parent_folder_id=null ){
//$folder_list = $this->check_folder_exists( $folder_name );
// if folder does not exists
//if( count( $folder_list ) == 0 ){
$client = $this->getClient();
if($client){
$service = new Google_Service_Drive( $client );
$folder = new Google_Service_Drive_DriveFile();
$folder->setName( $folder_name );
$folder->setMimeType('application/vnd.google-apps.folder');
if( !empty( $parent_folder_id ) ){
$folder->setParents( [ $parent_folder_id ] );
}
$result = $service->files->create( $folder );
$folder_id = null;
if( isset( $result['id'] ) && !empty( $result['id'] ) ){
$folder_id = $result['id'];
}
return $folder_id;
}
//}
//return $folder_list[0]['id'];
}
// This will check folders and sub folders by name
function check_folder_exists( $folder_name, $parent_folder_id=null){
$client = $this->getClient();
if($client){
$service = new Google_Service_Drive( $client );
if ($parent_folder_id){
$parameters['q'] = "mimeType='application/vnd.google-apps.folder' and name='$folder_name' and trashed=false and '$parent_folder_id' in parents";
} else {
$parameters['q'] = "mimeType='application/vnd.google-apps.folder' and name='$folder_name' and trashed=false";
}
$files = $service->files->listFiles($parameters);
$op = [];
foreach( $files as $k => $file ){
$op[] = $file;
}
return $op;
}
}
// This will insert file into drive and returns boolean values.
function insert_file_to_drive( $file_path, $file_name, $parent_file_id = null ){
$client = $this->getClient();
if($client){
$service = new Google_Service_Drive( $client );
$file = new Google_Service_Drive_DriveFile();
$file->setName( $file_name );
if( !empty( $parent_file_id ) ){
$file->setParents( [ $parent_file_id ] );
}
$result = $service->files->create(
$file,
array(
'data' => file_get_contents($file_path.'/'.$file_name),
'mimeType' => 'application/octet-stream',
)
);
$is_success = false;
if( isset( $result['name'] ) && !empty( $result['name'] ) ){
$is_success = true;
}
return $is_success;
}
}
Thanks for your time. I've found documentation on how to do this for public calendars, but I need it for a calendar which won't be shared with the world.
This is my code:
include( __DIR__ . '/composer/vendor/google/apiclient/autoload.php' );
$client_email = 'me#googletokenaccount.com';
$private_key = file_get_contents('/home/serverSecret.json');
$scopes = array( Google_Service_Drive::DRIVE_METADATA_READONLY );
$credentials = new Google_Auth_AssertionCredentials( $client_email, $scopes, $private_key );
$client = new Google_Client();
$client->setAssertionCredentials($credentials);
if ( $client->getAuth()->isAccessTokenExpired() )
{
$client->getAuth()->refreshTokenWithAssertion();
}
$client->setApplicationName("A Calendar");
$cal = new Google_Service_Calendar($client);
$calendarId = 'me#gmail.com';
$params = array( 'singleEvents' => true, 'orderBy' => 'startTime', 'timeMin' => date(DateTime::ATOM), 'maxResults' => 7 );
$events = $cal->events->listEvents($calendarId, $params);
$calTimeZone = $events->timeZone;
date_default_timezone_set($calTimeZone);
foreach ($events->getItems() as $event)
{
// Get the timings
$eventDateStr = $event->start->dateTime;
if(empty($eventDateStr)) { $eventDateStr = $event->start->date; } // Handle all-day events
$temp_timezone = $event->start->timeZone;
// Timezone override if applicable
if (!empty($temp_timezone)) { $timezone = new DateTimeZone($temp_timezone); }
else { $timezone = new DateTimeZone($calTimeZone); }
// Set up the timings
$eventdate = new DateTime($eventDateStr,$timezone);
$link = $event->htmlLink;
$TZlink = $link . "&ctz=" . $calTimeZone;
$newmonth = $eventdate->format("M");
$newday = $eventdate->format("j");
?>
<div class="event-container">
<div class="eventDate">
<span class="month"><?=$newmonth?></span>
<br />
<span class="day"><?=$newday?></span>
<span class="dayTrail"></span>
</div>
<div class="eventBody">
<?=$event->summary?>
</div>
</div>
<?php
}
?>
The above works when I use it with a public calendar using a client key but not when the calendar is made private. I need to know how to authenticate for private calendars.
You need the OAuth 2.0 service to access the private data:You might need to create a service account:
Typically, an application uses a service account when the application
uses Google APIs to work with its own data rather than a user's data.
For example, an application that uses Google Cloud Datastore for data
persistence would use a service account to authenticate its calls to
the Google Cloud Datastore API.
https://developers.google.com/identity/protocols/OAuth2ServiceAccount
I use Google API to retrieve analytics data and display them on my website. it worked fine for a month, but the last four days I get this error :
Error refreshing the OAuth2 token, message: '{ "error" : "invalid_grant" }'
Here is the code :
<?php
require_once ('src/Google/autoload.php');
$client = new Google_Client();
$client->setApplicationName( 'GAFetchData' );
$client->setAssertionCredentials(
new Google_Auth_AssertionCredentials(
// Google client ID email address
'xxxxx-xxxxxxxxxx#developer.gserviceaccount.com',
array('https://www.googleapis.com/auth/analytics.readonly'),
file_get_contents( $Path.'gapii/'.'GAFetchData-xxxxxxxx.p12' )
)
);
$client->setClientId( 'xxxxx-xxxxxxxxxx.apps.googleusercontent.com' );
$client->setAccessType( 'offline_access' );
$analytics = new Google_Service_Analytics( $client );
$analytics_id = 'ga:xxxxxx';
try {
$optParams = array();
$metrics = 'ga:pageviews';
$start_date = '7daysAgo';
$end_date = 'today';
$optParams['dimensions'] = 'ga:pagePath';
$optParams['filters'] = 'ga:pagePath!#=rech;';
$optParams['max-results'] = '10000';
$result = $analytics->data_ga->get( $analytics_id, $start_date, $end_date, $metrics, $optParams);
if( $result->getRows() ) { $items = $result->getRows(); }
}
catch(Exception $e) { echo $e->getMessage();}
?>
Issue solved !
It was caused by the server's clock, I just synchronise it with a NTP server using the following command (Ubuntu in my case) :
sudo ntpdate 3.pool.ntp.org
You will find a list of time servers from the
public NTP time server list
hope that helps !
I'm using Google API PHP client to add events to my calendar. ID is returned successfully after the insert & When I fetch that event using the ID it displays summary & everything correctly & for some reason , the event is showing up in my calendar
I'm using Service Account Credentials. Is there something to be enabled to get this working?
Here's my Code
session_start();
require dirname(__FILE__).'/google-api-php-client-master/autoload.php';
$client_id = '<client ID>';
$service_account_name = '<Service Account Name>';
$key_file_location = dirname(__FILE__).'/API-Project-96c2a9122085.p12';
if (!strlen($service_account_name) || !strlen($key_file_location)) {
echo missingServiceAccountDetailsWarning();
}
$client = new Google_Client();
$client->setApplicationName("Client_Library_Examples");
$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();
$event = new Google_Service_Calendar_Event();
$event->setSummary("WHY IS THIS NOT WOKING?");
$start = new Google_Service_Calendar_EventDateTime();
$start->setDateTime(date('Y-m-d\TH:i:s',strtotime('2014-12-24 10:00:00')));
$start->setTimeZone('Australia/Melbourne');
$event->setStart($start);
$end = new Google_Service_Calendar_EventDateTime();
$end->setDateTime(date('Y-m-d\TH:i:s',strtotime('2014-12-26 12:00:00')));
$end->setTimeZone('Australia/Melbourne');
$event->setEnd($end);
$newEvent = $service->events->insert('primary', $event);
$newEvent->getId();
$event = $service->events->get('primary', $newEvent->getId());
echo '<pre>'; print_r($event); echo '</pre>';
With the new Google_Client API, you need to share your calendar to yourself.
$scope = new Google_Service_Calendar_AclRuleScope();
$scope->setType('user');
$scope->setValue( 'Your Email Goes Here' );
$rule = new Google_Service_Calendar_AclRule();
$rule->setRole( 'owner' );
$rule->setScope( $scope );
$result = $service->acl->insert('primary', $rule);
Let me know if you still have issue.
I seem to have bumped into a google calendar api problem. and I can't really see where I have made the error so an extra set of eyes would be greatly appreciated. The problem in short is that the part of the code that should output the events.. doesn't (the "result" part of the code.
require_once "./google-api-php-client/src/Google/Client.php";
require_once "./google-api-php-client/src/Google/Service/Calendar.php";
// Service Account info
$client_id = "XXXXXX-XXXXXXXXXXXXXXXXXXXXX.apps.googleusercontent.com";
$app_name = "Some-name";
$service_account_name = 'XXXXX-XXXXXXXXXXXXXXXXXXXXXXX#developer.gserviceaccount.com';
$key_file_location = 'google-api-php-client/Some-name-xxxxxxxxxx.p12';
$cal_id = "primary";
// Service Account info
$client_id = $client_id;
$service_account_name = $service_account_name;
$key_file_location = $key_file_location;
// Calendar id
$calName = $cal_id;
$client = new Google_Client();
$client -> setApplicationName($app_name);
$service = new Google_Service_Calendar($client);
$key = file_get_contents($key_file_location);
$cred = new Google_Auth_AssertionCredentials(
$service_account_name,
array('https://www.googleapis.com/auth/calendar.readonly'),
$key
);
$client->setAssertionCredentials($cred);
$cals = $service->calendarList->listCalendarList();
print_r($cals);
echo "<br>events<br>";
$events = $service->events->listEvents($calName);
var_dump($events);
echo "<br>result:<br>";
// the following is what returns nothing, works fine until this point.
$i = 0;
foreach ( $events->getItems() as $event ) {
echo 'i:'.$i.' '.$event->getSummary();
$i++;
}
echo 'end';
Change $events to the below line:
$events = $service->events->listEvents('primary', $params);
Instead of primary, add $calName and also send $params in listEvents method.
Hope this works.