Uncaught exception 'apiServiceException' with message 'Error calling GET ....' - google-plus

I have a small card game for Google+ which needs the visitor's name, avatar, gender and city.
It works for myself, but in the error_log I see a lot of PHP-exceptions:
[28-Jan-2012 19:06:33] PHP Fatal error: Uncaught exception 'apiServiceException' with message 'Error calling GET https://www.googleapis.com/plus/v1/people/me?alt=json&key=AIzaSyAgQl0UeNM553PfLnPmP0jTtcJ8ZIQ3q0g: (404) Not Found' in /var/www/html/preferans.de/google/google-api-php-client/src/io/apiREST.php:86
Stack trace:
#0 /var/www/html/preferans.de/google/google-api-php-client/src/io/apiREST.php(56): apiREST::decodeHttpResponse(Object(apiHttpRequest))
#1 /var/www/html/preferans.de/google/google-api-php-client/src/service/apiServiceResource.php(151): apiREST::execute(Object(apiServiceRequest))
#2 /var/www/html/preferans.de/google/google-api-php-client/src/contrib/apiPlusService.php(207): apiServiceResource->__call('get', Array)
#3 /var/www/html/preferans.de/google/index.php(33): PeopleServiceResource->get('me')
#4 {main}
thrown in /var/www/html/preferans.de/google/google-api-php-client/src/io/apiREST.php on line 86
Here is my script:
<?php
require_once('google-api-php-client/src/apiClient.php');
require_once('google-api-php-client/src/contrib/apiPlusService.php');
session_start();
$client = new apiClient();
$client->setApplicationName('Video-Preferans');
$client->setClientId('XXX.apps.googleusercontent.com');
$client->setClientSecret('XXX');
$client->setRedirectUri('http://preferans.de/google');
$client->setDeveloperKey('XXX');
$client->setScopes(array('https://www.googleapis.com/auth/plus.me'));
$plus = new apiPlusService($client);
if (isset($_REQUEST['logout']))
unset($_SESSION['access_token']);
if (isset($_GET['code'])) {
$client->authenticate();
$_SESSION['access_token'] = $client->getAccessToken();
header('Location: http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']);
}
if (isset($_SESSION['access_token']))
$client->setAccessToken($_SESSION['access_token']);
if ($client->getAccessToken()) {
$me = $plus->people->get('me'); # XXX line 33 XXX
# the access token may have been updated lazily
$_SESSION['access_token'] = $client->getAccessToken();
} else {
printf('
<!doctype html>
<html>
<head>
<body>
<p>Play Preferans</p>
</body>
</html>
', $client->createAuthUrl());
exit();
}
$viewer_id = $me['id'];
list($first_name, $last_name) = explode(' ', $me['displayName']);
$city = $me['placesLived'][0]['value'];
$female = ($me['gender'] == 'male' ? 0 : 1);
$avatar = $me['image']['url'];
....skipped some html code....
Does anybody please know, why the apiServiceException is being thrown?
Or how and where at least catch it, so that I can debug it better?
I'm using the latest Google+ SDK 0.4.8.3 and also I'm requesting very basic user information and as I've written - it works for me and also for my wife's account.

You can wrap $me = $plus->people->get('me') within a try/catch block.
The plus/v1/people/me API returns a 404 Not Found when the user hasn't registered for Google+, and you can catch this case with the following:
try {
$me = $plus->people->get('me')
} catch (apiServiceException $e) {
// Handle exception. You can also catch Exception here.
// You can also get the error code from $e->getCode();
}

I have the same problem, only difference is I'm trying to use the Calendar API. I get the exact same error response as you did in the first place, tried the try/catch-block and it kind of worked. If I print the error response it says "403", but I also get the JSON-response I want. Do you know why?
my code:
if ($client->getAccessToken()) {
try{
$activities = $plus->activities->listActivities('me', 'public');
print 'Your Activities: <pre>' . print_r($activities, true) . '</pre>';
// The access token may have been updated.
$_SESSION['token'] = $client->getAccessToken();
} catch (apiServiceException $e) {
// Handle exception. You can also catch Exception here.
// You can also get the error code from $e->getCode();
echo $e->getCode();
print_r($activities);
}
}

Related

how to handle error 500 when requesting a distant server with guzzle?

i am requesting a webservice using :
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ConnectException;
try {
$client = new Client();
$response = $client->request('GET', $url); //it crashes at this line
$content = json_decode($response->getBody(), true);
}
catch (ConnectException $e) {
\Drupal::logger('amu_hal')->error('incorrect_url'.$url);
}
today the distant server return a error 500.
How can i modify my code not to crash my site when it happens?
I assume that by distant server you mean a server that takes a long time to connect. You can specify a timeout for the request.
Or perhaps the server returned error 500 and it fails during json_decode? You can check the status code returned by the request.
Or even perhaps the code is failing the line that you indicate but the exception ConnectException is not being caught? Try using Exception as a catch-all to debug this situation.
Instead of using Guzzle directly, I recommend that you use the Drupal wrapper (which uses Guzzle under the hood).
$client = Drupal::httpClient();
$request = $client->get($uri, ['connect_timeout' => 5]);
if ($request->getStatusCode() === 200) {
echo 'Connection Success';
} else {
echo sprintf('Error %d occurred', $request->getStatusCode());
}

How to turn off PDO error message

I am trying to use phpunit to test connection, I already make error_reporting(0) and assign PDO::ATTR_ERRMODE => PDO::ERRMODE_SILENT, but when I give the wrong information on purpose, it always dump error message, for example, if I give the wrong account, it shows
PDOException: SQLSTATE[HY000] [1045] Access denied for user 'test'#'localhost' (us
ing password: YES)
How to turn it off?
$options = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_PERSISTENT => false,
);
$dsn = 'mysql:host=' . $config['host'] . ';dbname=' . $config['database'] . ';charset=utf8';
try {
$this->dbh = new PDO($dsn, $config['username'], $config['password'], $options);
} catch (PDOExeception $e) {
// Do something
}
PDO::__construct will always throw a PDOException if the connection fails. There is nothing you can do about that. Any sane application should throw exception if it fails to connect or maybe you have good reason to explain why you need to turn off exception on connections.
Beside the connection It will work on others transactions.
Example:
<?php
$options = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_SILENT,
PDO::ATTR_PERSISTENT => false,
);
$dsn = 'mysql:host=' . $config['host'] . ';dbname=' . $config['database'] . ';charset=utf8';
try {
//THIS WILL THROW EXECPTION IF FAILED, NO MATTER WHAT ERROR MODE YOU SET
$this->dbh = new PDO($dsn, $config['username'], $config['password'], $options);
} catch (PDOException $e) {
// Do something
}
//JUST SILENT THIS WILL NOT CAUSE EXCEPTION
$dbh->query("SELECT badColumn FROM wrongTable");
?>

PHPMailer does not provide ErrorInfo

I have a problem with PHP Mailer, which is not providing the $mail->ErrorInfo when an error occured.
I tested with the original example from [http://phpmailer.worxware.com/?pg=tutorial#1] as below.
<?php
require("class.phpmailer.php");
$mail = new PHPMailer();
$mail->IsSMTP(); // telling the class to use SMTP
$mail->Host = "smtp.example.com"; // SMTP server
$mail->From = "from#example.com";
$mail->Subject = "First PHPMailer Message";
$mail->Body = "Hi! \n\n This is my first e-mail sent through PHPMailer.";
$mail->WordWrap = 50;
if(!$mail->Send()) {
echo 'Message was not sent.';
echo 'Mailer error: ' . $mail->ErrorInfo;
} else {
echo 'Message has been sent.';
}
?>
I've set the host to my server, modified "from" and "AddAddress" to correct addresses and I've received the test mail as expected. But whhen I change the recipient address to blxxxa#blablaxxxx.de, just to check how the errors will be handled I don't get the error.
$mail->AddAddress("blxxxa#blablaxxxx.de");
I still receive "Message has been sent". Any Idea? Maybe server settings?
Try putting your $mail->Send() into a try-catch block.
try{
// ... Your Setup ...
$mail->Send();
}
catch (phpmailerException $e) {
echo $e->errorMessage(); //PHPMailer error messages
}
catch (Exception $e) {
echo $e->getMessage(); // other error messages
}
if you look at the code of the phpmailer library ( phpmailer library on github search for the public function send() code block )
you'll see that phpmailer throws exceptions in case of failure.
You have some good examples here : http://www.merocode.com/sending-emails-using-phpmailer-via-smtp/
good luck.
ErrorInfo will not contain an error message unless an error happens. It sounds like your mail server is accepting the message without complaining (as would be expected if it's a relay or on localhost), so you need to check your mail server logs and your bounce mailbox since the problem is further upstream from you and thus not visible to PHPMailer.
In short, you're not doing anything wrong, you're just looking in the wrong place.
Provide profer hostname, username and password. for example,
<?php
require("class.phpmailer.php");
$mail = new PHPMailer();
$mail->IsSMTP(); // telling the class to use SMTP
$mail->Host = "mail.example.com"; // SMTP server
$mail->Port = 25; // set the SMTP port for the GMAIL server
$mail->Username = "username"; // SMTP account username example
$mail->Password = "password";
$mail->From = "from#example.com";
$mail->Subject = "First PHPMailer Message";
$mail->Body = "Hi! \n\n This is my first e-mail sent through PHPMailer.";
$mail->WordWrap = 50;
if(!$mail->Send()) {
echo 'Message was not sent.';
echo 'Mailer error: ' . $mail->ErrorInfo;
} else {
echo 'Message has been sent.';
}
?>
In my case PhpMailer causes a warning at $mail->send();
Warning: stream_socket_enable_crypto(): Peer certificate CN=mail.xxx.com' did not match expected CN=mail.yyy.com'
in class.smtp.php on line 368
So imho PhpMailer misses some exception handing here.
In such a case you have the following possibilities:
Create an issue in the ticket system https://github.com/PHPMailer/PHPMailer/issues and hope for an update
add a "#" to the function call #$mail->send(); - which hides the warning, but does not help you further
Work with the PHP buffer to read out the warning.
Update:
In PHPMailer 6.x the warning was removed - but $mail->ErrorInfo does not contain any useful information. All I get is "SMTP connect() failed". Not really an improvement...

refreshTokenWithAssertion Permission Denied

I am trying to use google-api-client in PHP for a project.
I got a "permission denied" response while at this statement:
$client->getAuth()->refreshTokenWithAssertion();
Google_IO_Exception, Message:Failed to connect to 74.125.193.84: Permission denied
File: /home/www/blah.com/restful/libs/Google/IO/Curl.php
Line:81
/home/www/blah.com/restful/libs/Google/IO/Abstract.php(125): Google_IO_Curl->executeRequest(Object(Google_Http_Request))
#1 /home/www/blah.com/restful/libs/Google/Auth/OAuth2.php(326): Google_IO_Abstract->makeRequest(Object(Google_Http_Request))
#2 /home/www/blah.com/restful/libs/Google/Auth/OAuth2.php(306): Google_Auth_OAuth2->refreshTokenRequest(Array)
#3 /home/www/blah.com/restful/v2/index.php(122): Google_Auth_OAuth2->refreshTokenWithAssertion()
I checked all my credentials and they look correct, what could be the problem?
Thanks,
John
code:
$client_id = '1234blahblahblah.apps.googleusercontent.com'; //Client ID
$service_account_name = '1234blahblah#developer.gserviceaccount.com'; //Email Address
$key_file_location = 'blahblah-1234.p12'; //key.p12
$client = new Google_Client();
$client->setApplicationName("test");
$service = new Google_Service_Calendar($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,
array('https://www.googleapis.com/auth/calendar'),
$key
);
print_r($cred);
$client->setAssertionCredentials($cred);
$client->setClientId($client_id);
if($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion(); //<<<<<failed here.
}
$_SESSION['service_token'] = $client->getAccessToken();
echo $_SESSION['service_token'];
}
Hi John I´ve the same problem and finally this works for me:
Before the lines:
if($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion(); //<<<<<failed here.
}
I put a try catch and that returns me that I had a writtin permissions problem:
try {
$client->getAuth()->refreshTokenWithAssertion($cred);
} catch (Exception $e) {
var_dump($e->getMessage());
}
I could do 2 things:
1) Go to Google/src/Config.php and change line 94: 'directory' => sys_get_temp_dir() . '/Google_Client'and change the directory to save cache temp files
2) or like me, made a echo sys_get_temp_dir(); before the try catch and give a chmod 777 permission to that dir
This solution works for me, I hope also for you. Anyway made an try/catch waiting for the exception message
See the service-account.php sample in the examples/ directory of the Google APIs Client Library for PHP on Github.com:
if($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion($cred); // set credentials there
}

google api v3 redirect_uri_mismatch Error

i am try to get google account authentication for my app, but when i choose the account to log in i get the error redirect_uri_mismatch,
at google console i create Client ID for web application
first i try to run the app on local host with the following settings
REDIRECT URIS : http://localhost/myapppath/
but get the same error
also i try to host my app at heroku with the following Client ID for web application settings
but get the same error, i search many times on stackoverflow with no success to find a solution
this is my code, it is a test code to get the uploaded videos of a user
require_once 'Google/Client.php';
require_once 'Google/Service/YouTube.php';
session_start();
/*
* You can acquire an OAuth 2.0 client ID and client secret from the
* Google Developers Console <https://console.developers.google.com/>
* For more information about using OAuth 2.0 to access Google APIs, please see:
* <https://developers.google.com/youtube/v3/guides/authentication>
* Please ensure that you have enabled the YouTube Data API for your project.
*/
$OAUTH2_CLIENT_ID = '42965713xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxercontent.com';
$OAUTH2_CLIENT_SECRET = 'y9AWlbxxxxxxxDqdQwJ';
$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);
$client->setScopes('https://www.googleapis.com/auth/youtube');
$redirect = filter_var('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'],
FILTER_SANITIZE_URL);
$client->setRedirectUri($redirect);
// Define an object that will be used to make all API requests.
$youtube = new Google_Service_YouTube($client);
if (isset($_GET['code'])) {
if (strval($_SESSION['state']) !== strval($_GET['state'])) {
die('The session state did not match.');
}
$client->authenticate($_GET['code']);
$_SESSION['token'] = $client->getAccessToken();
header('Location: ' . $redirect);
}
if (isset($_SESSION['token'])) {
$client->setAccessToken($_SESSION['token']);
}
// Check to ensure that the access token was successfully acquired.
if ($client->getAccessToken()) {
try {
// Call the channels.list method to retrieve information about the
// currently authenticated user's channel.
$channelsResponse = $youtube->channels->listChannels('contentDetails', array(
'mine' => 'true',
));
$htmlBody = '';
foreach ($channelsResponse['items'] as $channel) {
// Extract the unique playlist ID that identifies the list of videos
// uploaded to the channel, and then call the playlistItems.list method
// to retrieve that list.
$uploadsListId = $channel['contentDetails']['relatedPlaylists']['uploads'];
$playlistItemsResponse = $youtube->playlistItems->listPlaylistItems('snippet', array(
'playlistId' => $uploadsListId,
'maxResults' => 50
));
$htmlBody .= "<h3>Videos in list $uploadsListId</h3><ul>";
foreach ($playlistItemsResponse['items'] as $playlistItem) {
$htmlBody .= sprintf('<li>%s (%s)</li>', $playlistItem['snippet']['title'],
$playlistItem['snippet']['resourceId']['videoId']);
}
$htmlBody .= '</ul>';
}
} catch (Google_ServiceException $e) {
$htmlBody .= sprintf('<p>A service error occurred: <code>%s</code></p>',
htmlspecialchars($e->getMessage()));
} catch (Google_Exception $e) {
$htmlBody .= sprintf('<p>An client error occurred: <code>%s</code></p>',
htmlspecialchars($e->getMessage()));
}
$_SESSION['token'] = $client->getAccessToken();
} else {
$state = mt_rand();
$client->setState($state);
$_SESSION['state'] = $state;
$authUrl = $client->createAuthUrl();
$htmlBody = <<<END
<h3>Authorization Required</h3>
<p>You need to authorize access before proceeding.<p>
END;
}
?>
<!doctype html>
<html>
<head>
<title>My Uploads</title>
</head>
<body>
<?=$htmlBody?>
</body>
</html>
What credentials type you choose depends on the application you want to build. 'Client ID for web application' should work fine for you.
The URIs you specify in Redirect URIs have to point to the actual script file, like http://example.com/index.php. I don't think http://example.com is supposed to work.
i found the solution after replacing this line
$redirect = filter_var('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'], FILTER_SANITIZE_URL);
by this
$redirect = 'http://localhost/myappname';
i do not know why it is not working when it take the full path of the redirect class