Ejecución script de prueba de API

Introducción

Cerrar todas las sesiones en Google y habilitar solamente la correspondiente a los proyectos.

Acceder a https://console.developers.google.com/

* Crear o seleccionar un proyecto
* Buscar y habilitar las siguientes apis:
+ Drive
+ Sheets
+ Apps Script

Definir credenciales en https://console.developers.google.com/

Desde la opción credenciales:
* Ir a “Consentimiento de Oauth”: Completar email y nombre del producto
* Ir a “Credenciales”: Definir id de cliente de OAuth. Tipo de aplicación Otro (posteriormente utilizaremos Aplicación Web), en la descripción podemos poner por ejemplo: Google API Quickstart.
* La misma credencial debería servir para cualquier API.
* Descargar la credencial al directorio de trabajo y renombrarla como “client_secret.json”

Instalar librerías vía Composer

https://getcomposer.org/download/

Situarse en el directorio del proyecto desde la terminal y ejecutar:

php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('SHA384', 'composer-setup.php') === '544e09ee996cdf60ece3804abc52599c22b1f40f4323403c44d44fdfdd586475ca9813a858088ffbc1f233e9b180f061') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"
php composer.phar require google/apiclient:^2.0 

Se instalarán las librerías en el directorio “vendor/”

quickstart.php

* Copiar ejemplo https://developers.google.com/drive/v3/web/quickstart/php
* Copiar ejemplo https://developers.google.com/sheets/api/quickstart/php
* Ejecutar php quickstart.php
* Si se realiza un script para combinar ejemplos, recordar que la constante SCOPES debe definirse con ambos servicios

Detalle quickstart.php

Constantes

CREDENTIALS_PATH: Path hacia las credenciales en el home del usuario, se definen la primera vez que se ejecuta el script, a través de una URL de autenticación provista por el script
CLIENT_SECRET_PATH: Path hacia la identificación OAuth del ciente que se descarga desde la web una vez realizados los pasos de configuración
SCOPES: Se espeficican los servicios a los cuales se desea acceder y los permisos de acceso.

getClient()

Define una instancia de Google_Client a partir de las constantes definidas.
Si aún no se encuentran definidas las credenciales del usuario, proporciona la url de autorización que será almacenada en el directorio CREDENTIALS_PATH.

La autorización se define en base a los SCOPES definidos, por lo tanto, si se cambian los SCOPES, debe eliminarse el archivo definido en CREDENTIALS_PATH y volver a ejecutar el script para definir uno nuevo que permita acceder a los nuevos SCOPES.

Si no está definido el CREDENTIALS_PATH, llama al método Google_Client->createAuthUrl() para definir una URL de autorización.

/**
 * 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;
}
expandHomeDirectory($path)

La ruta pasada como parámetro se asocia al path del home del usuario.
Si mi usuario es /home/usuario y el parámetro es ./credentials/drive-php-quickstart-json, entonces como resultado se define /home/usuario/credentials/drive-php-quickstart-json

Acceso Web

_getClient.php

Definir un cliente para acceder a la API.

require_once __DIR__ . '/vendor/autoload.php';
session_start(); // el codigo de autorizacion (se almacenara directamente en una variable de sesion, en vez de un directorio)

define('APPLICATION_NAME', 'Drive API PHP Quickstart');
define('CLIENT_SECRET_PATH', __DIR__ . '/client_secret.json');
define('SCOPES', implode(' ', array(
  Google_Service_Drive::DRIVE)
));
define("REDIRECT_URI", 'http://' . $_SERVER['HTTP_HOST'] . '/auth.php');

$client = new Google_Client();
$client->setAuthConfig(CLIENT_SECRET_PATH);
$client->setRedirectUri(REDIRECT_URI); //el codigo de autorizacion es procesado en la URI indicada 
$client->addScope(SCOPES);
login.php
require_once '_getClient.php';
< div >
  < a href='< ? = $client - >createAuthUrl() ?>'>Autorizar< /a>
< /div>
_authClient.php

Utilizar el cliente de google para procesar código de autorización y almacenar token definido en una variable de sesión

require_once '_getClient.php';
if (isset($_GET['code'])) {
  $token = $client->fetchAccessTokenWithAuthCode($_GET['code']);
  $_SESSION['upload_token'] = $token;
  header('Location: descargarArchivo.php');
}
authorizeClient.php

Verificar si existe token de autorización y cargarlo al cliente de conexión, si no existe redirige a la página de login.

El check debe ser incluido cada vez que se acceda a una API.

require_once '_getClient.php';

if (!empty($_SESSION['upload_token'])) {
 $client->setAccessToken($_SESSION['upload_token']);
 if ($client->isAccessTokenExpired()) {
  unset($_SESSION['upload_token']);
  echo 'La sesion expiro. Volver a comenzar';
  die;
 }
}
descargarArchivo.php
require_once '_getClient.php';
require_once '_authClient.php';

$file = 'Mi archivo';

$service = new Google_Service_Drive($client);
$files = $service->files->listFiles([
 'q' => "name='" . $file . "'",
 'fields' => 'files(id,size)'
 ]);
if ( count($files) < 1 ) {
 echo 'No se encontro el archivo :(';
 die;
}
$fileId = $files[0]->id;
$fileSize = intval($files[0]->size);
$http = $client->authorize();
$fp = fopen($file, 'w');
$chunkSizeBytes = 1 * 1024 * 1024;
$chunkStart = 0;
while ($chunkStart < $fileSize) {
 $chunkEnd = $chunkStart + $chunkSizeBytes;
 $response = $http->request(
  'GET',
  sprintf('/drive/v3/files/%s', $fileId),
  [
   'query' => ['alt' => 'media'],
   'headers' => [
       'Range' => sprintf('bytes=%s-%s', $chunkStart, $chunkEnd)
   ]
  ]
  );
  $chunkStart = $chunkEnd + 1;
  fwrite($fp, $response->getBody()->getContents());
 }
 fclose($fp);
echo 'Archivo disponible en: "'.realpath($file).'"';

Errores comunes

appNotAuthorizedToFile

Se está queriendo ejecutar una acción sin los permisos adecuados (verificar si en la constante SCOPES se están definiendo los permisos correspondientes para la acción que se requiere)

{
 "error": {
  "errors": [
   {
    "domain": "global",
    "reason": "appNotAuthorizedToFile",
    "message": "The user has not granted the app 431378287880 read access to the file 1rwm_xF8nQPayZe8eLxLzNY4g3rHi6iUExs0uBcXve9mg8i1apSWW0whsCJl5.",
    "locationType": "header",
    "location": "Authorization"
   }
  ],
  "code": 403,
  "message": "The user has not granted the app 431378287880 read access to the file 1rwm_xF8nQPayZe8eLxLzNY4g3rHi6iUExs0uBcXve9mg8i1apSWW0whsCJl5."
 }
}

Links

Google MIME types

Fuente

https://developers.google.com/drive/v3/web/quickstart/php
https://developers.google.com/sheets/quickstart/php
https://academy.leewayweb.com/como-acceder-a-google-drive-usando-php/