Неустранимая ошибка: необработанное исключение "Google_Auth_Exception" с сообщением "Ошибка обновления токена OAuth2, сообщение:" {ошибка: invalid_grant}

У меня есть приложение Prediction, основанное на последней версии клиента Google-api-php 1.0.0. он отлично работает в среде localhost. но когда я развертываю точно такое же приложение в среде сервера хостинга, у меня возникает следующая проблема.

ЭТО ОШИБКА, КОТОРУЮ Я ПОЛУЧИЛ ОТ ХОСТИНГА СРЕДЫ

Fatal error: Uncaught exception 'Google_Auth_Exception' with message 'Error refreshing the OAuth2 token, message: '{ "error" : "invalid_grant" }'' in /home/predict/public_html/predict/Google/Auth/OAuth2.php:335 Stack trace: #0 /home/predict/public_html/predict/Google/Auth/OAuth2.php(294): Google_Auth_OAuth2->refreshTokenRequest(Array) #1 /home/predict/public_html/predict/index.php(40): Google_Auth_OAuth2->refreshTokenWithAssertion(Object(Google_Auth_AssertionCredentials)) #2 {main} thrown in /home/predict/public_html/predict/Google/Auth/OAuth2.php on line 335

*Расширения CURL и JSON корректно работают в среде хостинга.

ЭТО ВЕСЬ МОЙ ИСХОДНЫЙ КОД

<?php
session_start();

set_include_path("Google" . PATH_SEPARATOR . get_include_path());
require_once 'Client.php';
require_once 'Service/Prediction.php';

$client_id              = 'XXXXXXXXXX-uin70k09g5g6f05vqvdj9ch541c4spns.apps.googleusercontent.com';    
$service_account_name   = 'XXXXXXXXXX-uin70k09g5g6f05vqvdj9ch541c4spns@developer.gserviceaccount.com';  
$key_file_location      = 'APPKEY-d333c55a111a.p12';

if ($client_id == 'XXXXXXXXXX-uin70k09g5g6f05vqvdj9ch541c4spns.googleusercontent.com'
    || !strlen($service_account_name)
    || !strlen($key_file_location)) {  
}

$client = new Google_Client();

$client->setApplicationName("Predition App");
$service = new Google_Service_Prediction($client);

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

$key = file_get_contents($key_file_location);
$cred = new Google_Auth_AssertionCredentials(
    $service_account_name,`enter code here`
    array('https://www.googleapis.com/auth/prediction'),
    $key
);

$client->setAssertionCredentials($cred);

if($client->getAuth()->isAccessTokenExpired()) {    
  $client->getAuth()->refreshTokenWithAssertion($cred); 
}

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

// Prediction logic:
$id             = 'datamodel';
$project        = "XXXXXXXXXX";

$input          = $_REQUEST['input'];

//$predictionData = new Google_InputInput();  //Depricated method in Google_api_php_client_version1.0.0      // W.P.Roshan
$predictionData = new Google_Service_Prediction_InputInput();
$predictionData->setCsvInstance(array($input));

//$input = new Google_Input();                //Depricated method in Google_api_php_client_version1.0.0 // W.P.Roshan
$input = new Google_Service_Prediction_Input();
$input->setInput($predictionData);

$PredictionResult = $service->trainedmodels->predict($project,$id, $input,$optParams = array());
//print '<h3>Prediction Result:</h3><pre>' . print_r($result, true) . '</pre>';

$AccuracyMetaResult = $service->trainedmodels->get($project, $id, $optParams = array());    
//print '<h3>Classification Accuracy Result:</h3><pre>' . print_r($result, true) . '</pre>';

$stdout                     = new stdClass();
$stdout->dataModel          = $PredictionResult['id'];
$stdout->outputLabel        = $PredictionResult['outputLabel'];
$stdout->negative           = $PredictionResult['modelData']['outputMulti'][0]['score'];
$stdout->neutral            = $PredictionResult['modelData']['outputMulti'][1]['score'];
$stdout->positive           = $PredictionResult['modelData']['outputMulti'][2]['score'];
$stdout->modelCreated       = $AccuracyMetaResult['created'];
$stdout->trainingCompleted  = $AccuracyMetaResult['trainingComplete'];
$stdout->trainingStatus     = $AccuracyMetaResult['trainingStatus'];
$stdout->modelType          = $AccuracyMetaResult['modelData']['modelInfo']['modelType'];
$stdout->dataModelAccuracy  = $AccuracyMetaResult['modelData']['modelInfo']['classificationAccuracy'];

echo json_encode($stdout);

if ($client->getAccessToken()) {
  $_SESSION['token'] = $client->getAccessToken();
} 

person sunone5    schedule 19.08.2014    source источник
comment
Если ваш хостинг WHM/CPanel попросите их синхронизировать время сервера с сервером времени ( ntp.org — если ваш хостинг использует NTP — сетевой протокол времени), если ваш хостинг находится на VPS Virtuozzo, попросите людей, предоставляющих хостинг, синхронизировать VPS с сервером времени. @DalmTo - БЕЗ ВАШЕЙ ПОДДЕРЖКИ ЭТО НЕ БУДЕТ РЕШЕНО БОЛЬШОЕ СПАСИБО DalmTo.   -  person sunone5    schedule 19.08.2014


Ответы (3)


У меня были часы, когда я пытался решить эту проблему. Оказалось, что время моего сервера опережало время гугла на пару минут.

Установка времени моего сервера на правильное время немедленно устранила эту проблему.

Надеюсь, это кому-то поможет :)

person Joel Spencer    schedule 11.07.2015
comment
Не могли бы вы уточнить. Я тоже установил ntp на свой Linux-компьютер, но не смог понять, как решить проблему. Я также установил время своего местоположения на Азию / Калькутту. - person Bhupender Keswani; 09.10.2015

Я думаю, у вас есть проблема с порядком того, как вы делаете вещи. Вы создаете службу до того, как получите аутентификацию. Это пример использования Google Analytics API.

<?php
session_start();
require_once 'Google/Client.php';
require_once 'Google/Service/Analytics.php';

/************************************************
  The following 3 values an befound in the setting
  for the application you created on  Google 
  Developers console.
  The Key file should be placed in a location
  that is not accessable from the web. outside of 
  web root.

  In order to access your GA account you must
  Add the Email address as a user at the 
  ACCOUNT Level in the GA admin. 
 ************************************************/
$client_id = '1046123799103-nk421gjc2v8mlr2qnmmqaak04ntb1dbp.apps.googleusercontent.com';
$Email_address = '1046123799103-nk421gjc2v8mlr2qnmmqaak04ntb1dbp@developer.gserviceaccount.com';
$key_file_location = '629751513db09cd21a941399389f33e5abd633c9-privatekey.p12';

$client = new Google_Client();
$client->setApplicationName("Client_Library_Examples");

$key = file_get_contents($key_file_location);

// seproate additional scopes with a comma
$scopes ="https://www.googleapis.com/auth/analytics.readonly";  

$cred = new Google_Auth_AssertionCredentials(
    $Email_address,
    array($scopes),
    $key
    );

$client->setAssertionCredentials($cred);
if($client->getAuth()->isAccessTokenExpired()) {
    $client->getAuth()->refreshTokenWithAssertion($cred);
}

$service = new Google_Service_Analytics($client);  
$accounts = $service->management_accountSummaries->listManagementAccountSummaries();

//calulating start date
$date = new DateTime(date("Y-m-d"));
$date->sub(new DateInterval('P10D'));

//Adding Dimensions
$params = array('dimensions' => 'ga:userType');
// requesting the data
$data = $service->data_ga->get("ga:78110423", $date->format('Y-m-d'),  date("Y-m-d"), "ga:users,ga:sessions", $params );


?><html>
<?php echo $date->format('Y-m-d') . " - ".date("Y-m-d"). "\n";?>
<table>
<tr>
<?php
//Printing column headers
foreach($data->getColumnHeaders() as $header){  
    print "<td>".$header['name']."</td>";   
}
?>
</tr>
<?php
//printing each row.
foreach ($data->getRows() as $row) {    
    print "<tr><td>".$row[0]."</td><td>".$row[1]."</td><td>".$row[2]."</td></tr>";  
}

//printing the total number of rows
?>
<tr><td colspan="2">Rows Returned <?php print $data->getTotalResults();?> </td></tr>
</table>
</html>
<?php

?>

Пример взят из моего учебника Google Service Account php.

person DaImTo    schedule 19.08.2014
comment
@DalmTo - если я создаю службу до того, как получу аутентификацию, то почему она правильно работает в среде локального хоста. - person sunone5; 19.08.2014
comment
Сначала необходимо создать Google_Auth_AssertionCredentials, потому что он отправляется $client, а затем служба создается с использованием $client, который имеет свою аутентификацию. Вы делаете это задом наперед - person DaImTo; 19.08.2014
comment
если я делаю это в обратном порядке, почему он работает в среде локального хоста. Кажется, это не имеет значения, приятель ... но хорошая попытка ... спасибо. - person sunone5; 19.08.2014
comment
Вариант № 2: проверьте часы сервера, убедитесь, что они установлены правильно. Он должен быть синхронизирован с NTP. Если это не так, он думает, что что-то не так с вашей аутентификацией, и вы получите invalid_grant. - person DaImTo; 19.08.2014
comment
Да, это приемлемый ответ, но что такое NTP? и как мне синхронизировать время с сервером хостинга. - person sunone5; 19.08.2014
comment
NTP — это протокол сетевого времени для синхронизации часов между компьютерными системами. en.wikipedia.org/wiki/Network_Time_Protocol Какой это тип сервера? Просто проверьте его время, правильное ли оно? Если не установить время. - person DaImTo; 19.08.2014
comment
Давайте продолжим это обсуждение в чате. - person sunone5; 19.08.2014
comment
Я использую код @DaImTo, но у меня та же проблема. Я проверил часы сервера, и они кажутся правильными. Какие-либо предложения? - person user2768; 15.05.2015
comment
Теперь я подписан на developers.google.com/analytics /devguides/reporting/core/v3/, который, похоже, работает. - person user2768; 15.05.2015
comment
DalmTo, да, нужно синхронизировать с NTP :) Большое спасибо мой случай разрешился с этим - person Robin Gomez; 10.09.2015

У меня была такая же ошибка при входе на страницу. Эта ошибка возникает из-за повторной аутентификации.

После успешного входа на свою страницу. В вашем коде проверьте, установлен ли Session. В противном случае он снова будет аутентифицировать пользователя. Вот как я решил свою ошибку. Надеюсь, это сработает и для вас.

if(isset($_GET['code'])){<br>
     if(!isset($_SESSION['token'])){
        $gClient->authenticate($_GET['code']);
        $_SESSION['token'] = $gClient->getAccessToken();
    header('location:'.filter_var($redirectURL,FILTER_SANITIZE_URL));
    }
}
person sam palve    schedule 21.03.2017