Bagaimana cara menyegarkan token dengan klien Google API?

92

Saya telah bermain-main dengan Google Analytics API (V3) dan mengalami beberapa kesalahan. Pertama, semuanya sudah diatur dengan benar dan berfungsi dengan akun pengujian saya. Tetapi ketika saya ingin mengambil data dari ID profil lain (Akun Google Accont / GA yang Sama) saya mendapatkan Kesalahan 403. Yang aneh adalah bahwa data dari beberapa akun GA akan mengembalikan data sementara yang lain menghasilkan kesalahan ini.

Saya telah mencabut token dan mengautentikasi sekali lagi, dan sekarang sepertinya saya dapat mengambil data dari semua akun saya. Masalah terpecahkan? Tidak. Karena kunci akses akan kedaluwarsa, saya akan mengalami masalah yang sama lagi.

Jika saya telah memahami semuanya dengan benar, seseorang dapat menggunakan resfreshToken untuk mendapatkan authenticationTooken baru.

Masalahnya adalah, saat saya menjalankan:

$client->refreshToken(refresh_token_key) 

kesalahan berikut dikembalikan:

Error refreshing the OAuth2 token, message: '{ "error" : "invalid_grant" }'

Saya telah memeriksa kode di belakang metode refreshToken dan melacak permintaan kembali ke file "apiOAuth2.php". Semua parameter dikirim dengan benar. Grant_type dikodekan keras menjadi 'refresh_token' dalam metode, jadi sulit bagi saya untuk memahami apa yang salah. Array parameter terlihat seperti ini:

Array ( [client_id] => *******-uqgau8uo1l96bd09eurdub26c9ftr2io.apps.googleusercontent.com [client_secret] => ******** [refresh_token] => 1\/lov250YQTMCC9LRQbE6yMv-FiX_Offo79UXimV8kvwY [grant_type] => refresh_token )

Prosedurnya adalah sebagai berikut.

$client = new apiClient();
$client->setClientId($config['oauth2_client_id']);
$client->setClientSecret($config['oauth2_client_secret']);
$client->setRedirectUri($config['oauth2_redirect_uri']);
$client->setScopes('https://www.googleapis.com/auth/analytics.readonly');
$client->setState('offline');

$client->setAccessToken($config['token']); // The access JSON object.

$client->refreshToken($config['refreshToken']); // Will return error here

Apakah ini bug, atau apakah saya benar-benar salah paham?

seorch.me
sumber
Tidak tahu apakah itu bug atau sesuatu, tetapi saat ini saya menyegarkan token akses menggunakan permintaan http CURL mentah dan berfungsi dengan baik.
gremo
Seorch ... kamu sudah tahu yang ini? Masalah yang sama di sini.
Brian Vanderbusch
@gremo dapatkah Anda membagikan permintaan http CURL mentah yang Anda gunakan di sini? Akan sangat membantu. Terima kasih!
Silver Ringvee

Jawaban:

76

Jadi saya akhirnya menemukan cara untuk melakukan ini. Ide dasarnya adalah Anda memiliki token yang Anda dapatkan saat pertama kali meminta otentikasi. Token pertama ini memiliki token penyegaran. Token asli pertama kedaluwarsa setelah satu jam. Setelah satu jam, Anda harus menggunakan token penyegaran dari token pertama untuk mendapatkan token baru yang dapat digunakan. Anda gunakan $client->refreshToken($refreshToken)untuk mengambil token baru. Saya akan menyebutnya "temp token". Anda perlu menyimpan token temp ini juga karena setelah satu jam, token tersebut juga akan kedaluwarsa dan perhatikan bahwa token penyegaran tidak terkait dengannya. Untuk mendapatkan token temp baru, Anda perlu menggunakan metode yang Anda gunakan sebelumnya dan menggunakan refreshtoken token pertama. Saya telah melampirkan kode di bawah ini, yang jelek, tetapi saya baru dalam hal ini ...

//pull token from database
$tokenquery="SELECT * FROM token WHERE type='original'";
$tokenresult = mysqli_query($cxn,$tokenquery);
if($tokenresult!=0)
{
    $tokenrow=mysqli_fetch_array($tokenresult);
    extract($tokenrow);
}
$time_created = json_decode($token)->created;
$t=time();
$timediff=$t-$time_created;
echo $timediff."<br>";
$refreshToken= json_decode($token)->refresh_token;


//start google client note:
$client = new Google_Client();
$client->setApplicationName('');
$client->setScopes(array());
$client->setClientId('');
$client->setClientSecret('');
$client->setRedirectUri('');
$client->setAccessType('offline');
$client->setDeveloperKey('');

//resets token if expired
if(($timediff>3600)&&($token!=''))
{
    echo $refreshToken."</br>";
    $refreshquery="SELECT * FROM token WHERE type='refresh'";
    $refreshresult = mysqli_query($cxn,$refreshquery);
    //if a refresh token is in there...
    if($refreshresult!=0)
    {
        $refreshrow=mysqli_fetch_array($refreshresult);
        extract($refreshrow);
        $refresh_created = json_decode($token)->created;
        $refreshtimediff=$t-$refresh_created;
        echo "Refresh Time Diff: ".$refreshtimediff."</br>";
        //if refresh token is expired
        if($refreshtimediff>3600)
        {
            $client->refreshToken($refreshToken);
        $newtoken=$client->getAccessToken();
        echo $newtoken."</br>";
        $tokenupdate="UPDATE token SET token='$newtoken' WHERE type='refresh'";
        mysqli_query($cxn,$tokenupdate);
        $token=$newtoken;
        echo "refreshed again";
        }
        //if the refresh token hasn't expired, set token as the refresh token
        else
        {
        $client->setAccessToken($token);
           echo "use refreshed token but not time yet";
        }
    }
    //if a refresh token isn't in there...
    else
    {
        $client->refreshToken($refreshToken);
        $newtoken=$client->getAccessToken();
        echo $newtoken."</br>";
        $tokenupdate="INSERT INTO token (type,token) VALUES ('refresh','$newtoken')";
        mysqli_query($cxn,$tokenupdate);
        $token=$newtoken;
        echo "refreshed for first time";
    }      
}

//if token is still good.
if(($timediff<3600)&&($token!=''))
{
    $client->setAccessToken($token);
}

$service = new Google_DfareportingService($client);
Uri Weg
sumber
52
Alih-alih memeriksa 3600 detik, Anda harus menggunakan $ client-> isAccessTokenExpired ()
Gaurav Gupta
2
Pembaruan kecil. Di versi terbaru, saat Anda meminta token penyegaran, token akses baru yang dikembalikan sekarang hadir dengan token penyegaran baru. Jadi intinya, Anda dapat menggunakan token json yang diperbarui untuk menggantikan token json sebelumnya, dan tidak perlu menyimpan token akses awal lagi. .
skidad
1
Perhatikan bahwa $client->isAccessTokenExpired()masih hanya akan memeriksa waktu yang ditahan secara lokal untuk melihat apakah menurutnya token telah kedaluwarsa. Token mungkin masih kedaluwarsa dan aplikasi lokal hanya akan benar-benar tahu ketika mencoba menggunakannya. Dalam kasus ini, klien API akan mengembalikan pengecualian, dan tidak akan secara otomatis menyegarkan token.
Jason
44

Masalahnya ada pada token penyegaran:

[refresh_token] => 1\/lov250YQTMCC9LRQbE6yMv-FiX_Offo79UXimV8kvwY

Ketika sebuah string dengan '/'get json encoded, itu lolos dengan a '\', maka Anda perlu menghapusnya.

Token penyegaran dalam kasus Anda harus:

1/lov250YQTMCC9LRQbE6yMv-FiX_Offo79UXimV8kvwY

Apa yang saya anggap telah Anda lakukan adalah Anda telah mencetak string json yang dikirim kembali oleh google dan menyalin dan menempelkan token ke dalam kode Anda karena jika Anda json_decodemelakukannya maka itu akan menghapus dengan benar '\'untuk Anda!

Asim
sumber
1
menyebutkan luar biasa, membuat hari saya menyenangkan! jam yang dihemat!
Mircea Sandu
Anda menyelamatkan hari saya!
Truong Dang
Saya berharap saya dapat meningkatkan ini 100 kali. Saya baru saja akan membuat lubang ke dinding dengan keyboard saya setelah menatap pesan "hibah buruk" selama beberapa jam setelah mencoba segalanya untuk membuat token berfungsi. Fricking google man, kenapa menggunakan garis miring, kenapa?
Askerman
18

berikut adalah cuplikan untuk menyetel token, sebelum itu pastikan jenis akses harus disetel ke offline

if (isset($_GET['code'])) {
  $client->authenticate();
  $_SESSION['access_token'] = $client->getAccessToken();
}

Untuk menyegarkan token

$google_token= json_decode($_SESSION['access_token']);
$client->refreshToken($google_token->refresh_token);

ini akan menyegarkan token Anda, Anda harus memperbaruinya dalam sesi untuk yang dapat Anda lakukan

 $_SESSION['access_token']= $client->getAccessToken()
Faishal
sumber
1
Anda membuat hari saya menyenangkan :) terima kasih banyak, jauh lebih sederhana daripada yang saya kira karena saya telah menghabiskan banyak waktu untuk tidak kemana-mana: D
TB Ygg
16

Jenis akses harus disetel ke offline. stateadalah variabel yang Anda setel untuk Anda gunakan sendiri, bukan untuk penggunaan API.

Pastikan Anda memiliki versi terbaru pustaka klien dan tambahkan:

$client->setAccessType('offline');

Lihat Membentuk URL untuk penjelasan tentang parameter.

jk.
sumber
Terima kasih jk. Saya telah mengunduh versi terbaru dan mencabut akses ke aplikasi untuk akun saya. Kemudian saya memberikan akses sekali lagi dan menyimpan accessToken dan refreshToken. Masalahnya, saya selalu diberi refreshToken, bahkan jika setAccessType telah dihilangkan. Bagaimanapun, ketika saya menjalankan $ client-> refreshToken (refresh-token-key), saya masih mendapatkan kesalahan "invalid_grant". Saya telah memeriksa auth-url dan defaultnya adalah "force". Jika saya mengubahnya menjadi "otomatis" dan menjalankan metode otentikasi, saya tidak dialihkan karena saya sudah memberikan akses. Tapi responnya adalah accessToken tanpa refresh. Ada ide?
seorch.me
@ seorch.me Kedengarannya gila, tetapi apakah mungkin Anda harus menyiapkan new $client( $client = new apiClient();) untuk menggunakan token penyegaran?
jk.
1
@ seorch.me Anda harus menyetel $client->setApprovalPrompt('force')serta $client->setAccessType('offline')mendapatkan token penyegaran baru selama otorisasi. Tanpa memaksa pengguna untuk menyetujui cakupan akses, Google berasumsi Anda akan tetap menggunakan token penyegaran yang lama.
Jason
14

Jawaban yang diposting oleh @ uri-weg berhasil untuk saya, tetapi karena saya tidak menemukan penjelasannya yang sangat jelas, izinkan saya mengubah sedikit.

Selama urutan izin akses pertama, dalam panggilan balik, saat Anda mencapai titik di mana Anda menerima kode otentikasi, Anda harus menyimpan token akses dan token penyegaran. juga.

Alasannya adalah google api mengirimi Anda token akses dengan token penyegaran hanya ketika meminta izin akses. Token akses berikutnya akan dikirim tanpa token penyegaran apa pun (kecuali Anda menggunakan approval_prompt=forceopsi tersebut).

Token penyegaran yang Anda terima pertama kali tetap valid sampai pengguna mencabut izin akses.

Dalam php sederhana, contoh urutan panggilan balik adalah:

// init client
// ...

$authCode = $_GET['code'];
$accessToken = $client->authenticate($authCode);
// $accessToken needs to be serialized as json
$this->saveAccessToken(json_encode($accessToken));
$this->saveRefreshToken($accessToken['refresh_token']);

Dan selanjutnya, dalam php yang sederhana, urutan koneksi adalah:

// init client
// ...

$accessToken = $this->loadAccessToken();
// setAccessToken() expects json
$client->setAccessToken($accessToken);

if ($client->isAccessTokenExpired()) {
    // reuse the same refresh token
    $client->refreshToken($this->loadRefreshToken());
    // save the new access token (which comes without any refresh token)
    $this->saveAccessToken($client->getAccessToken());
}
Daishi
sumber
sempurna, banyak bekerja. satu-satunya hal yang akan saya katakan adalah bahwa Anda harus menjelaskan bahwa Anda harus meneruskan objek json bukan hanya token sebagai string.
Oliver Bayes-Shelton
@ OliBay-Shelter Hai. Terima kasih. Saya pikir // setAccessToken() expects jsonsudah cukup. Atau untuk bagian lain dari kode?
Daishi
Ini berfungsi dengan baik untuk saya, tetapi apakah Anda tahu jika kode ini menangani situasi di mana token kedaluwarsa karena melebihi batas 50 penyegaran token? Detail tentang 'Token Expiration' dapat ditemukan di sini: developers.google.com/identity/protocols/OAuth2#expiration
Bjorn
Tampaknya versi 2.0 terbaru sekarang mengembalikan token penyegaran dalam larik token akses. Ini berarti bahwa menyimpan token akses juga menyimpan token penyegaran, karena token penyegaran disertakan. Menanggapi token penyegaran yang kedaluwarsa, saya menduga itu harus diuji dan ditangani secara eksplisit - ingat batas 50 adalah "per pengguna per klien", yaitu 50 per klien sehingga Anda tidak mungkin mencapainya, terutama jika Anda menggunakan cakupan yang disertakan untuk menggabungkan token.
Brian C
8

Berikut adalah kode yang saya gunakan dalam proyek saya dan berfungsi dengan baik:

public function getClient(){
    $client = new Google_Client();
    $client->setApplicationName(APPNAME);       // app name
    $client->setClientId(CLIENTID);             // client id
    $client->setClientSecret(CLIENTSECRET);     // client secret 
    $client->setRedirectUri(REDIRECT_URI);      // redirect uri
    $client->setApprovalPrompt('auto');

    $client->setAccessType('offline');         // generates refresh token

    $token = $_COOKIE['ACCESSTOKEN'];          // fetch from cookie

    // if token is present in cookie
    if($token){
        // use the same token
        $client->setAccessToken($token);
    }

    // this line gets the new token if the cookie token was not present
    // otherwise, the same cookie token
    $token = $client->getAccessToken();

    if($client->isAccessTokenExpired()){  // if token expired
        $refreshToken = json_decode($token)->refresh_token;

        // refresh the token
        $client->refreshToken($refreshToken);
    }

    return $client;
}
Mr_Green
sumber
6

Memiliki masalah yang sama; skrip saya yang bekerja kemarin, untuk beberapa alasan aneh tidak hari ini. Tidak ada perubahan.

Rupanya ini karena jam sistem saya mati selama 2,5 (!!) detik, disinkronkan dengan NTP memperbaikinya.

Lihat juga: https://code.google.com/p/google-api-php-client/wiki/OAuth2#Solving_invalid_grant_errors

strikernl
sumber
Jawaban itu sangat membantuku. Anda mungkin menghemat banyak waktu saya. Banyak! Terima kasih! Saya baru saja mengeksekusi sudo apt-get install ntpdi mesin Debian saya untuk menginstal NTP. Ini menyinkronkan jam dan masalahnya terpecahkan.
Szymon Sadło
4

FYI: API Google Analytics 3.0 akan secara otomatis menyegarkan token akses jika Anda memiliki token penyegaran ketika kadaluwarsa sehingga skrip Anda tidak perlu refreshToken.

(Lihat Signfungsinya di auth/apiOAuth2.php)

Mark Smith
sumber
"Refresh secara otomatis" berarti saya hanya perlu meminta getAccessToken () dan saya akan mendapatkan yang disegarkan kembali? Tapi saya harus mengatur token penyegaran dari DB dulu, bukan? Jika tidak, penyegaran akan bekerja tanpa token penyegaran dan menurut saya ini tidak akan berhasil
ninsky
4

Terkadang Refresh Token yang tidak saya buat dengan menggunakan $client->setAccessType ("offline");.

Coba ini:

$client->setAccessType ("offline");
$client->setApprovalPrompt ("force"); 
Meenu Sharma
sumber
Untuk lebih spesifiknya, sepertinya token Segarkan disertakan dalam otorisasi pertama Anda . Jika Anda menyimpan dan kemudian menggunakannya, saya yakin (menurut orang lain, tidak diverifikasi) bahwa token penyegaran akan terus dikembalikan. Doco juga sekarang mengatakan bahwa mereka akan menyegarkan token akses secara otomatis jika mereka memiliki token penyegaran, yang berarti ini hanya masalah mengelola token penyegaran dengan aman. setApprovalPrompt ('force') memaksa token penyegaran untuk diterbitkan selanjutnya; tanpanya Anda tidak akan mendapatkan yang lain.
Brian C
2

Saya menggunakan contoh dengan smartcode dengan versi Google API saat ini, tetapi yang itu tidak berfungsi. Saya pikir API-nya terlalu ketinggalan jaman.

Jadi, saya baru saja menulis versi saya sendiri, berdasarkan salah satu contoh API ... Ini mengeluarkan token akses, token permintaan, jenis token, token ID, waktu kedaluwarsa, dan waktu pembuatan sebagai string

Jika kredensial klien dan kunci pengembang Anda benar, kode ini seharusnya berfungsi di luar kotak.

<?php
// Call set_include_path() as needed to point to your client library.
require_once 'google-api-php-client/src/Google_Client.php';
require_once 'google-api-php-client/src/contrib/Google_Oauth2Service.php';
session_start();

$client = new Google_Client();
$client->setApplicationName("Get Token");
// Visit https://code.google.com/apis/console?api=plus to generate your
// oauth2_client_id, oauth2_client_secret, and to register your oauth2_redirect_uri.
$oauth2 = new Google_Oauth2Service($client);

if (isset($_GET['code'])) {
    $client->authenticate($_GET['code']);
    $_SESSION['token'] = $client->getAccessToken();
    $redirect = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
    header('Location: ' . filter_var($redirect, FILTER_SANITIZE_URL));
    return;
}

if (isset($_SESSION['token'])) {
    $client->setAccessToken($_SESSION['token']);
}

if (isset($_REQUEST['logout'])) {
    unset($_SESSION['token']);
    $client->revokeToken();
}
?>
<!doctype html>
<html>
    <head><meta charset="utf-8"></head>
    <body>
        <header><h1>Get Token</h1></header>
        <?php
        if ($client->getAccessToken()) {
            $_SESSION['token'] = $client->getAccessToken();
            $token = json_decode($_SESSION['token']);
            echo "Access Token = " . $token->access_token . '<br/>';
            echo "Refresh Token = " . $token->refresh_token . '<br/>';
            echo "Token type = " . $token->token_type . '<br/>';
            echo "Expires in = " . $token->expires_in . '<br/>';
            echo "ID Token = " . $token->id_token . '<br/>';
            echo "Created = " . $token->created . '<br/>';
            echo "<a class='logout' href='?logout'>Logout</a>";
        } else {
            $authUrl = $client->createAuthUrl();
            print "<a class='login' href='$authUrl'>Connect Me!</a>";
        }
        ?>
    </body>
</html>
John Slegers
sumber
1
Silakan, Anda bisa menjelaskan mengapa baris ini: $redirect = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];. Mengapa Anda mengalihkan ke halaman yang sama? apakah ini perlu?
Tropicalista
@ Tropicalista: Tidak perlu memuat ulang halaman itu sendiri, tetapi ini adalah cara alur otentikasi biasanya diterapkan.
John Slegers
tetapi Anda tidak menggunakan token penyegaran untuk mendapatkan token akses baru jika token akses kedaluwarsa.
apadana
2

Anda perlu menyimpan token akses ke file atau database sebagai string json selama permintaan otorisasi awal, dan menyetel jenis akses ke offline $client->setAccessType("offline")

Kemudian, selama permintaan api berikutnya, ambil token akses dari file atau db Anda dan teruskan ke klien:

$accessToken = json_decode($row['token'], true);
$client->setAccessToken($accessToken);

Sekarang Anda perlu memeriksa apakah token telah kedaluwarsa:

if ($client->isAccessTokenExpired()) {
    // access token has expired, use the refresh token to obtain a new one
    $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
    // save the new token to file or db
    // ...json_encode($client->getAccessToken())

The fetchAccessTokenWithRefreshToken()fungsi akan melakukan pekerjaan untuk Anda dan memberikan tanda akses baru, simpan kembali ke file Anda atau database.

Sam Thompson
sumber
1

Saya memiliki masalah yang sama dengan google / google-api-php-client v2.0.0-RC7 dan setelah mencari selama 1 jam, saya menyelesaikan masalah ini menggunakan json_encode seperti ini:

    if ($client->isAccessTokenExpired()) {
        $newToken = json_decode(json_encode($client->getAccessToken()));
        $client->refreshToken($newToken->refresh_token);
        file_put_contents(storage_path('app/client_id.txt'), json_encode($client->getAccessToken()));
    }
Kakek
sumber
1

Ini bekerja dengan sangat baik, mungkin bisa membantu siapa saja:

index.php

session_start();

require_once __DIR__.'/client.php';

if(!isset($obj->error) && isset($_SESSION['access_token']) && $_SESSION['access_token'] && isset($obj->expires_in)) {
?>
<!DOCTYPE html>
<html>
<head>
<title>Google API Token Test</title>
<meta charset='utf-8' />
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script>
search('Music Mix 2010');
function search(q) {
    $.ajax({
        type: 'GET',
        url: 'action.php?q='+q,
        success: function(data) {
            if(data == 'refresh') location.reload();
            else $('#response').html(JSON.stringify(JSON.parse(data)));
        }
    });
}
</script>
</head>
<body>
<div id="response"></div>
</body>
</html>
<?php
}
else header('Location: '.filter_var('https://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']).'/oauth2callback.php', FILTER_SANITIZE_URL));
?>

oauth2callback.php

require_once __DIR__.'/vendor/autoload.php';

session_start();

$client = new Google_Client();
$client->setAuthConfigFile('auth.json');
$client->setAccessType('offline');
$client->setApprovalPrompt('force');
$client->setRedirectUri('https://'.filter_var($_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'], FILTER_SANITIZE_URL));
$client->addScope(Google_Service_YouTube::YOUTUBE_FORCE_SSL);

if(isset($_GET['code']) && $_GET['code']) {
    $client->authenticate(filter_var($_GET['code'], FILTER_SANITIZE_STRING));
    $_SESSION['access_token'] = $client->getAccessToken();
    $_SESSION['refresh_token'] = $_SESSION['access_token']['refresh_token'];
    setcookie('refresh_token', $_SESSION['refresh_token'], time()+60*60*24*180, '/', filter_var($_SERVER['HTTP_HOST'], FILTER_SANITIZE_URL), true, true);
    header('Location: '.filter_var('https://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']), FILTER_SANITIZE_URL));
    exit();
}
else header('Location: '.filter_var($client->createAuthUrl(), FILTER_SANITIZE_URL));
exit();

?>

client.php

// https://developers.google.com/api-client-library/php/start/installation
require_once __DIR__.'/vendor/autoload.php';

$client = new Google_Client();
$client->setAuthConfig('auth.json');
$client->setAccessType('offline');
$client->setApprovalPrompt('force');
$client->addScope(Google_Service_YouTube::YOUTUBE_FORCE_SSL);

// Delete Cookie Token
#setcookie('refresh_token', @$_SESSION['refresh_token'], time()-1, '/', filter_var($_SERVER['HTTP_HOST'], FILTER_SANITIZE_URL), true, true);

// Delete Session Token
#unset($_SESSION['refresh_token']);

if(isset($_SESSION['refresh_token']) && $_SESSION['refresh_token']) {
    $client->refreshToken($_SESSION['refresh_token']);
    $_SESSION['access_token'] = $client->getAccessToken();
}
elseif(isset($_COOKIE['refresh_token']) && $_COOKIE['refresh_token']) {
    $client->refreshToken($_COOKIE['refresh_token']);
    $_SESSION['access_token'] = $client->getAccessToken();
}

$url = 'https://www.googleapis.com/oauth2/v1/tokeninfo?access_token='.urlencode(@$_SESSION['access_token']['access_token']);
$curl_handle = curl_init();
curl_setopt($curl_handle, CURLOPT_URL, $url);
curl_setopt($curl_handle, CURLOPT_CONNECTTIMEOUT, 2);
curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl_handle, CURLOPT_USERAGENT, 'Google API Token Test');
$json = curl_exec($curl_handle);
curl_close($curl_handle);

$obj = json_decode($json);

?>

action.php

session_start();

require_once __DIR__.'/client.php';

if(isset($obj->error)) {
    echo 'refresh';
    exit();
}
elseif(isset($_SESSION['access_token']) && $_SESSION['access_token'] && isset($obj->expires_in) && isset($_GET['q']) && !empty($_GET['q'])) {
    $client->setAccessToken($_SESSION['access_token']);
    $service = new Google_Service_YouTube($client);
    $response = $service->search->listSearch('snippet', array('q' => filter_input(INPUT_GET, 'q', FILTER_SANITIZE_SPECIAL_CHARS), 'maxResults' => '1', 'type' => 'video'));
    echo json_encode($response['modelData']);
    exit();
}
?>
pengguna1768700
sumber
1

Google telah membuat beberapa perubahan sejak pertanyaan ini pertama kali diposting.

Berikut adalah contoh pekerjaan saya saat ini.

    public function update_token($token){

    try {

        $client = new Google_Client();
        $client->setAccessType("offline"); 
        $client->setAuthConfig(APPPATH . 'vendor' . DIRECTORY_SEPARATOR . 'google' . DIRECTORY_SEPARATOR . 'client_secrets.json');  
        $client->setIncludeGrantedScopes(true); 
        $client->addScope(Google_Service_Calendar::CALENDAR); 
        $client->setAccessToken($token);

        if ($client->isAccessTokenExpired()) {
            $refresh_token = $client->getRefreshToken();
            if(!empty($refresh_token)){
                $client->fetchAccessTokenWithRefreshToken($refresh_token);      
                $token = $client->getAccessToken();
                $token['refresh_token'] = json_decode($refresh_token);
                $token = json_encode($token);
            }
        }

        return $token;

    } catch (Exception $e) { 
        $error = json_decode($e->getMessage());
        if(isset($error->error->message)){
            log_message('error', $error->error->message);
        }
    }


}

sumber
1

Saya menggunakan google-api-php-client v2.2.2 Saya mendapatkan token baru dengan fetchAccessTokenWithRefreshToken();panggilan fungsi if tanpa params, ia mengembalikan token akses yang diperbarui dan token yang diperbarui tidak hilang.

if ($client->getAccessToken() && $client->isAccessTokenExpired()) {
    $new_token=$client->fetchAccessTokenWithRefreshToken();
    $token_data = $client->verifyIdToken();
}    
Igor Burlov
sumber
0

gunakan cuplikan kode berikut untuk mendapatkan token penyegaran Anda

    <?php

    require_once 'src/apiClient.php';
    require_once 'src/contrib/apiTasksService.php';

    $client = new apiClient();
    $client->setAccessType('offline');
    $tasksService = new apiTasksService($client);

    $auth = $client->authenticate();
    $token = $client->getAccessToken();
    // the refresh token
    $refresh_token = $token['refresh_token'];
    ?>
Aymen Mouelhi
sumber
0

Menurut Otentikasi di google: OAuth2 terus mengembalikan 'invalid_grant'

"Anda harus menggunakan kembali token akses yang Anda peroleh setelah otentikasi pertama yang berhasil. Anda akan mendapatkan kesalahan invalid_grant jika token Anda sebelumnya belum kedaluwarsa. Simpan dalam cache di suatu tempat sehingga Anda dapat menggunakannya kembali."

semoga membantu

Jon
sumber