2

I'm trying to create a Laravel API to interact with Gmail via the Google API client library for PHP. However, I encounter issues with the endpoint to get mails.

So far, I could do authorization and get the access token in my DB. This endpoint return JSON of this format:

{
    "user_id": 1,
    "token": {
        "access_token": "ya29.XXXXXXXXXXXX-K_P9Z0Rd0nU5WzSvU3TMlC0TZQRbMLkDHE1XI3j29mbIRP13dt_NGMb4d9trTECGKiwbjM45Ijk7fbhpLzU2JL7w-6w_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
        "expires_in": 3599,
        "scope": "https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/gmail.readonly",
        "token_type": "Bearer",
        "id_token": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-yK6GHPRATk64GaPcYCuIVyqTYNNvfvr8gCVuTCKr3RMtUz5J97ROZkJRN5w_AQvyJFL369MNTnHQAiqJoPIN2Wes0OAbeq1urpDRMRaAfF6Nuqun-pmewI8g5OCjkUMqekZTKlzCqRl7Xkm4qQRrwk66SxwGdC78Iy5Z_3VG1OIj681zoY18dQu9_ZqGMnwVuHmffmzNInuAmqHcQ7CLM_I_vJbWV3-UKVRF2UtjHvmUydCdo4PrEpL371i8exwPme5IK_xMcywxdfdjxm4duyv6X_ky2MCYwANNBSyBLMYh214FZPowL8choHmMIms-biJlg",
        "created": 1647922921
    },
    "name": "gmail",
    "updated_at": "2022-03-22T04:22:01.000000Z",
    "created_at": "2022-03-22T04:22:01.000000Z",
    "id": 10
}

My second endpoint is to get the mails by using the access token.

My implementation looks like this.

    // Services
    public function getEMails($user_id, $access_token){
        $this->client->setAccessToken($access_token);
        $service = new Gmail($this->client);
        $messages = $service->users_messages->listUsersMessages($user_id);
        return $messages;
    }
   // Controller
    public function getMails(WebService $web_service, GmailServices $gmail_services){
        $access_token = $web_service->token['access_token'];
        $user_id = 'me';
        if (isset($access_token)){
            $mails = $gmail_services->getEMails($user_id, $access_token);
        }
        return $mails;
    }
  // api.php (In route middleware)
  Route::get('/web-service/{mails}', [WebServiceController::class, 'getMails'])->name('web-service.getMails');

Hitting this endpoint, I get the below error.

"message": "Trying to access array offset on value of type null", "exception": "ErrorException"

which corresponds to this line $access_token = $web_service->token['access_token'];

I did some minor research, but I couldn't resolve it. Unfortunately, I'm not advanced in Laravel development, and I'll appreciate any help and feedback.

Furthermore, I equally want to add that my implementation is largely based on Bitfumes test-driven API development on YouTube. Here is the link to the repo https://github.com/bitfumes/laravel-test-driven-api

Thanks!

After trying the above, I was expecting to get the mails and equally work on pagination or querying via LIMIT so that the backend will not over-stress to get all mails at once.

16
  • 1
    My first question would be why are you storing the access token in the database? Its going to expire in an hour. My second question would be to ask why you haven't posted your authorization code. if your properly setting Google_Client it should be handling all that for you. Commented Mar 22, 2022 at 7:52
  • 1
    Consider providing a minimal reproducible example including your authorization code. Commented Mar 22, 2022 at 8:27
  • Hello @DaImTo, I'm planning to do a refresh of the access token as I proceed. And I equally exchange my authorization code to get a the access token and other details as you saw. The auth code is of this format to be precise ({ "code":"4/0AX4XXXXXXXXXXXXXXX2y2i-blXDoofX00zrLo3QDCoDSLlBpvwXcK6SA" }) Commented Mar 22, 2022 at 8:50
  • The authorization code only lasts five minutes and can only be used once again why bother? Commented Mar 22, 2022 at 8:53
  • 1
    @ARMELFOPA that is not the definition of a minimal reproducible example Commented Mar 22, 2022 at 9:43

1 Answer 1

0

Everything you do should be going though the Google_Client object. Your code is a little confusing to me you have two getEMails methods and neither appear to be using assigning things properly though the client.

When properly initialized it is able to handle everything for you.

$client = new Google_Client();
$client->setApplicationName('Gmail API PHP Quickstart');
$client->setScopes(Google_Service_Gmail::GMAIL_READONLY);
$client->setAuthConfig('credentials.json');
$client->setAccessType('offline');
$client->setPrompt('select_account consent');

You should be testing if the access token has expired. If it is expired then have the Google_Client request a new one.

 if ($client->isAccessTokenExpired()) {
        // Refresh the token if possible, else fetch a new one.
        if ($client->getRefreshToken()) {
            $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
        } else {
           // request access of the user if it has not been granted.
        }
        // note after refresh remember to store the new refresh token.
    }
Sign up to request clarification or add additional context in comments.

6 Comments

The first method, getEmails is in the Services directory, and contains the logic for getting the mails. The getMails is in the controller and if you did notice it calls getEmails in the services together with the user_id and access token as param...
I still dont undrstand why you are bothering with $web_service->token['access_token'];. Once the refresh token is set in the client let it handle the access token. Just pass the service around to your other methods. You are getting a null exception becouse it doesnt exist print the full object you will see its not there so its not going to work
The $web_service->token['access_token'] was a way for me to get the access token. I did a dd() and I noticed it was null, reason why I got the error: "message": "Trying to access array offset on value of type null", "exception": "ErrorException". I hardcoded the token in the setAccessToken method and I could have results. Earlier on I sent a github repo and thesame implementation was working, I'm trying to figure out why it's not working for me and I'm also looking for a better way to pass my access token, refreshing the token is however not my problem
As a reminder, I'm trying to build this as an API that can be called by any frontend app, reason why the implementation slightly deviate from what you see in the doc or other PHP tuts
You are right @DalmTo, I'm working on that as well
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.