I have the error saying that permission denied. I already tried this (giving view access to the google credential), and this. And everything doesnt work. I already enable the API for the google drive and also did this :
gcloud components update
gcloud auth login --enable-gdrive-access
I'm using PHP.
Here's the Code
<?php
ini_set("memory_limit", "2048M");
ini_set('max_execution_time', 7200); //3600 seconds = 60 minutes
if (!defined('BASEPATH'))
exit('No direct script access allowed');
use Google\Cloud\BigQuery\BigQueryClient;
use Google\Cloud\ServiceBuilder;
use Google\Cloud\ExponentialBackoff;
require 'assets/SDK/vendor/autoload.php';
//require 'assets/library/vendor/autoload.php';
require_once 'assets/library/google-api-php-client/vendor/autoload.php';
define('APPLICATION_NAME', 'asd');
define('CLIENT_SECRET_PATH', 'assets/library/auth/asd.json');
define('PROJECT_ID','qwe');
define('SCOPES', implode(' ', array(
'https://www.googleapis.com/auth/drive',
'https://www.googleapis.com/auth/drive.file',
'https://www.googleapis.com/auth/drive.metadata',
'https://www.googleapis.com/auth/drive.readonly')
));
public function index(){
$myFile = "assets/library/auth/session_bq2.txt";
if(file_exists($myFile)){
#$fh = fopen($myFile, 'r');
// echo 'filesize '.filesize($myFile);
$session = fread($fh, filesize($myFile));
fclose($fh);
//echo '--refreshToken index '.$session;
}
$client = new Google_Client();
$client->setAccessType('offline');
$client->setClientId('asd.apps.googleusercontent.com');
$client->setClientSecret('asds');
$client->setState('asd');
$client->setApplicationName(APPLICATION_NAME);
$client->setScopes(SCOPES);
if (isset($session) && $session) {
//Set the new access token after authentication
$client->setAccessToken($session);
//json decode the session token and save it in a variable as object
$sessionToken = json_decode($session);
//Save the refresh token (object->refresh_token) into a cookie called 'token' and make last for 1 month
setcookie('access_token', $sessionToken->refresh_token , time()+2678400);
$cookie = isset($_COOKIE['access_token']) ? $_COOKIE['access_token'] : "";
if(!empty($cookie)){
$client->refreshToken($cookie);
}
$client->setAccessToken($session);
}
else{
$tes = $client->getRefreshToken();
$client = new Google_Client();
$client->setAccessType('offline');
$client->setClientId('asd.apps.googleusercontent.com');
$client->setRedirectUri('qwe');
$client->setClientSecret('asd');
$client->setState('asd');
$client->setApplicationName(APPLICATION_NAME);
$client->setScopes(SCOPES);
if (isset($_GET['code'])) {
$client->authenticate($_GET['code']);
$myfile = fopen("assets/library/auth/session_bq2.txt", "w") or die("Unable to open file!");
$txt = json_encode($client->getAccessToken());
fwrite($myfile, $txt);
fclose($myfile);
header('Location: http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF']);
}
else{
$oauth2_client_id = 'asd.apps.googleusercontent.com';
// $oauth2_redirect = 'asd';
$oauth2_redirect = 'http://' . $_SERVER['HTTP_HOST'] . 'asd';
$oauth2_server_url = 'https://accounts.google.com/o/oauth2/auth';
$query_params = array(
'response_type' => 'code',
'access_type' => 'offline',
'client_id' => $oauth2_client_id,
'scope' => SCOPES,
'redirect_uri' => $oauth2_redirect,
'state' => 'asd',
'approval_prompt' => 'force'
);
$forward_url = $oauth2_server_url . '?' . http_build_query($query_params);
header('Location: ' . $forward_url);
}
}
$service = new Google_Service_Bigquery($client);
$query="SELECT * FROM [queryspreadsheet] LIMIT 10";
putenv('GOOGLE_APPLICATION_CREDENTIALS='.dirname(__FILE__) . '/assets/library/auth/MyProject-f0b4007b2f57.json');//this can be created with other ENV mode server side
$client->useApplicationDefaultCredentials();
$builder = new ServiceBuilder([
'projectId' => 'asd',
]);
$bigQuery = $builder->bigQuery();
$job = $bigQuery->runQueryAsJob($query);
$info=$job->info();
$queryResults = $job->queryResults();
/*$queryResults = $bigQuery->runQuery(
$query,
['useLegacySql' => true]);*/
// var_dump($queryResults);die;
if ($queryResults->isComplete())
{
$i = 0;
$rows = $queryResults->rows();
foreach ($rows as $row)
{
$i++;
$result[$i] = $row;
}
}
else
{
throw new Exception('The query failed to complete');
}
$i = 0;
$i++;
var_dump($result);die;
return $result;
}
Does anyone have any idea what did I miss? Thanks.
Related
I'm getting this error (I'm using PHP 7.0 and Google PHP API 2.9.1, and I'm using OAuth credentials for Web application):
Uncaught Error: Class 'Google_Service_Gmail_Resource_Users' not found in /google-api-2.9.1/vendor/google/apiclient-services/src/Google/Service/Gmail.php:106
Stack trace:
#0 /public_html/oauth2callback.php(20): Google_Service_Gmail->__construct(Object(Google\Client))
#1 {main} thrown in /public_html/googe-api-2.9.1/vendor/google/apiclient-services/src/Google/Service/Gmail.php on line 106
And here is what Im trying to do:
My index.php:
<?php
include_once __DIR__ . '/google-api-2.9.1/vendor/autoload.php';
$client = new Google_Client();
$client->setAuthConfig(__DIR__ . 'credenciales.json');
$client->addScope(Google_Service_Gmail::GMAIL_READONLY);
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
$client->setAccessToken($_SESSION['access_token']);
$gmail = new Google_Service_Gmail($client);
$user = 'me';
$list = $gmail->users_messages->listUsersMessages($user, [ 'q' => ['from:someEmail#gmail.com in:inbox'], ]);
$messageList = $list->getMessages();
$inboxMessage = [];
foreach($messageList as $mlist){
$optParamsGet2['format'] = 'full';
$single_message = $gmail->users_messages->get('me',$mlist->id, $optParamsGet2);
$message_id = $mlist->id;
$headers = $single_message->getPayload()->getHeaders();
$snippet = $single_message->getSnippet();
foreach($headers as $single) {
if ($single->getName() == 'Subject') {
$message_subject = $single->getValue();
}
else if ($single->getName() == 'Date') {
$message_date = $single->getValue();
$message_date = date('M jS Y h:i A', strtotime($message_date));
}
else if ($single->getName() == 'From') {
$message_sender = $single->getValue();
$message_sender = str_replace('"', '', $message_sender);
}
}
$inboxMessage[] = [
'messageId' => $message_id,
'messageSnippet' => $snippet,
'messageSubject' => $message_subject,
'messageDate' => $message_date,
'messageSender' => $message_sender
];
echo json_encode($inboxMessage);
}
} else {
$redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php';
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
My oauth2callback.php file:
<?php
require_once __DIR__ . '/google-api-2.9.1/vendor/autoload.php';
$client = new Google_Client();
$client->setAuthConfig(__DIR__ . 'credenciales.json');
$client->setRedirectUri('https://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php');
$client->addScope(Google_Service_Gmail::GMAIL_READONLY);
if (! isset($_GET['code'])) {
$auth_url = $client->createAuthUrl();
header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
} else {
$client->authenticate($_GET['code']);
$_SESSION['access_token'] = $client->getAccessToken();
$gmail = new Google_Service_Gmail($client);
$user = 'me';
$list = $gmail->users_messages->listUsersMessages($user, [ 'q' => ['from:someEmail#gmail.com in:inbox'], ]);
$messageList = $list->getMessages();
$inboxMessage = [];
foreach($messageList as $mlist){
$optParamsGet2['format'] = 'full';
$single_message = $gmail->users_messages->get('me',$mlist->id, $optParamsGet2);
$message_id = $mlist->id;
$headers = $single_message->getPayload()->getHeaders();
$snippet = $single_message->getSnippet();
foreach($headers as $single) {
if ($single->getName() == 'Subject') {
$message_subject = $single->getValue();
}
else if ($single->getName() == 'Date') {
$message_date = $single->getValue();
$message_date = date('M jS Y h:i A', strtotime($message_date));
}
else if ($single->getName() == 'From') {
$message_sender = $single->getValue();
$message_sender = str_replace('"', '', $message_sender);
}
}
$inboxMessage[] = [
'messageId' => $message_id,
'messageSnippet' => $snippet,
'messageSubject' => $message_subject,
'messageDate' => $message_date,
'messageSender' => $message_sender
];
echo json_encode($inboxMessage);
}
}
When I accept the app, google takes me to:
https://mywebsite.com/oauth2callback.php?code=4/8521e-kahsd875CLzcbtvppohs584ehtptRa6nXZpjhbFTDGFQjN9jgvQj_7be2E2j654ytv&scope=https://www.googleapis.com/auth/gmail.readonly
So, I go get pass the authorization screen from Google, I accept my app, and then a blank screen. The error shown comes from the error log file.
Why I get that Class 'Google_Service_Gmail_Resource_Users' is not found when I do call the autoload file?
So I see a few problems with your current setup. The one relating to your problem is that you aren't using Composer. It's small and simple and easy to use, and handles all the autoloading stuff for you. No worries about missing directories or unzipping errors. The download version of the Google API client already includes a pre-built Composer vendor folder, so you aren't saving any disk space or code complexity by skipping it.
Second is your directory structure; the way your server is set up, it's trivial for someone to access https://mywebsite.example.com/credenciales.json and get your private data.
So here's what I recommend:
In your document root (/var/www/html/home_dir) create a public folder and copy index.php and oauth2callback.php to that folder.
Update your server configuration to point to /var/www/html/home_dir/public as your document root
Change into /var/www/html/home_dir and run composer require google/apiclient (install Composer if you haven't already)
Edit your PHP files as needed, adjusting the path to credentiales.json and changing your require directives to point to /var/www/html/home_dir/vendor/autoload.php.
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;
}
}
I'm trying to create a copy of a document using the Google Docs Api, and then edit it that copy by inserting text into it. So, I've looked at the documentation and seemingly implemented it exactly the way it says.
<?php
//That is, if this is just a regular login
//Personal Files
require("loginManager.php");
require("globals.php");
require("googleDrive.php");
//Moodle files
require("../config.php");
require("../my/lib.php");
require("../files/renderer.php");
require("../course/lib.php");
//Google Docs
$CREDENTIALS_PATH = "../../" . "vendor/autoload.php";
require ($CREDENTIALS_PATH);
//Example code
$copyTitle = 'Copy Title';
$documentId = "1vYyeGLbadFi0sl9g2LEJSZCB4YiGOpCb";
$copy = new Google_Service_Drive_DriveFile(array(
'name' => $copyTitle
));
//Initialize necessary client variables
$desiredPath = "../../credentials.json";
$authCode = (isset($_GET["code"]) ? $_GET["code"]:"");
GoogleDrive::setAuthCode($authCode);
$client = GoogleDrive::getClient($desiredPath, $FULLSCRIPT);
$docServices = new Google_Service_Docs($client);
$driveServices = new Google_Service_Drive($client);
$files = $driveServices->files;
$documents = $docServices->documents;
$driveResponse = $files->copy($documentId, $copy);
$documentCopyId = $driveResponse->id;
//Create desiredRequests
$desiredRequests = array(new Google_Service_Docs_Request(array(
'insertText' => array(
'text' => 'Hello world!',
'location' => array(
'index' => 25)))));
$batchUpdateRequests = new Google_Service_Docs_BatchUpdateDocumentRequest(array(
'requests' => $desiredRequests));
$docChangeResponse = $documents->batchUpdate($documentCopyId, $batchUpdateRequests);
echo $OUTPUT->header();
echo $OUTPUT->custom_block_region('content');
echo $OUTPUT->footer();
//Check if there's any get actions that need to be serviced
$getVariable = filter_input(INPUT_GET, "action");
if($getVariable == "openFileManager") {core_files_renderer::render_form_filemanager();}
else if($getVariable == "createCourse")
{
/*Important note: there are two types of ids when it comes to courses
*
* Programmer's Notes:
*
* -$instance is the instance of a record of from the enrol table
* -the enrol table stores instances of courses...so does mdl_course
* -idnumber and id, the latter is the actual primary key, the other is
* I guess is for school admins or course creators to be able to number
* the courses according to their own system. idnumber can be null.
*
*/
$enrollmentPlugin = enrol_get_plugin("manual");
if($enrollmentPlugin)
{
//Create data for course_request
$data = new stdClass();
$data->requester = $USER->id;
$data->id = 1;
$course_request_object = new course_request($data);
unset($data);
//create data for new course
$data = new stdClass();
$data->fullname = 'Math';
$data->shortname = 'Math 7';
$data->summary = 'Awesome!';
$data->summaryformat = FORMAT_PLAIN;
$data->format = 'topics';
$data->newsitems = 0;
$data->numsections = 5;
//$data->category = $course_request_object->get_category();
$data->category = 1;
$course = create_course($data);
//Instance is the record from the enrol table
$instanceid = $enrollmentPlugin->add_instance($course);
$instance = $DB->get_record('enrol', array('courseid'=>$course->id, 'enrol'=>'manual'), '*', MUST_EXIST);
$enrollmentPlugin->enrol_user($instance, $USER->id);
}
}
else if($getVariable == "appendDocument")
{
$courseID = filter_input(INPUT_GET, "courseID");
$fs = get_file_storage();
$data = array(
'contextid' => $courseID, // ID of context
'component' => 'course_myarea', // usually = table name
'filearea' => 'myarea', // usually = table name
'itemid' => 0, // usually = ID of row in table
'filepath' => '/', // any path beginning and ending in /
'filename' => 'myfile.txt'
);
$content = "hellp worldl";
$fs->create_file_from_string($data, $content);
}
else if($getvariable == null)
{
//if there are no get paramaters then it's a first time entry
//get all of user's courses, files, etc
$courses = enrol_get_all_users_courses($USER->id);
global $DB;
foreach($courses as $currentCourse)
{
$desiredID = $currentCourse->id;
$desiredFiles = $DB->get_record('files', array('contextid'=> $desiredID));
$contentHash = $desiredFiles->contenthash;
$dir1 = substr($contentHash, 0, 2); $dir2 = substr($contentHash, 2, 2);
$desiredPath = $CFG->dirrot."../../../../moodledata/filedir/"
.$dir1."/".$dir2."/".$contentHash;
$myFile = file_get_contents($desiredPath);
$type = mime_content_type($desiredPath);
$contentTypes = array("pdf" => "application/pdf",
"txt" => "text/plain");
//header("Content-Type: application/pdf");
//readfile($desiredPath, false, $foo);
$myFile = file_get_contents("goedel.pdf");
$foo = 3;
}
}
?>
Here's where GoogleDrive::getClient is defined in case it helps
class GoogleDrive
{
private static $AUTH_CODE;
public static function setAuthCode($desiredCode)
{
self::$AUTH_CODE = $desiredCode;
}
public static function getClient($credentialsPath, $callbackScript)
{
$client = new Google_Client();
$client->setApplicationName('MyApp');
$client->setScopes(Google_Service_Drive::DRIVE);
$client->setAuthConfig($credentialsPath);
$client->setAccessType('online');
$client->setPrompt('select_account consent');
$desiredVariable = self::$AUTH_CODE;
if($desiredVariable != null)
{
$accessToken = $client->fetchAccessTokenWithAuthCode($desiredVariable);
$client->setAccessToken($accessToken);
return $client;
}
// 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();
$client->setRedirectUri($callbackScript);
redirect($authUrl);
// 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;
}
}
However, when I run the previous code I get this error.
"{
"error": {
"code": 400,
"message": "This operation is not supported for this document",
"errors": [
{
"message": "This operation is not supported for this document",
"domain": "global",
"reason": "failedPrecondition"
}
],
"status": "FAILED_PRECONDITION"
}
}
"
Any help or direction will be greatly appreciated.
Edit 1: I've changed the script to reflect Tanaike's solution
I believe your situation and goal as follows.
You have already been able to use Google Docs API.
The script of a copy of a document worked.
You want to remove the error in your question.
For this, how about this modification?
From:
$desiredRequests = new Google_Service_Docs_Request(array(
'insertText' => array(
'text' => 'Hello world!',
'location' => array(
'index' => 25))));
In your script, when $batchUpdateRequests is retrieved, it becomes as follows.
{"requests":{"createNamedRangeType":{},"createNamedRangeDataType":{},"createParagraphBulletsType":{},"createParagraphBulletsDataType":{},"deleteContentRangeType":{},"deleteContentRangeDataType":{},"deleteNamedRangeType":{},"deleteNamedRangeDataType":{},"deleteParagraphBulletsType":{},"deleteParagraphBulletsDataType":{},"deletePositionedObjectType":{},"deletePositionedObjectDataType":{},"deleteTableColumnType":{},"deleteTableColumnDataType":{},"deleteTableRowType":{},"deleteTableRowDataType":{},"insertInlineImageType":{},"insertInlineImageDataType":{},"insertTableRowType":{},"insertTableRowDataType":{},"insertTextType":{},"insertTextDataType":{},"replaceAllTextType":{},"replaceAllTextDataType":{},"updateParagraphStyleType":{},"updateParagraphStyleDataType":{},"updateTextStyleType":{},"updateTextStyleDataType":{},"internal_gapi_mappings":{},"modelData":{},"processed":{},"insertText":{}}}
I think that this is the reason of your issue.
To:
$desiredRequests = array(new Google_Service_Docs_Request(array(
'insertText' => array(
'text' => 'Hello world!',
'location' => array(
'index' => 25)))));
In this modified script, when $batchUpdateRequests is retrieved, it becomes as follows.
{"requests":[{"insertText":{"text":"Hello world!","location":{"index":25,"segmentId":null}}}]}
In this request body, I could confirm that it worked.
Note:
If an error like Invalid requests[0].insertText: Index 25 must be less than the end index of the referenced segment occurs, please modify 'index' => 25 to 'index' => 1.
Reference:
Method: documents.batchUpdate
I'm using this composer package https://github.com/basvandorst/StravaPHP
The OAUTH is working fine and its generating me the JSON with the access token and user id, etc..
But whenever I try to use other function it returns me 404 not found.
Output is this :
{"token_type":"Bearer","access_token":"077058e0c800881c72a4b10a04a520d5898d4e3e","athlete":{"id":35670467,"username":"amir_do","resource_state":2,"firstname":"Amir","lastname":"Do","city":null,"state":null,"country":null,"sex":"M","premium":false,"summit":false,"created_at":"2018-10-13T13:55:41Z","updated_at":"2018-10-13T13:56:25Z","badge_type_id":0,"profile_medium":"https://lh5.googleusercontent.com/-ku6v9lKNgYY/AAAAAAAAAAI/AAAAAAAAAAA/ABtNlbASj8KhClhwnVYVqRrEG2oiYzWPbA/mo/photo.jpg","profile":"https://lh5.googleusercontent.com/-ku6v9lKNgYY/AAAAAAAAAAI/AAAAAAAAAAA/ABtNlbASj8KhClhwnVYVqRrEG2oiYzWPbA/mo/photo.jpg","friend":null,"follower":null,"email":"goncalomaia97#gmail.com"}}
35670467
Client error: `GET https://www.strava.com/api/athletes/35670467/stats?access_token=077058e0c800881c72a4b10a04a520d5898d4e3e` resulted in a `404 Not Found` response: {"message":"Record Not Found","errors":[{"resource":"resource","field":"path","code":"invalid"}]}
And this is my current callback.php page code:
<?php
include 'vendor/autoload.php';
use Strava\API\Client;
use Strava\API\Exception;
use Strava\API\Service\REST;
session_start();
$client = new GuzzleHttp\Client();
global $connect;
require_once("configs/database.php");
$connect = new mysqli($config['database']['host'],$config['database']['user'],$config['database']['pass'],$config['database']['db']);
$code = $_GET['code'];
$state = $_GET['state'];
$scope = $_GET['scope'];
$user = $_SESSION['username'];
$check = $connect->query("SELECT * FROM users WHERE email = '$user'");
$fetch = $check->fetch_array(MYSQLI_ASSOC);
$apix = $fetch['api'];
$api_secretx = $fetch['api_secret'];
$client = new GuzzleHttp\Client();
$data = [
"client_id" => $apix,
"client_secret" => $api_secretx,
"code" => $code
];
$result = $client->post('https://www.strava.com/oauth/token', ['json' => $data]);
print "<pre>";
print_r( $result->getBody()->getContents() );
print "</pre>";
$bodyb = $result->getBody();
$varx = json_decode((string) $bodyb, true);
$token = $varx['access_token'];
$id = $varx['athlete']['id'];
$_SESSION['token'] = $token;
printf($id);
try {
// REST adapter (We use `Guzzle` in this project)
$adapter = new \GuzzleHttp\Client(['base_uri' => 'https://www.strava.com/api/v3']);
// Service to use (Service\Stub is also available for test purposes)
$service = new \Strava\API\Service\REST($token, $adapter);
// Receive the athlete!
$client = new Client($service);
$athlete = $client->getAthleteStats($id);
print_r($athlete);
} catch(Exception $e) {
print $e->getMessage();
}
$adapter = new \GuzzleHttp\Client(['base_uri' => 'https://www.strava.com/api/v3']);
Change that to this (It should be trailing) :
$adapter = new \GuzzleHttp\Client(['base_uri' => 'https://www.strava.com/api/v3/']);
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.