twilio catching error does not work - php

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

Related

Microsoft Graph API (Calendar) Intermittent 503 Errors

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.

Square API object creation

I am using the square api to search my orders using the following code:
require '../connect-php-sdk-master/autoload.php';
// Configure OAuth2 access token for authorization: oauth2
SquareConnect\Configuration::getDefaultConfiguration()->setAccessToken('MY_AUTH_CODE');
//settings for the searchOrders
$searchOrdersSettings = ([
'location_ids'=>['MY_LOCATION_ID']
]);
$apiInstance = new SquareConnect\Api\OrdersApi();
$body = new \SquareConnect\Model\SearchOrdersRequest($searchOrdersSettings); // \SquareConnect\Model\SearchOrdersRequest | An object containing the fields to POST for the request. See the corresponding object definition for field details.
try {
$result = $apiInstance->searchOrders($body);
/* echo '<pre>';
print_r($result);
echo '<pre>'; */
} catch (Exception $e) {
echo 'Exception when calling OrdersApi->searchOrders: ', $e->getMessage(), PHP_EOL;
}
I would like to set a created_at start and end date but I have no idea how to create 'An object containing the fields to POST for the request'. Can anyone help me out?
Per the Square PHP SDK documentation, you would need to set the query and filter of the query. You can do something like this (tested and working as a small snippet):
require_once(__DIR__ . '/vendor/autoload.php');
// Configure OAuth2 access token for authorization: oauth2
SquareConnect\Configuration::getDefaultConfiguration()->setAccessToken('ACCESS_TOKEN_HERE');
$apiInstance = new \SquareConnect\Api\OrdersApi();
$body = new \SquareConnect\Model\SearchOrdersRequest();
$body->setLocationIds(['LOCATION_ID_HERE']);
// create query for searching by date
$query = new \SquareConnect\Model\SearchOrdersQuery();
$filter = new \SquareConnect\Model\SearchOrdersFilter();
$date_time_filter = new \SquareConnect\Model\SearchOrdersDateTimeFilter();
$date_time_filter->setCreatedAt([
"start_at" => "2020-03-01T00:00:00Z",
"end_at" => "2020-03-13T00:00:00Z"
]);
//pass the filter and query to the request
$filter->setDateTimeFilter($date_time_filter);
$query->setFilter($filter);
$body->setQuery($query);
try {
$result = $apiInstance->searchOrders($body);
error_log(var_dump($result));
} catch (Exception $e) {
echo 'Exception when calling OrdersApi->searchOrders: ', $e->getMessage(), PHP_EOL;
}

503 Error while trying to send SMS with Twilio

I´m using Twilio PHP API to send mass sms to my customers.
Problem is that i can only send like 80st SMS and then i got a server error:
Failed to load resource: the server responded with a status of 503
(Backend fetch failed)
Well i think this might be the error.
Because i get no success echo echo "Sent message to $name and in the twilio SMS log i can only see that 80 SMS of 200 has been sent.
What can cause this error?
foreach ($usrs as $number => $name) {
try{
$sms = $client->account->messages->create(
// the number we are sending to - Any phone number
$number,
array(
// Step 6: Change the 'From' number below to be a valid Twilio number
'from' => "xxxxxxxxxxx",
// the sms body
'body' => "Hey $name. $text"
)
);
// Display a confirmation message on the screen
echo "Sent message to $name <br>";
}
catch (TwilioException $e) {
die( $e->getCode() . ' : ' . $e->getMessage() );
}
}
Twilio developer evangelist here.
Twilio has a limit of 100 concurrent API requests and will only send 1 message a second. As Ahmed suggested in the comments, I recommend you add a delay between calls to the API if you are sending more than 100 messages.
edit
Adds sleep(1) for each message. This will make the page delay a second after sending each message.
foreach ($usrs as $number => $name) {
try{
$sms = $client->account->messages->create(
// the number we are sending to - Any phone number
$number,
array(
// Step 6: Change the 'From' number below to be a valid Twilio number
'from' => "xxxxxxxxxxx",
// the sms body
'body' => "Hey $name. $text"
)
);
// Display a confirmation message on the screen
echo "Sent message to $name <br>";
sleep(1);
}
catch (TwilioException $e) {
die( $e->getCode() . ' : ' . $e->getMessage() );
}
}

Sending a Dynamic Text to Voice Call without URL Reference

In the Twilio documentation, it states you can send a text to voice call statically like this:
use Twilio\Rest\Client;
$AccountSid = "";
$AuthToken = "";
$client = new Client($AccountSid, $AuthToken);
try {
$call = $client->account->calls->create(
"+15555551234",
"+15555554321",
array("url" => '/twilio/twilio.welcome.message.php')
);
echo "Started call: " . $call->sid;
} catch (Exception $e) {
echo "Error: " . $e->getMessage();
}
I find that to be a little bit much for dynamically created messages. This is fine for static messages. What I want to do is something like this:
use Twilio\Twiml;
$response = new Twiml();
$response->say('Chapeau!', ['voice' => 'woman', 'language' => 'fr']);
$AccountSid = "";
$AuthToken = "";
$client = new Client($AccountSid, $AuthToken);
try {
$call = $client->account->calls->create(
"+phoneNumber",
"+phoneNumber",
array("response" => $response)
);
echo "Started call: " . $call->sid;
} catch (Exception $e) {
echo "Error: " . $e->getMessage();
}
It hints at being able to do this in the documentation, but I can't find it anywhere. I'd be really shocked if there wasn't an easier implementation than creating a php script, to call, and then delete to get this to work. But I've seen worse things in my life.
Twilio developer evangelist here.
I'm afraid there's no way to send TwiML to Twilio to be executed when a call is answered. You still need to send a URL that will respond with TwiML when the call is connected.
However, you can make that URL react dynamically. If you are just sending a message to be read out then you could send the message as a query parameter in the URL and then use that message when the webhook is called. For example:
$message = "Hello! This is a message!";
$call = $client->account->calls->create(
"+15555551234",
"+15555554321",
array("url" => '/twilio/twilio.welcome.message.php?message='.urlencode($message))
);
Then, in your webhook:
<?php
$message = $_REQUEST['message'];
header("Content-type: text/xml");
echo "<?xml version='1.0' encoding='UTF-8'?>\n";
?>
<Response>
<Say><?php echo $message ?></Say>
</Response>
This way, you can dynamically create messages but only host one webhook endpoint.
Let me know if that helps at all.
What about using Twiml bin? This way instead of pointing to your server, you'd have a twilio hosted URL that generates the twiml for you. It supports dynamic variables, looping etc.
see : https://support.twilio.com/hc/en-us/articles/230878368
And then use dynamic variables like this :
<Say>Hello {{CustomerName}}</Say>

PHP, Twilio SMS - capturing twilio's response

I'm trying to do some SMS messages using Twilio, and so far it's pretty straight forward, but I'm using some test data to capture various scenarios and I used "1234567890" as a phone number to capture an error, but I get the following error when I navigate to the page that queries the twilio api:
Fatal error: Uncaught exception 'Twilio\Exceptions\RestException'
with message '[HTTP 404] Unable to fetch record:
The requested resource /PhoneNumbers/1234567890 was not found'
Here's my code:
use Twilio\Rest\Client;
$client = new Client($sid, $token);
if($ph && preg_match('/^[0-9]{10}$/', $ph)) {
//this returns an array containing type, error_code, and a boolean
//value for is_valid.
$response = lookup($client, $ph);
if($response['is_valid']) {
//send the message via twilio.
$message = $client->messages->create(
$ph,
array(
'from' => 'my_twilio_number_goes_here',
'body' => 'text_body_goes_here'
)
);
//handle twilio response
$status = $message->status;
$sid = $message->sid;
}
How can I capture that response?
$twilio = new TwilioClient(env('TWILIO_ACCOUNT_ID'), env('TWILIO_TOKEN'));
$message=new \StdClass;
try
{
//check mobile number is valid or not
$is_valid_number = $twilio->lookups->v1->phoneNumbers($phone_number)->fetch();
if($is_valid_number)
{
$data['From']=env('TWILIO_FROM_ALPHANUMERIC_NAME');
$data['Body']="Sms testing";
$message = $twilio->messages->create($mobile_number, $data);
}
else{
echo "Your Mobile number is not available.";
}
}
catch(\Exception $e)
{
echo $e->getMessage();
}

Categories