(403) Insufficient Permission, for sending email on gmail api - php

I'm able to retrieve an email with authentication for reading the google api. I followed the quick start guid, and am able to read email messages after setting up a client and linking it to a client_secret.json file.
What I have working so far is the following:
<?php
require 'google-api-php-client/src/Google/autoload.php';
define('APPLICATION_NAME', 'Gmail API Quickstart');
define('CREDENTIALS_PATH', '~/.credentials/gmail-api-quickstart.json');
define('CLIENT_SECRET_PATH', 'client_secret.json');
define('SCOPES', implode(' ', array(
Google_Service_Gmail::GMAIL_READONLY)
));
/**
* Returns an authorized API client.
* #return Google_Client the authorized client object
*/
function getClient() {
$client = new Google_Client();
$client->setApplicationName(APPLICATION_NAME);
$client->setScopes(SCOPES);
$client->setAuthConfigFile(CLIENT_SECRET_PATH);
$client->setAccessType('offline');
// Load previously authorized credentials from a file.
$credentialsPath = expandHomeDirectory(CREDENTIALS_PATH);
if (file_exists($credentialsPath)) {
$accessToken = file_get_contents($credentialsPath);
} 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->authenticate($authCode);
// Store the credentials to disk.
if(!file_exists(dirname($credentialsPath))) {
mkdir(dirname($credentialsPath), 0700, true);
}
file_put_contents($credentialsPath, $accessToken);
printf("Credentials saved to %s\n", $credentialsPath);
}
$client->setAccessToken($accessToken);
// Refresh the token if it's expired.
if ($client->isAccessTokenExpired()) {
$client->refreshToken($client->getRefreshToken());
file_put_contents($credentialsPath, $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_Gmail($client);
// Print the labels in the user's account.
$user = 'me';
//$results = $service->users_labels->listUsersLabels($user);
//$results = $service->users_messages->get('denverwebsiterepair#gmail.com', '14eadd821012b3ed');
$optParams['maxResults'] = 5;
$optParams['labelIds'] = 'INBOX';
$messages= $service->users_messages->listUsersMessages('me', $optParams);
$list = $messages->getMessages();
$messageId = $list[0]->getId();
$optParamsGet = [];
$optParamsGet['format'] = 'full';
$message = $service->users_messages->get('me', $messageId, $optParamsGet);
$messagePayload = $message->getPayload();
$headers = $message->getPayload()->getHeaders();
$part = $message->getPayload()->getParts();
$body = $part[0]['body'];
$rawData = $body->data;
$decodeMessage = base64_decode($rawData);
// THIS IS THE MESSAGE BODY I CAN GET
echo $decodeMessage;
What puzzles me is that when I try the following to try to send mail, per the google instructions, I get the error:
Error calling POST https://www.googleapis.com/gmail/v1/users/me/messages/send: (403) Insufficient Permission
All I did was add a change to the bottom:
<?php
require 'google-api-php-client/src/Google/autoload.php';
define('APPLICATION_NAME', 'Gmail API Quickstart');
define('CREDENTIALS_PATH', '~/.credentials/gmail-api-quickstart.json');
define('CLIENT_SECRET_PATH', 'client_secret.json');
define('SCOPES', implode(' ', array(
Google_Service_Gmail::GMAIL_READONLY)
));
/**
* Returns an authorized API client.
* #return Google_Client the authorized client object
*/
function getClient() {
$client = new Google_Client();
$client->setApplicationName(APPLICATION_NAME);
$client->setScopes(SCOPES);
$client->setAuthConfigFile(CLIENT_SECRET_PATH);
$client->setAccessType('offline');
// Load previously authorized credentials from a file.
$credentialsPath = expandHomeDirectory(CREDENTIALS_PATH);
if (file_exists($credentialsPath)) {
$accessToken = file_get_contents($credentialsPath);
} 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->authenticate($authCode);
// Store the credentials to disk.
if(!file_exists(dirname($credentialsPath))) {
mkdir(dirname($credentialsPath), 0700, true);
}
file_put_contents($credentialsPath, $accessToken);
printf("Credentials saved to %s\n", $credentialsPath);
}
$client->setAccessToken($accessToken);
// Refresh the token if it's expired.
if ($client->isAccessTokenExpired()) {
$client->refreshToken($client->getRefreshToken());
file_put_contents($credentialsPath, $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();
//------------ MY CHANGES HERE ---------------
$service = new Google_Service_Gmail($client);
// Print the labels in the user's account.
$user = 'me';
//$results = $service->users_labels->listUsersLabels($user);
try {
$msg = new Google_Service_Gmail_Message();
$mime = rtrim(strtr(base64_encode("THIS IS A TEST MESSAGE"), '+/', '-_'), '=');
$msg->setRaw($mime);
$service->users_messages->send("me", $msg);
echo "OK";
} catch (Exception $ex) {
echo $ex->getMessage();
}
EDIT: I realized that my Google_Service_Gmail scope was set to READ_ONLY. I tried changing this to MAIL_GOOGLE_COM per the api source on line 34, but still got the error.

Change the the scope to: GMAIL_COMPOSE instead to MAIL_GOOGLE_COM and then try to reconnect through Google API so it get the permission again. You can also add multiple scope in the scopes array.
I hope it will work for you.

Don't Forget to reconnect through Google API by re generating the credentials after deleting the old one on google developer console, after updating the scope in the code as per required.

Related

Fatal error: Uncaught exception 'Google\Service\Exception' with message '{ "error": "unauthorized_client", "error_description": "Unauthorized" }

This is the code I have and it does not work for me, it returns the error commented on the subject. I have done the whole process by registering, delegating the entire domain and authorizing everything and it fails...
$REDIRECT_URI = 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
$KEY_LOCATION = $_SERVER['DOCUMENT_ROOT'].'/cada/includes/classes/google-api-php-client-2.1.1/client_secret_1050007893675-7bkmqjiqr1p57s9alr7fu7e016lrh5hc.apps.googleusercontent.com.json';
$TOKEN_FILE = $_SERVER['DOCUMENT_ROOT']."/cada/share/token.txt";
$SCOPES = array(
Google_Service_Calendar::CALENDAR
);
$client = new Google_Client();
$client->setApplicationName("SimesatSat");
$client->setAuthConfig($KEY_LOCATION);
// Incremental authorization
$client->setIncludeGrantedScopes(true);
// Allow access to Google API when the user is not present.
$client->setAccessType('offline');
$client->setRedirectUri($REDIRECT_URI);
$client->setScopes($SCOPES);
if (isset($_GET['code']) && !empty($_GET['code']))
{
try
{
// Exchange the one-time authorization code for an access token
$accessToken = $client->fetchAccessTokenWithAuthCode($_GET['code']);
// Save the access token and refresh token in local filesystem
file_put_contents($TOKEN_FILE, json_encode($accessToken));
$_SESSION['accessToken'] = $accessToken;
header('Location: ' . filter_var($REDIRECT_URI, FILTER_SANITIZE_URL));
exit();
}
catch (\Google_Service_Exception $e)
{
print_r($e);
}
}
if (!isset($_SESSION['accessToken']))
{
$token = #file_get_contents($TOKEN_FILE);
if ($token == null)
{
// Generate a URL to request access from Google's OAuth 2.0 server:
$authUrl = $client->createAuthUrl();
// Redirect the user to Google's OAuth server
header('Location: ' . filter_var($authUrl, FILTER_SANITIZE_URL));
exit();
}
else
{
$_SESSION['accessToken'] = json_decode($token, true);
}
}
$client->setAccessToken($_SESSION['accessToken']);
/* Refresh token when expired */
if ($client->isAccessTokenExpired())
{
// the new access token comes with a refresh token as well
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
file_put_contents($TOKEN_FILE, json_encode($client->getAccessToken()));
}
////////////CONSULTA DATOS ////////////////////////////
$service = new Google_Service_Calendar($client);
$results = $service->calendarList->listCalendarList();
print_r($results);
Can anybody help me? I have another project with another client with the same code and it works perfectly! I do not understand what's happening. The only difference is that this project is part of a subdomain. Could that be the mistake?

Google api client php access token not working

I am using "google api client php" to get access token using service account json base key file. But i am getting access token null. My sample code is
$client = new \Google_Client();
$client->setApplicationName('My App');
putenv('GOOGLE_APPLICATION_CREDENTIALS=path-to-the-key.json');
$client->useApplicationDefaultCredentials();
$client->setScopes(['https://www.googleapis.com/auth/analytics.readonly']);
$client->authorize();
$token = $client->getAccessToken();
echo $token; // null
I was solved my problem by developing own php code from google documentation. I use sign JWT payload using Guzzle HTTP Client to get access token. Here is the doc
My implementation:
public static function base64url_encode($data) {
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}
public static function getJwtAssertion($private_key_file)
{
$json_file = file_get_contents($private_key_file);
$info = json_decode($json_file);
$private_key = $info->{'private_key'};
//{Base64url encoded JSON header}
$jwtHeader = self::base64url_encode(json_encode(array(
"alg" => "RS256",
"typ" => "JWT"
)));
//{Base64url encoded JSON claim set}
$now = time();
$jwtClaim = self::base64url_encode(json_encode(array(
"iss" => $info->{'client_email'},
"scope" => "https://www.googleapis.com/auth/analytics.readonly",
"aud" => "https://www.googleapis.com/oauth2/v4/token",
"exp" => $now + 3600,
"iat" => $now
)));
$data = $jwtHeader.".".$jwtClaim;
// Signature
$Sig = '';
openssl_sign($data,$Sig,$private_key,'SHA256');
$jwtSign = self::base64url_encode($Sig);
//{Base64url encoded JSON header}.{Base64url encoded JSON claim set}.{Base64url encoded signature}
$jwtAssertion = $data.".".$jwtSign;
return $jwtAssertion;
}
public static function getGoogleAccessToken($private_key_file)
{
$result = [
'success' => false,
'message' => '',
'token' => null
];
if (Cache::has('google_token')) {
$result['token'] = Cache::get('google_token');
$result['success'] = true;
return $result;
}
if(!file_exists($private_key_file)){
$result['message'] = 'Google json key file missing!';
return $result;
}
$jwtAssertion = self::getJwtAssertion($private_key_file);
try {
$client = new Client([
'base_uri' => 'https://www.googleapis.com',
]);
$payload = [
'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer',
'assertion' => $jwtAssertion
];
$response = $client->request('POST', 'oauth2/v4/token', [
'form_params' => $payload
]);
$data = json_decode($response->getBody());
$result['token'] = $data->access_token;
$result['success'] = true;
$expiresAt = now()->addMinutes(58);
Cache::put('google_token', $result['token'], $expiresAt);
} catch (RequestException $e) {
$result['message'] = $e->getMessage();
}
return $result;
}
Now call it:
$googleToken = getGoogleAccessToken($KEY_FILE_LOCATION);
I used similar type of client to get access token but that was for google sheets.
This would be same like that. So I'm sharing my google sheets code snippet here.
<?php
if (!function_exists('curl_reset'))
{
function curl_reset(&$ch)
{
$ch = curl_init();
}
}
require_once __DIR__ . '/goog/vendor/autoload.php';
define('APPLICATION_NAME', 'Google Sheets API PHP Quickstart');
define('CREDENTIALS_PATH', __DIR__ . '/sheets.googleapis.com-php-quickstart.json');
define('CLIENT_SECRET_PATH', __DIR__ . '/client_secret.json');
// If modifying these scopes, delete your previously saved credentials
// at ~/.credentials/sheets.googleapis.com-php-quickstart.json
define('SCOPES', implode(' ', array(
Google_Service_Sheets::SPREADSHEETS)
));
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(APPLICATION_NAME);
$client->setScopes(SCOPES);
$client->setAuthConfig(CLIENT_SECRET_PATH);
$client->setAccessType('offline');
// Load previously authorized credentials from a file.
$credentialsPath = CREDENTIALS_PATH;
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;
}
So when you call getClient function in a php script in command line it will generate a link to verify the user in browser after that it will provide an code which you have to place in the command line. Then it will generate the access token which can be reused later.

PHP / GMail API

I have been trying to use PHP coding for accessing my Gmail, following the documentation here: https://developers.google.com/gmail/api/quickstart/php
This worked well until this evening when I started back on it. I now get the following error:
Fatal error: Uncaught LogicException: refresh token must be passed in
or set as part of setAccessToken in
C:\Users\mcgranj\Dropbox\eBay_web\google\vendor\google\apiclient\src\Google\Client.php:258
Stack trace: #0
C:\Users\mcgranj\Dropbox\eBay_web\google\quickstart.php(71):
Google_Client->fetchAccessTokenWithRefreshToken(NULL) #1
C:\Users\mcgranj\Dropbox\eBay_web\google\quickstart.php(118):
getClient() #2 {main} thrown in
C:\Users\mcgranj\Dropbox\eBay_web\google\vendor\google\apiclient\src\Google\Client.php
on line 258
I have been troubleshooting it all night, following every suggestion I could find:
Google API Client "refresh token must be passed in or set as part of setAccessToken"
Google API PHP Refresh Token returns NULL
Google api refresh_token null and how to refresh access token
But I am still having that problem, and it is using the quick start PHP code. I am so frustrated by this. Any guidance and/or suggestions are welcome.
Here is my PHP code:
<?php
require_once __DIR__ . '/vendor/autoload.php';
date_default_timezone_set('America/Chicago');
ini_set('max_execution_time', 0); //indefinite
ini_set('memory_limit','256M'); //increase PHP memory
ini_set('display_errors', 10);
define('APPLICATION_NAME', 'Gmail API PHP Quickstart');
define('CREDENTIALS_PATH', '~/.credentials/gmail-php-quickstart.json');
define('CLIENT_SECRET_PATH', __DIR__ . '/client_secret.json');
define('SCOPES', implode(' ', array(
Google_Service_Gmail::GMAIL_READONLY)
));
function getClient() {
$client = new Google_Client();
$client->setApplicationName(APPLICATION_NAME);
$client->setScopes(SCOPES);
$client->setAuthConfig(CLIENT_SECRET_PATH);
$client->setAccessType('offline');
$credentialsPath = expandHomeDirectory(CREDENTIALS_PATH);
if (file_exists($credentialsPath)) {
$accessToken = json_decode(file_get_contents($credentialsPath), true);
} else {
$authUrl = $client->createAuthUrl();
printf("Open the following link in your browser:\n%s\n", $authUrl);
print 'Enter verification code: ';
$authCode = trim(fgets(STDIN));
$accessToken = $client->fetchAccessTokenWithAuthCode($authCode);
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);
if ($client->isAccessTokenExpired()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
$newAccessToken = $client->getAccessToken();
$accessToken = array_merge($accessToken, $newAccessToken);
file_put_contents($credentialsPath, json_encode($accessToken));
}
return $client;
}
function expandHomeDirectory($path) {
$homeDirectory = getenv('HOME');
if (empty($homeDirectory)) {
$homeDirectory = getenv('HOMEDRIVE') . getenv('HOMEPATH');
}
return str_replace('~', realpath($homeDirectory), $path);
}
$client = getClient();
$service = new Google_Service_Gmail($client);
$user = 'me';
$results = $service->users_labels->listUsersLabels($user);
function listMessages($service, $user) {
$pageToken = NULL;
$messages = array();
$opt_param = array();
do {
try {
if ($pageToken) {
$opt_param['pageToken'] = $pageToken;
}
$opt_param['maxResults'] = 5; //Return only 5 messages
$opt_param['labelIds'] = 'INBOX';
$opt_param['q'] = "after:2017/07/08 FROM:shipment-tracking#amazon.com";
$messagesResponse = $service->users_messages->listUsersMessages($user, $opt_param);
if ($messagesResponse->getMessages()) {
$messages = array_merge($messages, $messagesResponse->getMessages());
$pageToken = $messagesResponse->getNextPageToken();
}
} catch (Exception $e) {
print 'An error occurred: ' . $e->getMessage();
}
} while ($pageToken);
foreach ($messages as $message) {
print 'Message with ID: ' . $message->getId() . '<br/>';
$id = $message->getId();
echo "<pre>"; print_r($message); echo "</pre>";
$gmailurl = "https://www.googleapis.com/gmail/v1/users/".$user."/messages/".$id;
echo "<a href='$gmailurl' target='_blank'>".$gmailurl."</a><p>";
$messagePayload = $message->getPayload();
}
return $messages;
}
listMessages($service, $user);
?>
Based from this thread, make sure that you have called json_encode before writing the auth result to the token.json file. You can fix it by adding json_encode like: file_put_contents($credentialsPath, json_encode($accessToken));. Also, this page suggested to add $client->setAccessType('offline'); and include force prompt to return the refresh token: $client->setApprovalPrompt('force');.

google sheets api v4 PHP Quickstart Writing to a single range

I can read my Google Sheet Doc use this tutorial: https://developers.google.com/sheets/api/quickstart/php
quickstart.php:
<?php
require_once __DIR__ . '/vendor/autoload.php';
define('APPLICATION_NAME', 'Google Sheets API PHP Quickstart');
define('CREDENTIALS_PATH', '~/.credentials/sheets.googleapis.com-php-quickstart.json');
define('CLIENT_SECRET_PATH', __DIR__ . '/client_secret.json');
// If modifying these scopes, delete your previously saved credentials
// at ~/.credentials/sheets.googleapis.com-php-quickstart.json
define('SCOPES', implode(' ', array(
Google_Service_Sheets::SPREADSHEETS_READONLY)
));
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(APPLICATION_NAME);
$client->setScopes(SCOPES);
$client->setAuthConfig(CLIENT_SECRET_PATH);
$client->setAccessType('offline');
// Load previously authorized credentials from a file.
$credentialsPath = expandHomeDirectory(CREDENTIALS_PATH);
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_Sheets($client);
// Prints the names and majors of students in a sample spreadsheet:
$spreadsheetId = 'myfileid';
$range = 'Class Data!A2';
$response = $service->spreadsheets_values->get($spreadsheetId, $range);
$values = $response->getValues();
if (count($values) == 0) {
print "No data found.\n";
} else {
print "Name, Major:\n";
foreach ($values as $row) {
// Print columns A and E, which correspond to indices 0 and 4.
printf("%s, %s\n", $row[0], $row[4]);
}
}
All is Ok. I can read my Google Sheet Doc. But I need have only one additional possibility: writing to a single range. I added to end of quickstart.php this code:
$values = array(
array(
5
),
// Additional rows ...
);
$body = new Google_Service_Sheets_ValueRange(array(
'values' => $values
));
$params = array(
'valueInputOption' => $valueInputOption
);
$result = $service->spreadsheets_values->update($spreadsheetId, $range,
$body, $params);
frome here: https://developers.google.com/sheets/api/guides/values
I have:
PHP Fatal error:
Uncaught exception 'Google_Service_Exception' with message '{
"error": {
"code": 403,
"message": "Request had insufficient authentication scopes.",
"errors": [
{
"message": "Request had insufficient authentication scopes.",
"domain": "global",
"reason": "forbidden"
}
],
"status": "PERMISSION_DENIED"
}
}
My Google Sheet Doc has permission for redact/modify. I need have writing to a single range. What is mean this error? Please help me modify quickstart.php.
Change the scopes to Google_Service_Sheets::SPREADSHEETS check,
also try this
$params = array(
'valueInputOption' => $valueInputOption
);
to check
$params = array(
'valueInputOption' => 'USER_ENTERED'
);

Google Calendar 403 Forbidden PHP Server to Server Communication

<?php
include('lead1.php');
require_once __DIR__ . '/vendor/autoload.php';
global $link;
$emailmsgsql = "SELECT *
FROM psleads WHERE agreeid = '6'";
$msgreqsres = mysqli_query($link, $emailmsgsql); // or die(mysql_error()0);
$msgreqs = $msgreqsres->fetch_assoc();
$start = $msgreqs['contractbegindate'] . ' ' . $msgreqs['contractbegintime'];
$end = $msgreqs['contractenddate'] . ' ' . $msgreqs['contractendtime'];
$startDT = new DateTime($start, new DateTimeZone('Pacific/Honolulu'));
$endDT = new DateTime($end, new DateTimeZone('Pacific/Honolulu'));
$startDTw3c = $startDT->format(DateTime::W3C);
$endDTw3c = $endDT->format(DateTime::W3C);
putenv('GOOGLE_APPLICATION_CREDENTIALS=./service-account.json');
define('CREDENTIALS_PATH', '~/calendar-php.json');
define('CLIENT_SECRET_PATH', './client_secret.json');
//define('CLIENT_SECRET_PATH', __DIR__ . '/client_secret.json');
$client = new Google_Client();
$client->setApplicationName("Paradise_Sound_Booking_Calendar");
$client->addScope('https://www.googleapis.com/auth/calendar');
$client->setAuthConfig(CLIENT_SECRET_PATH);
$client->setClientId('532085378494-s908fs5mu4rf2e2s60cecgaprg9pem1p.apps.googleusercontent.com');
$client->setDeveloperKey("XXXXX");//flo.gd
$client->useApplicationDefaultCredentials();
// Load previously authorized credentials from a file.
function expandHomeDirectory($path) {
$homeDirectory = getenv('HOME');
if (empty($homeDirectory)) {
$homeDirectory = getenv('HOMEDRIVE') . getenv('HOMEPATH');
}
return str_replace('~', realpath($homeDirectory), $path);
}
$credentialsPath = expandHomeDirectory(CREDENTIALS_PATH);
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));
$authCode = 'Manually pasted return code into script here';
// 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()));
}
$service = new Google_Service_Calendar($client);
$event = new Google_Service_Calendar_Event(array(
'summary' => 'Booked Event ' . $msgreqs['contractbegindate'],
'start' => array(
'dateTime' => $startDTw3c,
//'dateTime' => '2015-05-28T09:00:00-07:00',
'timeZone' => 'Pacific/Honolulu',
),
'end' => array(
'dateTime' => $endDTw3c,
'timeZone' => 'Pacific/Honolulu',
)
));
$calendarId = 'iddnpsbinrifod2826eqo1kmoo#group.calendar.google.com';
$eventres = $service->events->insert($calendarId, $event);
echo json_encode($eventres);
?>
So here is my PHP code I am using to test event insertion into MY google calendar.
I thought I could use just an API key but google seems to have this convulted way of doing OAUTH that I just can't figure out. I can see all my 403 errors in my API Developers Console.
Does anyone have working code to do simple event inserts into my calendar.
CONTEXT:
I will recieve an IPN from paypal (done) and that will fire off this script that will insert an event into MY calendar, not the users. Can anyone help me without referring me to the google developer docs? They seem sparse and I have read them over and over and over again to no avail of solving my issue.
Here is the error I am getting:
Fatal error: Uncaught exception 'Google_Service_Exception' with
message '{ "error": { "errors": [ { "domain": "global", "reason":
"forbidden", "message": "Forbidden" } ], "code": 403, "message":
"Forbidden" } } ' in
/home/dahfrench/flo.gd/src/Google/Http/REST.php:118 Stack trace: #0
/home/dahfrench/flo.gd/src/Google/Http/REST.php(94):
Google_Http_REST::decodeHttpResponse(Object(GuzzleHttp\Psr7\Response),
Object(GuzzleHttp\Psr7\Request), 'Google_Service_...') #1 [internal
function]: Google_Http_REST::doExecute(Object(GuzzleHttp\Client),
Object(GuzzleHttp\Psr7\Request), 'Google_Service_...') #2
/home/dahfrench/flo.gd/src/Google/Task/Runner.php(181):
call_user_func_array(Array, Array) #3
/home/dahfrench/flo.gd/src/Google/Http/REST.php(58):
Google_Task_Runner->run() #4
/home/dahfrench/flo.gd/src/Google/Client.php(789):
Google_Http_REST::execute(Object(GuzzleHttp\Client),
Object(GuzzleHttp\Psr7\Request), 'Google_Service_...', Array) #5
/home/dahfrench/flo.gd/src/Google/Service/Resource.php(232): Goo in
/home/dahfrench/flo.gd/src/Google/Http/REST.php on line 118
You may want to finalize what authentication you want to implement : user needs to login to perform/request to Google Services or delegate a domain-wide authority to the service account.
If you will be using OAuth 2.0:
Your application must use OAuth 2.0 to authorize requests.
Sample Code from Google:
<?php
require_once __DIR__ . '/vendor/autoload.php';
define('APPLICATION_NAME', 'Google Calendar API PHP Quickstart');
define('CREDENTIALS_PATH', '~/.credentials/calendar-php-quickstart.json');
define('CLIENT_SECRET_PATH', __DIR__ . '/client_secret.json');
// If modifying these scopes, delete your previously saved credentials
// at ~/.credentials/calendar-php-quickstart.json
define('SCOPES', implode(' ', array(
Google_Service_Calendar::CALENDAR_READONLY)
));
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(APPLICATION_NAME);
$client->setScopes(SCOPES);
$client->setAuthConfig(CLIENT_SECRET_PATH);
$client->setAccessType('offline');
// Load previously authorized credentials from a file.
$credentialsPath = expandHomeDirectory(CREDENTIALS_PATH);
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_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);
if (count($results->getItems()) == 0) {
print "No upcoming events found.\n";
} else {
print "Upcoming events:\n";
foreach ($results->getItems() as $event) {
$start = $event->start->dateTime;
if (empty($start)) {
$start = $event->start->date;
}
printf("%s (%s)\n", $event->getSummary(), $start);
}
}
If you will be using Google Apps Domain-Wide Delegation of Authority:
Authorizing a service account to access data on behalf of users in a domain is sometimes referred to as "delegating domain-wide authority" to a service account.
Sample Code from a SO post:
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();
}
?>
Note: If you plan on using only one calendar, I would recommend using a service account then sharing your calendar to the account in order to avoid 403 : Forbidden as said in the related SO post
Hope this helps.

Categories