Google API 클라이언트로 토큰을 새로 고치는 방법은 무엇입니까?


91

Google Analytics API (V3)를 가지고 놀았는데 오류가 발생했습니다. 첫째, 모든 것이 올바르게 설정되고 내 테스트 계정으로 작동합니다. 하지만 다른 프로필 ID (동일한 Google Accont / GA 계정)에서 데이터를 가져 오려면 403 오류가 발생합니다. 이상한 점은 일부 GA 계정의 데이터는 데이터를 반환하고 다른 계정은이 오류를 생성한다는 것입니다.

토큰을 취소하고 한 번 더 인증했는데 이제 모든 계정에서 데이터를 가져올 수있는 것 같습니다. 문제 해결됨? 아니. 액세스 키가 만료되면 동일한 문제가 다시 발생합니다.

내가 제대로 이해했다면 resfreshToken을 사용하여 새로운 authenticationTooken을 얻을 수 있습니다.

문제는 내가 실행할 때입니다.

$client->refreshToken(refresh_token_key) 

다음 오류가 반환됩니다.

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

나는 refreshToken 메서드 뒤에있는 코드를 확인하고 "apiOAuth2.php"파일에 대한 요청을 다시 추적했습니다. 모든 매개 변수가 올바르게 전송됩니다. grant_type은 메소드 내에서 'refresh_token'으로 하드 코딩되어 있으므로 무엇이 잘못되었는지 이해하기가 어렵습니다. 매개 변수 배열은 다음과 같습니다.

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

절차는 다음과 같습니다.

$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

이것은 버그입니까, 아니면 완전히 오해 한 적이 있습니까?


버그인지 여부는 모르지만 현재 원시 CURL http 요청을 사용하여 액세스 토큰을 새로 고치고 있으며 제대로 작동하고 있습니다.
gremo

서치 ... 이거 아직 알아 내셨어요? 여기에도 같은 문제가 있습니다.
Brian Vanderbusch 2012 년

@gremo 여기서 사용한 원시 CURL http 요청을 공유 할 수 있습니까? 정말 도움이 될 것입니다. 감사!
Silver Ringvee 19 년

답변:


76

그래서 나는 이것을하는 방법을 마침내 알아 냈습니다. 기본 아이디어는 인증을 처음 요청할 때받는 토큰이 있다는 것입니다. 이 첫 번째 토큰에는 새로 고침 토큰이 있습니다. 첫 번째 원래 토큰은 한 시간 후에 만료됩니다. 한 시간 후에는 사용 가능한 새 토큰을 얻으려면 첫 번째 토큰의 새로 고침 토큰을 사용해야합니다. $client->refreshToken($refreshToken)새 토큰을 검색하는 데 사용 합니다. 저는 이것을 "임시 토큰"이라고 부를 것입니다. 이 임시 토큰도 저장해야합니다. 한 시간이 지나면 만료되고 연결된 새로 고침 토큰도 없기 때문입니다. 새 임시 토큰을 얻으려면 이전에 사용한 방법을 사용하고 첫 번째 토큰의 refreshtoken을 사용해야합니다. 나는 추악한 코드를 아래에 첨부했지만 이것에 새로운 메신저 ...

//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);

52
3600 초 동안 확인하는 대신 $ client-> isAccessTokenExpired ()를 사용해야합니다.
Gaurav Gupta

2
작은 업데이트. 최신 버전에서 새로 고침 토큰을 요청하면 이제 반환되는 새 액세스 토큰이 새 새로 고침 토큰과 함께 제공됩니다. 따라서 기본적으로 업데이트 된 json 토큰을 사용하여 이전 json 토큰을 대체 할 수 있으며 더 이상 초기 액세스 토큰을 유지할 필요가 없습니다. .
skidadon

1
참고 $client->isAccessTokenExpired()여전히이 토큰이 만료 생각하는지 로컬에서 개최 된 시간을 확인합니다. 토큰은 여전히 ​​만료되었을 수 있으며 로컬 응용 프로그램은 사용할 때만 실제로 알 수 있습니다. 이 경우 API 클라이언트는 예외를 반환 하고 토큰을 자동으로 새로 고치지 않습니다 .
Jason

44

문제는 새로 고침 토큰에 있습니다.

[refresh_token] => 1\/lov250YQTMCC9LRQbE6yMv-FiX_Offo79UXimV8kvwY

가있는 문자열이 '/'get json encoded이면 a 로 이스케이프 '\'되므로 제거해야합니다.

사례의 새로 고침 토큰은 다음과 같아야합니다.

1/lov250YQTMCC9LRQbE6yMv-FiX_Offo79UXimV8kvwY

무엇 난 당신이 한 겠지하면 경우에 때문에 당신이 구글에서 다시 전송 된 JSON 문자열을 인쇄하고 복사 코드에 토큰 붙여 넣은 것입니다 json_decode그 다음이 제대로 제거됩니다 '\'당신을 위해!


1
놀라운 언급, 내 하루를 만들었습니다! 시간 절약!
Mircea Sandu

당신은 내 하루를 구했습니다!
Truong Dang

나는 이것을 100 번 찬성 할 수 있으면 좋겠다. 토큰이 작동하도록 모든 것을 시도한 후 몇 시간 동안 "나쁜 승인"메시지를 쳐다 본 후 키보드로 벽에 구멍을 뚫 으려고했습니다. 망할 구글 맨, 왜 슬래시를 사용합니까?
Askerman 19

17

다음은 토큰을 설정하는 스 니펫입니다. 그 전에 액세스 유형을 오프라인 으로 설정해야합니다.

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

토큰을 새로 고치려면

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

이것은 당신의 토큰을 새로 고칠 것입니다, 당신은 당신이 할 수있는 세션에서 그것을 업데이트해야합니다

 $_SESSION['access_token']= $client->getAccessToken()

1
당신은 이것으로 나의 하루를 만들었습니다 :) 내가 아무데도 가지 않고 많은 시간을
보냈기

16

액세스 유형은로 설정해야합니다 offline. stateAPI의 사용이 아닌 사용자가 직접 사용하도록 설정 한 변수입니다.

최신 버전의 클라이언트 라이브러리 가 있는지 확인 하고 다음을 추가합니다.

$client->setAccessType('offline');

매개 변수에 대한 설명은 URL 형성을 참조하십시오 .


감사합니다 jk. 최신 버전을 다운로드하고 내 계정의 앱에 대한 액세스를 취소했습니다. 그런 다음 한 번 더 액세스 권한을 부여하고 accessToken과 refreshToken을 저장했습니다. 문제는 setAccessType이 생략 된 경우에도 항상 refreshToken을 받았습니다. 어쨌든 $ client-> refreshToken (refresh-token-key)을 실행하면 "invalid_grant"오류가 발생합니다. auth-url을 확인했고 기본값은 "force"입니다. "자동"으로 변경하고 인증 방법을 실행하면 이미 액세스 권한을 부여 했으므로 리디렉션되지 않습니다. 그러나 respons는 새로 고침이없는 accessToken입니다. 어떤 아이디어?
seorch.me

@ seorch.me 이상하게 들리지만 새로 고침 토큰을 사용하려면 새 $client( $client = new apiClient();)를 설정해야 할 수 있습니까?
jk.

1
@ seorch.me 인증하는 동안 새 새로 고침 토큰을 설정 $client->setApprovalPrompt('force')하고 가져와야합니다 $client->setAccessType('offline'). 사용자가 액세스 범위를 승인하도록 강요하지 않고 Google은 이전 새로 고침 토큰을 계속 사용할 것이라고 가정합니다.
Jason

14

@ uri-weg가 올린 답변은 저에게 효과적 이었지만 그의 설명이 명확하지 않았으므로 조금 다시 말하겠습니다.

첫 번째 액세스 권한 시퀀스 동안 콜백에서 인증 코드를받은 지점에 도달 하면 액세스 토큰과 새로 고침 토큰저장 해야합니다 .

그 이유는 google api가 액세스 권한을 요청하는 경우에만 새로 고침 토큰이 포함 된 액세스 토큰을 전송하기 때문입니다. 다음 액세스 토큰은 새로 고침 토큰없이 전송됩니다 ( approval_prompt=force옵션 을 사용하지 않는 경우 ).

처음받은 새로 고침 토큰은 사용자가 액세스 권한을 취소 할 때까지 유효합니다.

단순한 PHP에서 콜백 시퀀스의 예는 다음과 같습니다.

// 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']);

그리고 나중에 단순한 PHP에서 연결 순서는 다음과 같습니다.

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

완벽하고 많이 일했습니다. 내가 말하고 싶은 것은 토큰뿐 아니라 문자열로 json 객체를 전달해야한다고 설명해야한다는 것입니다.
Oliver Bayes-Shelton

@ OliverBayes-Shelton 안녕하세요. 감사. // setAccessToken() expects json충분 하다고 생각했습니다 . 아니면 코드의 다른 부분입니까?
Daishi

이것은 나에게 잘 작동하지만이 코드가 50 개의 토큰 새로 고침 제한을 초과하여 토큰이 만료되는 상황을 처리하는지 알고 있습니까? '토큰 만료'에 대한 자세한 내용은 다음에서 확인할 수 있습니다. developers.google.com/identity/protocols/OAuth2#expiration
Bjorn

최신 2.0 버전은 이제 액세스 토큰 배열에서 새로 고침 토큰을 반환하는 것 같습니다. 즉, 액세스 토큰을 저장하면 새로 고침 토큰이 포함되어 있으므로 새로 고침 토큰도 저장됩니다. 새로 고침 토큰 만료에 대한 응답으로 명시 적으로 테스트하고 처리해야한다고 생각합니다. 50 제한은 "클라이언트 당 사용자 당"입니다. 즉, 클라이언트 당 50 개이므로 특히 다음과 같은 경우에 도달 할 가능성이 낮습니다. 포함 된 범위를 사용하여 토큰을 결합합니다.
Brian C

8

내 프로젝트에서 사용중인 코드는 다음과 같습니다.

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;
}

6

같은 문제가있었습니다. 어제 작동했던 내 대본은 이상한 이유로 오늘은 그렇지 않았습니다. 변화가 없다.

분명히 이것은 내 시스템 시계가 2.5 (!!) 초 떨어져서 NTP와 동기화되어 문제가 해결 되었기 때문입니다.

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


그 대답은 저에게 많은 도움이되었습니다. 당신은 아마 저에게 많은 시간을 절약 할 수있었습니다. 많이! 감사! 방금 sudo apt-get install ntp데비안 컴퓨터에서 NTP를 설치했습니다. 시계를 동기화하고 문제가 해결되었습니다.
Szymon Sadło

4

참고 : 3.0 Google Analytics API는 만료 될 때 새로 고침 토큰이있는 경우 액세스 토큰을 자동으로 새로 고침하므로 스크립트에 refreshToken.

(의 Sign기능 참조 auth/apiOAuth2.php)


"자동으로 새로 고침"이란 getAccessToken ()을 요청하면 새로 고쳐진 것을 다시받을 수 있다는 의미입니까? 하지만 먼저 DB에서 새로 고침 토큰을 설정해야합니다. 그렇지 않으면 새로 고침 토큰 없이도 새로 고침이 작동하며 이것이 작동하지 않을 것이라고 생각합니다
ninsky

4

때때로 새로 고침 토큰을 사용하여 생성하지 않았습니다 $client->setAccessType ("offline");.

이 시도:

$client->setAccessType ("offline");
$client->setApprovalPrompt ("force"); 

좀 더 구체적으로 말하면 새로 고침 토큰이 첫 번째 인증에 포함 된 것 같습니다 . 저장하고 사용하면 새로 고침 토큰이 계속 반환 될 것이라고 믿습니다 (확인되지 ​​않은 다른 사람에 따르면). doco는 또한 새로 고침 토큰이있는 경우 액세스 토큰을 자동으로 새로 고칠 것이라고 말합니다. 즉, 새로 고침 토큰을 안전하게 관리하기 만하면됩니다. setApprovalPrompt ( 'force')는 이후에 새로 고침 토큰을 강제로 발행합니다. 그것 없이는 당신은 다른 것을 얻을 수 없습니다.
Brian C

2

현재 버전의 Google API에서 스마트 코드로 예제를 사용했지만 작동하지 않았습니다. 그의 API가 너무 구식이라고 생각합니다.

그래서 API 예제 중 하나를 기반으로 자체 버전을 작성했습니다. 액세스 토큰, 요청 토큰, 토큰 유형, ID 토큰, 만료 시간 및 생성 시간을 문자열로 출력합니다.

클라이언트 자격 증명과 개발자 키가 올 바르면이 코드가 즉시 작동합니다.

<?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>

1
왜이 줄 : $redirect = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];. 같은 페이지로 리디렉션하는 이유는 무엇입니까? 이것이 필요한가요?
Tropicalista

@Tropicalista : 페이지 자체를 다시로드 할 필요는 없지만 일반적으로 인증 흐름이 구현되는 방식입니다.
John Slegers 2014 년

그러나 액세스 토큰이 만료 된 경우 새 액세스 토큰을 얻기 위해 새로 고침 토큰을 사용하지 않습니다.
apadana

2

초기 인증 요청시 액세스 토큰을 파일 또는 데이터베이스에 json 문자열로 저장하고 액세스 유형을 오프라인으로 설정해야합니다. $client->setAccessType("offline")

그런 다음 후속 API 요청 중에 파일 또는 db에서 액세스 토큰을 가져 와서 클라이언트에 전달합니다.

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

이제 토큰이 만료되었는지 확인해야합니다.

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())

fetchAccessTokenWithRefreshToken()함수는 작업을 수행하고 새 액세스 토큰을 제공하고 파일 또는 데이터베이스에 다시 저장합니다.


1

google / google-api-php-client v2.0.0-RC7 과 동일한 문제가 있으며 1 시간 동안 검색 한 후 다음 과 같이 json_encode를 사용하여이 문제를 해결 했습니다.

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

1

이것은 여기에서 매우 잘 작동합니다. 아마도 누구에게나 도움이 될 수 있습니다.

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

1

이 질문이 처음 게시 된 이후 Google은 몇 가지 사항을 변경했습니다.

다음은 현재 작업중인 예입니다.

    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);
        }
    }


}

1

google-api-php-client v2.2.2를 사용 fetchAccessTokenWithRefreshToken();합니다. 매개 변수없이 if 함수 호출을 사용하여 새 토큰을 얻 습니다. 업데이트 된 액세스 토큰을 반환하고 새로 고친 토큰은 손실되지 않습니다.

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


-1

다음 코드 조각을 사용하여 새로 고침 토큰을 가져옵니다.

    <?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'];
    ?>
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.