Google My Business API - I managed to display all reviews

6.6k views Asked by At

After lots of research and experiments, I was able to display all Google Reviews on my website, the reason to post this question here is, I played with API for the first time, and I have few questions raising on my mind. I am not sure whether my approach is correct or it can be improved further? Whether the code is safe in terms of security-wise too.

The following steps were taken, you might know, we have to do some Prerequisites, which I did.

  1. After getting approval, I tested the API through Google Oauth Playground and managed to get accoundId and locationId. (https://mybusiness.googleapis.com/v4/accounts/{accountId}/locations/{locationId}/reviews)

  2. To implement the reviews on the website, I used the Google PHP Client Library (https://github.com/googleapis/google-api-php-client).

Now let's come on to the main part, to fetch all results we need to add "Access token" at the end of the URL. (https://mybusiness.googleapis.com/v4/accounts/102xxxxxxx/locations/733xxxxxxx/reviews?access_token=xxxxxxxxxx)

Now, the problem was access token gets expired after an hour, to overcome this I generated a refresh token and use the following code. Although I am not sure, whether the refresh token ever gets expired?

<?php
// include your composer dependencies
require_once 'GoogleClientApi/vendor/autoload.php'; // or wherever autoload.php is located

$refreshToken = 'xxxxxxxxxxxx'; // generrated from https://developers.google.com/oauthplayground/
$name = "accounts/xxxxxxx/locations/xxxxxxxx"; // generrated from https://developers.google.com/oauthplayground/

//PHP Client Library 
$client = new Google_Client();

$client->setClientId("xxxxxx"); // generated from Google Cloud Platform
$client->setClientSecret("xxxxx");  // generated from Google Cloud Platform
$client->refreshToken($refreshToken); // as set above in variable.

//Authorization Scopes
//$client->addScope("https://www.googleapis.com/auth/business.manage"); // Not needed probably.

$access_token = $client->getAccessToken(); // confused here...
$client->setAccessToken($access_token); // confused here..

$token = $access_token['access_token'];

$jsonDoc = file_get_contents("https://mybusiness.googleapis.com/v4/accounts/xxxxx/locations/xxxx/reviews?access_token=$token");

$array = json_decode($jsonDoc, true); // when true works as assoc array ?>

print_r($array) // output the JSON formatted reviews.

Now, the questions raised on my mind:

  1. The refresh token which I generated through Googe OAuth playground can get expire? If yes do I have to regenerate the token again through Playground and manually add the codes every time in the file?
  2. These two lines I am confused with. The following code generates a new access token on each page refresh is this normal flow? or is it against any Google Policies or I am just overthinking?
$access_token = $client->getAccessToken(); // confused here...
$client->setAccessToken($access_token); // confused here..
  1. Do I need to store the refresh token or access token in any file or database?
2

There are 2 answers

1
Muhammad Sanaullah On

A refresh token is required to regenerate the access token again. So you have to store Refresh token. Access token expires after one hour while refresh token never expires you can retrieve an access token from refresh token when you need.

5
Linda Lawton - DaImTo On

The issue you are going to have with this code is that every time the refresh token expires you are going to need to authorize it again.

If you are using oauth2 playground the refresh token is probably going to expire quite often. As the playground is only intended for testing purposes.

What you should consider doing is creating a single user system. The code is authorized and then the refresh token is stored in a file in the following example that is called token.json

You will need to authorize this once and then after that it will load the access token by requesting a new one using the refresh token in token.json file.

/**
 * Returns an authorized API client.
 * @return Google_Client the authorized client object
 */
function getClient()
{
    $client = new Google_Client();
    $client->setApplicationName('PHP Quickstart');
    $client->setScopes(Google_Service_Drive::BUSINESS.MANAGE);
    $client->setAuthConfig('credentials.json');
    $client->setAccessType('offline');


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


// Get the API client and construct the service object.
$client = getClient();
$service = new Google_Service_Drive($client);

A few notes from me.

This code will run command like and not in a web browser. I suggest you cache the response you are expecting from the API into a database. Then show the users the response from the database. You can set this code up to run as a cron job every hour if you like but there is really no reason to have it run live for every user. You would probably run out of quote if you tried to. Caching it is a much better option.

Due to some recent change made by google if your app is in the testing phase and has not yet been verified your refresh tokens are only going to be good for at max two weeks. After that the users consent will be revoked and the refresh token will be expired and you will need to authorize it again. So before going to production with this make sure to apply for verification. Explain to google when you go though it that it is a single user script.

enter image description here

I have a video on the verification process that might help. What you need to know about Google verification in 2021.