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 !
Related
I am trying to update Google Calendar using the PHP API. I have successfully been able to create Google Calendar Events and automatically get the ID for the event, but when I try and update the event, I get this error:
PHP Fatal error: Call to undefined function dateTime() in public_html/googleapi/calendarupdate.php on line 45. It is referring to the line:
$event->setStart.dateTime($startdatetime);
Here is my current PHP Code for the error:
<?php
header('Content-type: application/json');
require_once __DIR__ . '/google-api-php-client/src/Google/autoload.php';
$summary = $_POST["summary"];
$location = $_POST["location"];
$description = $_POST["description"];
$startdatetime = $_POST["startdatetime"];
$enddatetime = $_POST["enddatetime"];
$clientemail = $_POST["clientemail"];
$privatekey = $_POST["privatekey"];
$useremail = $_POST["useremail"];
$calendarid = $_POST["calendarid"];
$client_email = $clientemail;
$private_key = file_get_contents($privatekey);
$scopes = array('https://www.googleapis.com/auth/calendar');
$user_to_impersonate = $useremail;
$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
);
$client = new Google_Client();
$client->setAssertionCredentials($credentials);
if ($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion();
}
$service = new Google_Service_Calendar($client);
$event = $service->events->get($useremail, $calendarid);
$event->setSummary($summary);
$event->setLocation($location);
$event->setStart.dateTime($startdatetime);
$event->setStart.timeZone('America/Los_Angeles');
$event->setEnd.dateTime($enddatetime);
$event->setEnd.timeZone('America/Los_Angeles');
$event->setDescription($description);
$updatedEvent = $service->events->update($useremail, $event->getId(), $event);
echo json_encode($updatedEvent);
My PHP code is based off of Google's API Documentation found here.
Ok, I actually managed to figure it out. I just had to change the line:
$event->setStart.dateTime($startdatetime);
To This:
$event->start->setDateTime($startdatetime);
I do the same general thing for the end datetime, except where it says start, I just put end. Just tested it and it worked perfectly. The site that helped me out can be found here.
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??
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'm trying to make some analytics query from server to server.
I'm using laravel with https://github.com/google/google-api-php-client library.
This is the code I'm using:
$client = new Google_Client();
$key = file_get_contents(storage_path('key.p12'));
$cred = new Google_Auth_AssertionCredentials(
'***#developer.gserviceaccount.com', array('https://www.googleapis.com/auth/youtube.readonly', 'https://www.googleapis.com/auth/yt-analytics.readonly'), $key);
$client->setAssertionCredentials($cred);
if ($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion($cred);
}
Session::put('service_token', $client->getAccessToken());
$service = new Google_Service_YouTubeAnalytics($client);
$id = 'channel==MINE';
$start_date = '2014-05-01';
$end_date = '2014-06-30';
$optparams = array(
'dimensions' => 'day',
'sort' => 'day,-views'
);
$metric = 'views,estimatedMinutesWatched';
$api = $service->reports->query($id, $start_date, $end_date, $metric, $optparams);
$service = new Google_Service_YouTubeAnalytics($client);
$id = 'channel==MINE';
$start_date = '2014-05-01';
$end_date = '2014-06-30';
$optparams = array(
'dimensions' => 'day',
'sort' => 'day,-views'
);
$metric = 'views,comments,favoritesAdded,likes,dislikes,estimatedMinutesWatched,averageViewDuration';//'views,estimatedMinutesWatched';
$api = $service->reports->query($id, $start_date, $end_date, $metric, $optparams);
My problem is that the authentication is working just fine, but I can't get the analytics query get to work, I'm getting the following error:
Error calling GET https://www.googleapis.com/youtube/analytics/v1/reports?ids=channel%3D%3DMINE&start-date=2014-05-01&end-date=2014-06-30&metrics=views%2CestimatedMinutesWatched&dimensions=day&sort=day%2C-views: (400) Invalid query. Query did not conform to the expectations.
Even though the same exact query is working in the API explorer:
https://developers.google.com/apis-explorer/#p/youtubeAnalytics/v1/youtubeAnalytics.reports.query?ids=channel%253D%253DMINE&start-date=2014-05-01&end-date=2014-06-30&metrics=views%252CestimatedMinutesWatched&dimensions=day&sort=day%252C-views&_h=1&
Any idea?
I tested your query and it's working fine, but apparently YouTube does not support service accounts. The documentation says it should return a 403 in this case, but for some reason it's returning 400.
You need to add a Google API key
https://www.googleapis.com/youtube/analytics/v1/reports?ids=channel%3D%3DMINE&start-date=2014-05-01&end-date=2014-06-30&metrics=views%2CestimatedMinutesWatched&dimensions=day&sort=day%2Cviews&key={YOUR_API_KEY}
also if you look at your string you have type error on the end where "-views" should be just "views" without dash
You can use Google automated tool to generate a valid link.
https://developers.google.com/youtube/analytics/v1/
I am working on the PHP API to Google Calendar, I have previously used the Zend library and I am upgrading to the API V3 I downloaded the Git Hub client library v1.0.
I have completed oAuth 2 and I am storing Refresh tokens in a database. I can connect and write events to Google Calendar, thanks mainly to the contributors at StackOverflow. Thanks
My problem is that I cannot delete events. I am connecting with oAuth 2 and retrieving event Ids however
$service->events->delete('primary', $event->getId());
This generates Fatal error: Uncaught exception 'Google_IO_Exception' with message 'HTTP Error: Unable to connect: '0'' in C:\wamp\www\new-roster-decoder\src\Google\IO\Stream.php on line 128
I have hunted high and low and been unable to find a solution. Please help Thanks
EDITED AS SOLVED
Due to Emily's great advice this is solved
Solution downloaded the latest API from GitHub as the problem of GZIP has been sorted.
As a matter of interest I initially commented out GZIP in congig.php and this fixed it, but I then lost the performance benefits, then new library sorted it.
Lessons learnt. Stackoverflow users are very kind to give their time, and always try the lastest software
END OF EDIT
<?php
/// This works
session_start();
set_include_path("src/" . PATH_SEPARATOR . get_include_path());
require_once 'Google/Client.php';
require_once 'Google/Service/Calendar.php';
require_once 'account/dbc.php';
$client_id = 'XXXXXXXXXX.apps.googleusercontent.com';
$client_secret = 'XXXXXXXXXXX';
$redirect_uri = 'http://localhost:80/new-roster-decoder/account/GoogleoAuth.php';
$client = new Google_Client();
$client->setClientId($client_id);
$client->setClientSecret($client_secret);
$client->setRedirectUri($redirect_uri);
$client->addScope("https://www.googleapis.com/auth/calendar");
$client->setAccessType('offline');
$users_rs_settings = mysqli_query($link,"select * from users WHERE id = 118");
$users_array = mysqli_fetch_array($users_rs_settings);
$refresh_token = $users_array['refresh_token']; //2010-04-06
$client->refreshToken($refresh_token);
$service = new Google_Service_Calendar($client);
$event = new Google_Service_Calendar_Event();
$event->setSummary('Positioning TX');
$event->setLocation('BRS-LGW');
$start = new Google_Service_Calendar_EventDateTime();
$start->setDateTime('2014-02-19T14:00:00.000-00:00');
$start->setTimeZone('Europe/London');
$event->setStart($start);
$end = new Google_Service_Calendar_EventDateTime();
$end->setDateTime('2014-02-19T17:25:00.000-00:00');
$end->setTimeZone('Europe/London');
$event->setEnd($end);
// insert ext properties
$rdname = "RosterDecoderID";
$rdvalue = 1;
$extendedProperties = New Google_Service_Calendar_EventExtendedProperties();
$extendedProperties->setPrivate(array($rdname=>$rdvalue));
$event->setExtendedProperties($extendedProperties);
// end of insert ext properties
$createdEvent = $service->events->insert('primary', $event);
echo $createdEvent->getId()."\n\n";
$_SESSION['access_token'] = $client->getAccessToken();
var_dump($_SESSION['access_token']);
var_dump($event);
$minCheck = date(DATE_ATOM, mktime(0, 0, 0, date("m"), date("d"), date("Y") ));
$maxCheck = date(DATE_ATOM, mktime(0, 0, 0, date("m"), (date("d")+1), date("Y") ));
$optParams = array( 'privateExtendedProperty' => 'RosterDecoderID=1','timeMin' => $minCheck, 'timeMax' => $maxCheck);
$events = $service->events->listEvents('primary', $optParams);
while(true) {
foreach ($events->getItems() as $event) {
$eventID = $event->getId();
//////////////////////////////////////////////////////////
//This bit throws an error
$service->events->delete('primary', $event->getId());
/////////////////////////////////////////////////////////
// The error is
// Fatal error: Uncaught exception 'Google_IO_Exception' with message 'HTTP Error: Unable to connect: '0'' in C:\wamp\www\new-roster-decoder\src\Google\IO\Stream.php on line 128
echo $event->getSummary();
echo $event->getId()."\n\n";
}
}
?>
I am able to delete event from google calendar..
use private key file you get from developer console.
Fore more info check this link
What is the Google API password for the OAuth PKCS p12 private key?
how-where-to-obtain-a-p12-key-file-from-the-google-developers-console
below is code please check
const KEY_FILE = '<<some location on server>>/xxx-65454f656a-xxx-560265d-privatekey.p12';
// this is my private key file location, make sure it accessible
try {
$key = file_get_contents(KEY_FILE);
$auth = new \Google_Auth_AssertionCredentials(
SERVICE_ACCOUNT_NAME,
array('https://www.googleapis.com/auth/calendar'),
$key);
$auth->sub = $calendarId;
$client = new \Google_Client();
$client->setAssertionCredentials($auth);
$client->setApplicationName("Parabola V2");
$client->setClientId(CLIENT_ID);
$service = new \Google_Service_Calendar($client);
$service->events->delete($calendarId, $eventId);
} catch (\Exception $e) {
echo "Exception while deleting event :- ".$e->getMessage();
return null;
}
$service->events->delete('primary', $event->getId());
'primary' must be the calendar id
"myname#gmail.com" or "mhggf54gfh5#group.calendar.google.com"
thats how it work for me