Microsoft Graph API (Calendar) Intermittent 503 Errors - php

This code sometimes works, but frequently runs for ~20s then fails with the "503 Service Unavailable" message when I call getPage(). The authentication/token request seems to be working fine.
I can't seem to identify any pattern of when it fails/succeeds. I don't believe it's a throttling error, as there is no "Retry-After" header returned, and the script only runs once per day at night with <200 records returned. I've also tried removing the $filter and changing parameter order as described here, with no clear benefit.
Can someone please help find the cause here? Happy to share any additional info. Any help is much appreciated, thanks!
<?php
define('DEBUG', true);
session_start();
// set config vars
$ms_url_base = "https://login.microsoftonline.com/d3523db7-f84a-4a24-a815-cd4ba4691c9c";
$ms_client_id = '<client id>';
$ms_redirect_uri = "https://example.com/path";
$ms_scope = "calendars.readwrite user.read";
$ms_client_secret = '<secret>';
$ms_auth_endpoint = '/oauth2/v2.0/authorize';
$ms_token_endpoint = '/oauth2/v2.0/token';
$query_numdays = 100;
if (DEBUG) error_reporting(E_ALL);
date_default_timezone_set("America/Detroit");
require_once __DIR__.'/vendor/autoload.php';
use Microsoft\Graph\Graph;
use Microsoft\Graph\Model;
class EventMod extends \Microsoft\Graph\Model\Event {
// custom functions here
public function getNextLink() {
parent::getNextLink();
}
}
class ResponseMod extends \Microsoft\Graph\Http\GraphResponse {}
// authorization
$provider = new Stevenmaguire\OAuth2\Client\Provider\Microsoft([
'clientId' => $ms_client_id,
'clientSecret' => $ms_client_secret,
'redirectUri' => $ms_redirect_uri,
'urlAuthorize' => $ms_url_base.$ms_auth_endpoint,
'urlAccessToken' => $ms_url_base.$ms_token_endpoint,
'urlResourceOwnerDetails' => 'https://graph.microsoft.com/v2.0/me',
]);
if (!isset($_GET['code'])) {
$options = ['scope' => $ms_scope, 'aud' => 'Graph'];
$authUrl = $provider->getAuthorizationUrl($options);
$_SESSION['oauth2state'] = $provider->getState();
header('Location: '.$authUrl);
exit;
} elseif (empty($_GET['state']) || ($_GET['state'] !== $_SESSION['oauth2state'])) {
unset($_SESSION['oauth2state']);
exit('Invalid state');
} else {
try {
$token = $provider->getAccessToken('authorization_code', ['code' => $_GET['code']]);
} catch (League\OAuth2\Client\Provider\Exception\IdentityProviderException $e) {
exit ("Get access token exception: ".$e->getMessage());
}
if (DEBUG) {
echo 'Access Token: ' . $token->getToken() . "<p>";
echo 'Refresh Token: ' . $token->getRefreshToken() . "<p>";
echo 'Expired in: ' . $token->getExpires() . "<p>";
echo 'Already expired? ' . ($token->hasExpired() ? 'expired' : 'not expired') . "<p>";
}
// start calendar query
$start=new DateTimeImmutable("yesterday 0:0:1");
$end = $start->add(new DateInterval("P".$query_numdays."D"));
$url='/me/calendarview'
.'?startdatetime='.$start->format('c')
.'&enddatetime='.$end->format('c')
.'&$filter=isOrganizer+eq+false'
.'&$select=subject,responseStatus,start,categories'
.'&$orderby=start/dateTime';
$graph = new Graph;
$graph->setAccessToken($token->getToken());
$data = array();
try {
$iterator = $graph->createCollectionRequest("GET", $url)
->setReturnType(EventMod::class)
->addHeaders(["Prefer" => 'outlook.timezone="America/Detroit"'])
->setPageSize(25);
do {
$page = $iterator->getPage(); /*************** THIS IS WHERE THE EXCEPTION HAPPENS ************/
if (DEBUG) echo "<pre>".print_r($page, true)."</pre>";
$data = array_merge($data, $page);
} while (!$iterator->isEnd());
}
catch (\Microsoft\Graph\Exception\GraphException $e) {
if (DEBUG) echo "GraphException Message: ".$e->getMessage();
exit;
}
catch (Exception $e) {
if (DEBUG) echo "Unk Exception getting data: ".$e->getMessage();
exit;
}
if (DEBUG) print_r($data);
}
?>
composer.json
{
"require": {
"microsoft/microsoft-graph": "^1.29",
"stevenmaguire/oauth2-microsoft": "^2.2"
}
}

I played with your above API call and i ended up noticing the issue - in the case of having bigger larger dates and lot of data at my end (not with smaller time window or less records). It tells me that the failure is due to the client timeout. We need to understand that Calendar view is an expensive operation that too when you deal with calendars and filters added to it. So i went ahead in this scenario, reduce/minimize time window for calendar view by client so smaller segments of time are scanned for matching calendar events. It helped me to get the records as i expected and make use of effective usage of Calendarview API call too.

Apparently the issue was not in the code at all. I discovered that the 503 error was thrown only when a specific date's events were being read by the API. One of the events was rather large and I deleted it; after this the script works well.
This particular event has 16536 attendees listed, which I believe was the source of the error. Still unexplained is why the error was intermittent. I was eventually able to get graph explorer to successfully read the event, so perhaps the bug is in the Microsoft Graph SDK for PHP. I will post there to see if the devs want to capture this error condition.

Related

Using the Facebook PHP-SDK, I cannot access individual videos

I am having a weird issue. Every time I try to read a specific video from FB, it tells me:
(#100) type must be one of the following values: tagged, uploaded
Which is odd, as the access token in this case IS ME, and I uploaded the video, so I SHOULD be able to read the data.
when I hit "/me/videos/uploaded" it returns a list of my videos, with the correct id's (I thought maybe I was using the wrong value).
here is the quick and dirty I am using to test
public function fbtestAction() {
$code = $this->params()->fromQuery('code');
$state = $this->params()->fromQuery('state');
$fb = new \Facebook\Facebook([
'app_id' => [add_id],
'app_secret' => [app_secret],
'default_graph_version' => 'v2.5',
]);
$helper = $fb->getRedirectLoginHelper();
if(!$code) {
$permissions = ['user_videos'];
$loginUrl = $helper->getLoginUrl('http://test.local/fbtest', $permissions);
die("<a href='$loginUrl'>clickity</a>");
} else {
try {
$accessToken = $helper->getAccessToken();
$fb->setDefaultAccessToken($accessToken);
} catch(Facebook\Exceptions\FacebookResponseException $e) {
echo 'Graph returned an error: ' . $e->getMessage();
exit;
} catch(Facebook\Exceptions\FacebookSDKException $e) {
echo 'Facebook SDK returned an error: ' . $e->getMessage();
exit;
} finally {
echo '<pre>';
//var_dump($fb->get('/me'));
var_dump($fb->get('/me/videos/uploaded'));
//var_dump($fb->get('/videos/[video_id]'));
echo '</pre>';
die;
}
}
}
`
Reading comprehension for the win. The proper endpoint is "/[video_id]" not "/videos/[video_id]"

Facebook SDK 5 php: "Graph returned an error: Unsupported post request."

Facebook post to page, SDK 5 php.
Like the titel says, "Graph returned an error: Unsupported post request." I can't figure out why I'm getting it, tried every tip I've found both here on Stackoverflow and other websites.
I've tried to change settings in the app and page, tried small changes in the code, diffrent tokens and so on. Any tips on how I should proceed?
session_start();
include ('../assets/db_conn.php');
require_once __DIR__ . '/FacebookSDK/src/Facebook/autoload.php';
include('fbData.php');
$fb = new Facebook\Facebook($fbData);
$access_token = '**';
//////////*DB CONNECTIONS HERE*////////Took it away to make the code cleaner
$pages = $getFbPages->fetchAll();
$params = array();
$params["message"] = 'test1';
$params["link"] = 'http://***.se';
$params["picture"] = 'https://www.****.com/WNI01_14-Logo-275x63.png';
$params["description"] = 'testar en beskrivning';
foreach ($pages as $page) {
$pageID = $page['pageId'];
// post to Facebook
try {
// Returns a `Facebook\FacebookResponse` object
$response = $fb->post('/'.$pageID.'/feed', $params, $access_token);
} catch(Facebook\Exceptions\FacebookResponseException $e) {
echo 'Graph returned an error: ' . $e->getMessage();
exit;
} catch(Facebook\Exceptions\FacebookSDKException $e) {
echo 'Facebook SDK returned an error: ' . $e->getMessage();
exit;
}
$graphNode = $response->getGraphNode();
}
error is due to your domain name or call back URL that you provided in App creation but may be you are testing on any other URL. Your testing URl must be sub domain or any other related to your domain

twilio catching error does not work

I am implementing twilio in my laravel 5 application. To use it in the framework I use aloha/laravel-twilio integration.
Sending a valid request with test-credentials works fine. I have problems when I want to implement an error-handling.
For some reason the catch does not get the error, which results in a crash of the app. The error seems to be in the twilio-sdk if I read the error message correctly.
Here is what I've done so far:
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
use Aloha\Twilio\TwilioInterface;
class Activation extends Model {
protected $fillable = array( 'a', 'b', 'c');
public static function send() {
// Testaccount
// $toNumber = '+15005550006'; // valid number; works fine
$toNumber = '+15005550001'; // #todo will throw an exeption, and breaks the app
try {
\Twilio::message( $toNumber, 'Pink Elephants and Happy Rainbows');
} catch ( Services_Twilio_RestException $e ) {
elog( 'EACT', $e->getMessage( ) , __FUNCTION__ ); // this is not called when an twilio error occurs
}
}
}
This results in the following error:
Whoops, looks like something went wrong.
Services_Twilio_RestException in /path/to/my/laravel/vendor/twilio/sdk/Services/Twilio.php line 297
Exception_message: The 'To' number +15005550001 is not a valid phone number.
From the documentation this error (not valid phone numer) shall be thrown, but I should have a possiblity to catch and process it. Currently, this does not work. I do not get the error catched...
How can I get the twilio-errors catched and processed?
The class is in a namespace, so I have to reference the absolut class exception - \Services_Twilio_RestException - in the catch .
It works with this code:
try {
\Twilio::message( $toNumber, 'Pink Elephants and Happy Rainbows');
} catch ( \Services_Twilio_RestException $e ) {
elog( 'EACT', $e->getMessage( ) , __FUNCTION__ );
}
See below which is valid as of today. TwilioException is not valid and neither is Services_Twilio_RestException. You should use Exception instead.
UPDATE
You need to import Twilio\Exceptions\TwilioException for TwilioException to work.
My use case is I had to send to a database of numbers and not have an invalid phone number break my script. We did some work-around a month or two ago which involved logging when a message was sent and had a cron job checking where we left off every two minutes... not efficient when you're sending tens of thousands of text messages.
require_once '../Twilio/autoload.php'; // Loads the library
use Twilio\Rest\Client;
//some test fail numbers
$arr = array(1234567890,"11855976lend1",321619819815,198198195616516);
/* ==================================================================================
//create a function to send SMS using copilot (uses an SID instead of a phone number)
================================================================================*/
function sendSMS($to){
// Download the PHP helper library from twilio.com/docs/php/install
// These vars are your accountSid and authToken from twilio.com/user/account
$account_sid = 'xxx';
$auth_token = 'xxx';
$client = new Client($account_sid, $auth_token);
//this nifty little try/catch will save us pain when we encounter bad phone numbers
try{
$client->messages->create(
$to,
array(
'messagingServiceSid' => "MGxxx",
'body' => "This is the body we're sending."
)
);
//sent successfully
echo "sent to $to successfully<br>";
}catch(Exception $e){
echo $e->getCode() . ' : ' . $e->getMessage()."<br>";
}
}
foreach($arr as &$value){
sendSMS($value);
}
//remember to unset the pointer so you don't run into issues if re-using
unset($value);
Today (19-May-2017) the code is like this :
// Step 1: set our AccountSid and AuthToken from https://twilio.com/console
$AccountSid = "XXX";
$AuthToken = "XXX";
$client = new Client($AccountSid, $AuthToken);
try {
$sms = $client->account->messages->create(
// the number we are sending to - Any phone number
$number,
array(
// Step 2: Change the 'From' number below to be a valid Twilio number
// that you've purchased
'from' => "+XXXXXXXXXXX",
// the sms body
'body' => $sms
)
);
// Display a confirmation message on the screen
echo "Sent message to $name";
} catch (TwilioException $e) {
die( $e->getCode() . ' : ' . $e->getMessage() );
}
This is what worked for me:
$twilioCli = new \Twilio\Rest\Client(config('app.twilioAccountSID'), config('app.twilioAuthToken'));
try {
$twilioCli->messages->create(
$formattedToNum,
[
'from' => config('app.twilioFromNumber'),
'body' => "sms body goes here"
]
);
}
catch (\Twilio\Exceptions\RestException $e) {
echo "Error sending SMS: ".$e->getCode() . ' : ' . $e->getMessage()."\n";
}

Google Analytics PHP API - Error (403) Access Not Configured

I have been Googling this for going on hours now. I have followed the Hello Analytics tutorial.
The application runs fine until the user has granted permission from the Google 'consent screen' at which point i receive the following error:
There wan a general error : Error calling GET My url
(403) Access Not Configured. Please use Google Developers Console to
activate the API for your project.
I have checked in the developer console and Analytics API is enabled and, after reading other posts on this, have added Google+ and Drive access.
NOTE: I am running this application locally and redirecting the redirecting back to 127.0.0.1.
I have added my code below for reference although I think the issue is to do with my google console account and / or running this application locally.
Appreciate any help with this guys. Please let me know if any further information is required.
==================================================================================
// --------------------- Google libraries
require_once 'google-api-php-client/src/Google_Client.php';
require_once 'google-api-php-client/src/contrib/Google_AnalyticsService.php';
session_start();
// --------------------- Application credentials
$client = new Google_Client();
$client->setApplicationName('Interim Testing Tool');
$client->setClientId('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com');
$client->setClientSecret('xxxxxxxxxxxxxxxxxxxxxxxx');
$client->setRedirectUri('http://127.0.0.1');
$client->setDeveloperKey('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
$client->setScopes(array('https://www.googleapis.com/auth/analytics.readonly'));
// Returns objects from the Analytics Service instead of associative arrays.
$client->setUseObjects(true);
// --------------------- Client access checks
// Handle authorization flow from the server
if (isset($_GET['code'])) {
$client->authenticate();
$_SESSION['token'] = $client->getAccessToken();
$redirect = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
header('Location: ' . filter_var($redirect, FILTER_SANITIZE_URL));
}
// Retrieve and use stored credentials if set
if (isset($_SESSION['token'])) {
$client->setAccessToken($_SESSION['token']);
}
if (!$client->getAccessToken()) {
// CLient not logged in create a connect button
$authUrl = $client->createAuthUrl();
print "<a class='login' href='$authUrl'>Connect Me!</a>";
} else {
$analytics = new Google_AnalyticsService($client);
runMainDemo($analytics);
}
//-------------------------------------------------------------- Run main demo
function runMainDemo($analytics) {
try {
// Get the user's first view (profile) ID.
$profileId = getFirstProfileId($analytics);
if (isset($profileId)) {
// Query the Core Reporting API.
$results = getResults($analytics, $profileId);
// Output the results.
printResults($results);
}
} catch (apiServiceException $e) {
// Error from the API.
print 'There was an API error : ' . $e->getCode() . ' : ' . $e->getMessage();
} catch (Exception $e) {
print 'There wan a general error : ' . $e->getMessage();
}
}
// ------------------------------------------------------------------ Get first profile id
function getFirstprofileId($analytics) {
$accounts = $analytics->management_accounts->listManagementAccounts();
if (count($accounts->getItems()) > 0) {
$items = $accounts->getItems();
$firstAccountId = $items[0]->getId();
$webproperties = $analytics->management_webproperties->listManagementWebproperties($firstAccountId);
if (count($webproperties->getItems()) > 0) {
$items = $webproperties->getItems();
$firstWebpropertyId = $items[0]->getId();
$profiles = $analytics->management_profiles->listManagementProfiles($firstAccountId, $firstWebpropertyId);
if (count($profiles->getItems()) > 0) {
$items = $profiles->getItems();
return $items[0]->getId();
} else {
throw new Exception('No views (profiles) found for this user.');
}
} else {
throw new Exception('No webproperties found for this user.');
}
} else {
throw new Exception('No accounts found for this user.');
}
}

Khan Academy PHP Oauth Code

Im really struggling w/ the OAuth for Khan Academy. This is for my class website (Im a teacher) and I want to pull in user data on particular students. If I could do the OAUTH I would be fine. Im using PHP.
There seems to be many librarys out there, I have been playing w/ Google Oauth (located here http://code.google.com/p/oauth-php/source/browse/trunk/example/client/twolegged.php)
I can formulate the token request fine, although when I call it in the script, it seems like it tries to redirect to another page and gets blocked there.
http://myonlinegrades.com/prealg/khan/oauth-php/example/client/twoleggedtest.php
Im really struggling - Id love any help you might offer.
Code below:
<?php
include_once "../../library/OAuthStore.php";
include_once "../../library/OAuthRequester.php";
// Test of the OAuthStore2Leg
// uses http://term.ie/oauth/example/
$key = '*********';//'<your app's API key>';
$secret = '***********';//'<your app's secret>';
$callBack = "http://myonlinegrades.com/prealg/test2.php5";
$url = 'http://www.khanacademy.org/api/auth/request_token';
$options = array('consumer_key' => $key, 'consumer_secret' => $secret);
OAuthStore::instance("2Leg", $options);
$method = "GET";
//$params = null;
$params = array(oauth_consumer_key => $key,oauth_callback=>$callBack);
try
{
// Obtain a request object for the request we want to make
$request = new OAuthRequester($url, $method, $params);
// Sign the request, perform a curl request and return the results,
// throws OAuthException2 exception on an error
// $result is an array of the form: array ('code'=>int, 'headers'=>array(), 'body'=>string)
$result = $request->doRequest();
$response = $result['body'];
if ($response != 'oauth_token=requestkey&oauth_token_secret=requestsecret')
{
echo 'Error! $response ' . $response;
}
else
{
}
var_dump($response);
}
catch(OAuthException2 $e)
{
echo "Exception" . $e->getMessage();
}
?>
Not sure this is what you're looking for, but I put together a simple example of doing oAuth with Khan Academy using the Temboo SDK: take a look at https://github.com/matthewflaming/temboo-experiments/tree/master/KhanAcademyOauth
(Full disclosure: I work at Temboo)

Categories