asimlqt / php-google-spreadsheet-client

A PHP library for accessing and manipulating Google Spreadsheets
Other
543 stars 154 forks source link

Can't connect to Magento 1.9.2.2 #131

Closed adamphh closed 8 years ago

adamphh commented 8 years ago

Hi there, I tried to use your lib to put Order information from Magento to Google Spreadsheets but it's impossible. It always shows error "Access token is invalid". Could you please let me know what is the $accessToken value? How to get $accessToken? Thank you!

ootri commented 8 years ago

We use this library within Magento (1.9.2.2) to insert order data into Google Sheets and it's been working flawlessly for over a year now. There's nothing special or different with using this in Magento, other than you'll need to be careful with the compilation process (you can use it, but you'll have to make some tweaks). You'll need to setup a google service account and give it edit privileges to your spreadsheet. This page is a great reference: Using OAuth 2.0 for Server to Server Applications

Here's basically our code for getting the access token:

$clientId = '';
$appName = '';
$serviceAccountName = '';
$keyFile = ''; //key.p12

$client = new Google_Client();
$client->setClientId($clientId);
$client->setApplicationName($appName);
$cred = new Google_Auth_AssertionCredentials(
    $serviceAccountName,
    array(  'https://www.googleapis.com/auth/calendar',
            'https://spreadsheets.google.com/feeds',
            'https://docs.google.com/feeds'),
            file_get_contents($keyFile)
    );
if (isset($_SESSION['service_token'])) $client->setAccessToken($_SESSION['service_token']);
$client->setAssertionCredentials($cred);
if ($client->getAuth()->isAccessTokenExpired()) $client->getAuth()->refreshTokenWithAssertion($cred);
$_SESSION['service_token'] = $client->getAccessToken();
$obj_token = json_decode($client->getAccessToken());
$accessToken = $obj_token->access_token;

This is quite condensed and it's not actually the code we use, but pretty close.

Inside Magento we observe the event 'sales_order_save_after' and add the order number to a queue to process later (the customer/user shouldn't have to wait for this to run, especially if it fails). Then we setup a cron to run every 5 minutes which checks to see if any orders are in the queue. From there it's pretty easy, but we do have a verification method to check to see if the data was actually inserted into the spreadsheet because it could fail. We also add order information to a Google Calendar which is why we have 'https://www.googleapis.com/auth/calendar' above.

Feel free to let me know if you need any other help getting it working.

adamphh commented 8 years ago

Hi Ootri, Thank you for your reply. Could you please explain more details of the code? How can I get the $appName and $serviceAccountName?

adamphh commented 8 years ago

Hi Ootri, I already get AccessToken via code below but when I use the xample code, it always shows the problem: Error refreshing the OAuth2 token, message: '{ "error" : "invalid_grant" }'

$client_id = '831939097204-snsg7p0ed3esm4bj8c6dljfh23mfpbmv.apps.googleusercontent.com'; $client_secret = 'lF_Sb5nb3fuzBkqX4OaHgToK'; $redirect_uri = Mage::app()->getStore()->getUrl('simple/glogin/user',array('_secure'=>true)); $client = new Google_Client(); $client->setClientId($client_id); $client->setClientSecret($client_secret); $client->setRedirectUri($redirect_uri); $client->addScope("https://www.googleapis.com/auth/drive"); $service = new Google_Service_Drive($client); $coreSession = Mage::getSingleton('core/session');

    if ($this->getRequest()->getParam('logout')) {
        $coreSession->unset('spreadsheet_token');
    }

    if ($code = $this->getRequest()->getParam('code')) {
        $client->authenticate($code);
        $coreSession->setData('spreadsheet_token', $client->getAccessToken());
    }
    if ($coreSession->getData('spreadsheet_token')) {
        $client->setAccessToken($coreSession->getData('spreadsheet_token'));
    } else {
        $authUrl = $client->createAuthUrl();
        try{
            header('Location: '.$authUrl);
        } catch(Exception $e) {
            print_r($e->getMessage());die('error');
        }
    }
$token = json_decode($coreSession->getData('spreadsheet_token'), true);

$accessToken = $token['access_token'];
    if ($client->getAuth()->isAccessTokenExpired()) $client->getAuth()->refreshToken($accessToken);
    $serviceRequest = new Google_Spreadsheet_DefaultServiceRequest($accessToken);
    Google_Spreadsheet_ServiceRequestFactory::setInstance($serviceRequest);
    $spreadsheetService = new Google_Spreadsheet_SpreadsheetService();
    $spreadsheetFeed = $spreadsheetService->getSpreadsheets();
ootri commented 8 years ago

I would recommend setting up a service account as described [here](Using OAuth 2.0 for Server to Server Applications). I don't see a reason to setup everything in a controller like you're doing unless it's for testing, but even then you'll still want a server to server app.

asimlqt commented 8 years ago

@adammagestore

Have you managed to resolve this?

You need to add the following scope: https://spreadsheets.google.com/feeds I think that's why you're getting "Access token is invalid"