Twilio Call disconnects after one ring - twilio

Twilio calls gets automatically disconnect after one ring. When it's the case for cell phone, everything works just fine but for the landline having ring back-tone the call gets disconnected after one ring. I have checked the call logs; and the status for each call was completed but the duration of each call was 3sec.
This is the code that I have wrote:
$sid = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
$token = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
$twilio = new Client($sid, $token);
$call = $twilio->calls
->create("+1XXXXXXX", // to
"+1XXXXXX", // from
[
"twiml" => "<Response><Say>Hi, A new order has been made by a customer!</Say></Response>"
]
);

Related

Twilio Redirecting the wrong call when using CallSid and trying to update live call

So here's the logic of what I am working on:
Someone calls my Twilio Number I use the dial twiml to forward to a cell phone
I use gather and play a whisper to the operator answering the phone (so his cell phone).
The operator has a choice - press 1 to accept, press 2 (transfers to
a different agent).
step 3 is where I am having trouble I am using the code below:
$call = $twilio->calls($CallSid)
->update([
"method" => "POST",
"url" => "http:www.example.com/directcall.php"
]
);
Here's the problem it is modifying the call but it's redirecting the operators phone number instead of the person who is calling in. So the operator is getting redirected to the other operator and the customer is being hung up on. I tried using the parentcallsid too but that doesn't seem to work either.
Any ideas what I am doing wrong?
so just to be clear I want the flow to work like this:
Customer calls phone number -> redirects to designated operator -> if designated operator presses 2 it redirects the customer to operator 2 and disconnects operator 1 from the call. Is this possible?
Thanks for the help, I greatly appreciate it.
UPDATE PLEASE FIND THE CODE SAMPLES BELOW
Index.php
<?php
include ("config.php");
require_once './vendor/autoload.php';
use Twilio\TwiML\VoiceResponse;
$response = new VoiceResponse();
$twilionumber = ltrim($_POST['To'], '+');
$callernumber=ltrim($_POST['From'], '+');
createCall($phonenumbertouse,$response,$twilionumber);
echo $response;
function createCall($phonenumbertouse,$response,$twilionumber) {
$dial = $response->dial('',['timeout' => '30']);
$dial->number($phonenumbertouse, ['action' => "http://example.com/whisper.php",'method' => 'GET']);
}
WHISPER.PHP
<?php
include ("config.php");
require_once './vendor/autoload.php';
use Twilio\TwiML\VoiceResponse;
$response = new VoiceResponse();
$gather = $response->gather(['action' => "http://example.com/route.php",
'method' => 'GET']);
$gather->say($whisper, ['voice' => 'woman', 'language' => 'en-US']);
echo $response;
?>
route.php
<?php
include ("config.php");
require_once './vendor/autoload.php';
use Twilio\TwiML\VoiceResponse;
use Twilio\Rest\Client;
$response = new VoiceResponse();
$keyedInput=$_REQUEST['Digits'];
$mycallsid=$_REQUEST['ParentCallSid'];
if ($keyedInput == 1){
$response->say('connecting the call');
}
elseif ($keyedInput == 2){
$twilio = new Client($sid, $token);
$call = $twilio->calls($mycallsid)
->update([
"method" => "POST",
"url" => "http://example.com/redirect.php"
]
);
}
elseif ($keyedInput == 3){
$response->say('you selected 3');
}
else {
$response->say('Sorry, I don\'t understand that choice.');
}
echo $response;
?>
**Redirect.php **
<?php
include ("config.php");
require_once './vendor/autoload.php';
use Twilio\TwiML\VoiceResponse;
$response = new VoiceResponse();
$dial = $response->dial('+14151234567',['timeout' => '30']);
echo $response;
?>
Twilio developer evangelist here.
Your issue here is that you are using the wrong CallSid to update.
In this case there are two CallSids at play. When your user dials in to your Twilio number, that call between the user and Twilio has one CallSid. Then, when Twilio creates an outbound call to the operator, that call has a different CallSid.
In your application, when you get the <Gather> response from the operator, the CallSid being sent to your endpoint is the CallSid of the operator's call leg. Instead, you need to find the CallSid of the original call.
You should find that the ParentCallSid parameter is sent to the webhook endpoint as well. That ParentCallSid is the original inbound call's Sid and is what you should use to redirect the caller to another operator.
Edit
OK, so I had a go at building this. I don't normally work in PHP, so I wrote this in Node.js (as Twilio Functions). I got it to work and the answer still seems to me to be "use the ParentCallSid, so hopefully it gives you some idea where you might have gone wrong.
The incoming call
This makes an outbound call to my cell phone number, with a url set to make the whisper to me when I answer the call.
exports.handler = function (context, event, callback) {
const twiml = new Twilio.twiml.VoiceResponse();
const dial = twiml.dial();
dial.number({ url: "/whisper" }, MY_CELL_PHONE_NUMBER);
callback(null, twiml);
};
<Response>
<Dial><Number url="/whisper">MY_CELL_PHONE_NUMBER</Number></Dial>
</Response>
The whisper
This returns a <Gather> spoken to the person answering the cell phone number. It offers a choice, dial "1" to connect or "2" to hang up, triggering the original caller to dial to another number.
exports.handler = function (context, event, callback) {
const twiml = new Twilio.twiml.VoiceResponse();
const gather = twiml.gather({ digits: 1, action: "/after-whisper" });
gather.say("Dial 1 to connect, dial 2 to hang up.");
callback(null, twiml);
};
<Response>
<Gather action="/after-whisper" digits="1">
<Say>Dial 1 to connect, dial 2 to hang up.</Say>
</Gather>
</Response>
The Gather action "/after-whisper"
This checks the Digits parameter. If it is "1" it immediately calls back with an empty response, signalling the end of the whisper and leading the call to connect with the original caller.
If the Digits parameter is not "1" then we initialise a Twilio client and make a request to the API to update the call with the sid ParentCallSid to a new URL. Once that is complete we return TwiML that says to <Hangup> the whisper call (which wasn't strictly necessary, but I like the intention).
exports.handler = async function (context, event, callback) {
const twiml = new Twilio.twiml.VoiceResponse();
if (event.Digits === "1") {
callback(null, twiml);
} else {
const client = context.getTwilioClient();
try {
// Update the parent call with a new URL.
await client.calls(event.ParentCallSid).update({
url: URL_TO_NEXT_TWIML,
});
} catch (error) {
console.log(error);
}
twiml.hangup();
callback(null, twiml);
}
};
The next TwiML
This is the endpoint that the url above relates to, when it gets the callback it just returns a <Dial> to another number, though it could include another whisper and go round this loop again if desired.
exports.handler = async function (context, event, callback) {
const twiml = new Twilio.twiml.VoiceResponse();
twiml.dial(NEXT_NUMBER_TO_DIAL);
callback(null, twiml);
};
<Response>
<Dial>NEXT_NUMBER_TO_DIAL</Dial>
</Response>

Twilio Device Setup - Registers, Connects to TWiML App, but won't accept calls

Am trying to setup a soft phone in browser, via TWiML app.
I created the following:
A page on my own server which serves TWiML to dial a number, say '+11111111111'.
A TWiML app which points to that page
A Twilio number which points to that app.
A page on my server which creates a Twilio Device associated with the app and buttons to run device.connect() or device.register()
The device is setup correctly, as I can register and connect with no errors.
The app works - the phone rings at +111 when I press "Call Using Twilio" button on the TWiML app page, when I call the number pointing to the TWiML app, and when I press the button on my own page. Yay!
What I cannot figure out:
How to answer the phone using the Twilio Device.
The device registers with no issue, so why doesn't it get incoming calls?
How to call other numbers aside from the one in my app.
I did in device.connect({params: {To: '+2222222222'}}), why doesn't it call that number?
Here are all the relevant pages:
calls.pug:
doctype html
html(lang="en")
head
meta(charset="utf-8")
title Browser Calls
body
input#call(type="submit" value="call")
input#register(type="submit" value="register")
pre
script(src="/js/twilio-sdk/twilio.js")
script(type="module" src="/js/calls.js")
[client] calls.js
const $ = css => document.querySelector(css);
const echo = msg => $('pre').innerText += msg + "\n";
var device;
async function setupDevice(){
let data = await fetch('/token/new');
data = await data.json();
device = new Twilio.Device(data.token);
device.on("error",
err => echo("Twilio.Device Error: " + err.message));
echo ('Device setup complete.')
}
$('#register').addEventListener('click', async e => {
if (!device) await setupDevice();
device.on("registered", conn =>
echo('Ready to accept incoming calls.')
);
device.on("incoming", call =>
echo('Incoming call to device')
);
device.register()
});
$('#call').addEventListener('click', async e => {
if (!device) await setupDevice();
let params = { To: '+22222222222' }
device.connect({ params })
});
[node] token.js
const express = require('express');
const router = express.Router();
const AccessToken = require('twilio').jwt.AccessToken;
const VoiceGrant = AccessToken.VoiceGrant;
const config = require('../config');
router.get('/new', function (req, res) {
const accessToken = new AccessToken(
config.accountSid, config.apiKey, config.apiSecret, {identity: 'SG'}
);
const grant = new VoiceGrant({
outgoingApplicationSid: config.appSid,
incomingAllow: true,
});
accessToken.addGrant(grant);
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify({ token: accessToken.toJwt() }));
});
module.exports = router;
Twilio developer evangelist here.
How to answer the phone using the Twilio Device.
The device registers with no issue, so why doesn't it get incoming calls?
To direct a call to the Device, you need to return TwiML that <Dial>s the <Client> with the ID of your access token ("SG" in this case).
So, if you want calls to your Twilio number to be directed to this client you should update the Twilio number's incoming webhook to point to a URL that returns this:
<Response>
<Dial>
<Client>
<Identity>SG</Identity>
</Client>
</Dial>
</Response>
How to call other numbers aside from the one in my app.
I did in device.connect({params: {To: '+2222222222'}}), why doesn't it call that number?
Currently, it sounds like you point the Device to a TwiML app that responds with static TwiML that dials your example number '+11111111111'. To use the parameters, you will need to make that TwiML dynamic, by returning it from your Node server instead. The parameters are sent to the TwiML endpoint, so you can then use them in the response.
Here is an example Express endpoint that would work for you:
const express = require('express');
const router = express.Router();
const { VoiceResponse } = require("twilio").twiml;
const config = require('../config');
router.use(express.urlencoded({ extended: false }));
router.post("/call", function(res, res) {
const To = req.body;
const twiml = new VoiceResponse();
const dial = twiml.dial({ callerId: config.twilioNumber });
dial.number(To);
res.set("Content-Type", "text/xml");
res.send(twiml.toString());
});
module.exports = router;

Not recieving sms using twilio notify service, no debug error in console?

I am trying to send bulk SMS using Twilio notify API. I had looked at the documentation, and other StackOverflow resources but did not find the issue yet. What I am doing is:
$sid = "AC1e590cbb8eee064c3c71axxxxxxxxxxx";
$token = "94c2dc3e2e407c4ebd28cxxxxxxxxxxx";
$twilio = new Client($sid, $token);
$serviceSid = "IS32913ae9b083b809b1c06xxxxxxxxxxx";
$recipients = array();
foreach($phone_nos as $phone_no) {
array_push($recipients, $phone_no['phone_no']);
}
//recipients array print value is
//Array
//(
//[0] => +923105653361
//[1] => +923491457062
//)
$binding = array();
foreach ($recipients as $recipient) {
$binding[] = '{"binding_type":"sms", "address":"'.$recipient.'"}';
}
//binding array is print value is
//Array
//(
//[0] => {"binding_type":"sms", "address":"+923105653361"}
//[1] => {"binding_type":"sms", "address":"+923491457062"}
//)
$service = $twilio->notify->v1->services->create();
$notification = $twilio->notify->services($serviceSid)
->notifications->create([
"toBinding" => $binding,
"body" => 'Test message 5 notify'
]);
echo $notification->body;
echo '<pre>';print_r($notification->sid);exit;
The notify console is showing the messages are sent with no error.
Twilio developer evangelist here.
It looks like you haven’t connected a messaging service and a phone number to your Notify service. Follow the instructions in the documentation here to set that up, then try sending the messages again.

Twilio API getting the recording of a call

I am testing Twilio's API in PHP. Currently I have a working module which allows me to place calls and record them. Now I am writing a module to report on those calls.
The code below is supposed to fetch a filtered list of calls and present my browser with a little info about that call, as well as link to the audio recording. This script fetches call logs. For each call it then calls a function to fetch the recording belonging to the current call. Problem is, it fetches the same audio recording every time.
$version = '2010-04-01';
// Set our AccountSid and AuthToken
$sid = 'abc123';
$token = 'fbc123';
// Your Account Sid and Auth Token from twilio.com/user/account
$client = new Services_Twilio($sid, $token,$version);
$dt = date("Y-m-d");
// Loop over the list of calls and echo a property for each one
foreach ($client->account->calls->getIterator(0, 50, array(
"Status" => "completed",
"StartTime>" => "2015-08-04",
"StartTime<" => "$dt"
)) as $call
) {
echo $call->sid.", ".$call->duration.", $".abs($call->price)." ".getRecording($call->sid)."<br/>";
}
function getRecording($callsid){
// Twilio REST API version
$version = '2010-04-01';
// Set our AccountSid and AuthToken
$sid = 'abc123';
$token = 'fbc123';
$client = new Services_Twilio($sid, $token);
// Loop over the list of recordings and echo a property for each one
foreach ($client->account->recordings->getIterator(0, 50, array(
"callSid" => '$callsid'
)) as $recording
) {
return " ->".$callsid." <strong><a href='http://api.twilio.com".$recording->uri."'>Audio</a></strong>";
}
}
The output is this (please notice that every audio file has the same URL):
CAab40cacf1690a86e604ba0f527153887, 1, $0.015 ->CAab40cacf1690a86e604ba0f527153887 <strong><a href='http://api.twilio.com/2010-04-01/Accounts/acctnumber/Recordings/REe9a199dec7376ef94d6af256749e7d81'>Audio</a></strong>
CAaf5629839a6d2095067a04359dc13809, 14, $0.015 ->CAaf5629839a6d2095067a04359dc13809 <strong><a href='http://api.twilio.com/2010-04-01/Accounts/acctnumber/Recordings/REe9a199dec7376ef94d6af256749e7d81'>Audio</a></strong>
CAa8610e49f6e49a71c8bf3e02d3e974f1, 11, $0.015 ->CAa8610e49f6e49a71c8bf3e02d3e974f1 <strong><a href='http://api.twilio.com/2010-04-01/Accounts/acctnumber/Recordings/REe9a199dec7376ef94d6af256749e7d81'>Audio</a></strong>
CA478704a99883f919a9932b52c6971cf7, 21, $0.015 ->CA478704a99883f919a9932b52c6971cf7 <strong><a href='http://api.twilio.com/2010-04-01/Accounts/acctnumber/Recordings/REe9a199dec7376ef94d6af256749e7d81'>Audio</a></strong>
CA00b2f9db896e3b8cfc82c93df5c8e11e, 9, $0.015 ->CA00b2f9db896e3b8cfc82c93df5c8e11e <strong><a href='http://api.twilio.com/2010-04-01/Accounts/acctnumber/Recordings/REe9a199dec7376ef94d6af256749e7d81'>Audio</a></strong>
CAcbd21d8dd3de1c06ce1f393c987bc6c7, 19, $0.015 ->CAcbd21d8dd3de1c06ce1f393c987bc6c7 <strong><a href='http://api.twilio.com/2010-04-01/Accounts/acctnumber/Recordings/REe9a199dec7376ef94d6af256749e7d81'>Audio</a></strong>
CAffb1d60f5f48b870af65329d7d4ca48f, 4, $0.015 ->CAffb1d60f5f48b870af65329d7d4ca48f <strong><a href='http://api.twilio.com/2010-04-01/Accounts/acctnumber/Recordings/REe9a199dec7376ef94d6af256749e7d81'>Audio</a></strong>
CA44fd1b5b9ef347f730d068abafffbd73, 15, $0.015 ->CA44fd1b5b9ef347f730d068abafffbd73 <strong><a href='http://api.twilio.com/2010-04-01/Accounts/acctnumber/Recordings/REe9a199dec7376ef94d6af256749e7d81'>Audio</a></strong>
Twilio developer evangelist here.
The parameters for queries are case sensitive so you need to capitalize the c in callSid. Also wrapping a string in single quotes doesn't substitute it.
foreach ($client->account->recordings->getIterator(0, 50, array(
"callSid" => '$callsid'
to
foreach ($client->account->recordings->getIterator(0, 50, array(
"CallSid" => $callsid
Please let me know if I can help further!
edit: To clarify what was happening, a request was being made to get all the recordings in the account since the query param was off and each time it was taking the first one of the collection and returning that. Thus causing them to all be the same.

How to capture when a caller joins a Twilio conference?

Our app brings together several participants into a conference. The Host, uses twilio client, while participants use either phone lines or twilio clients.
The host need to know when each participant joins the conference.
is there a way via the RESTful API to get in real-time who joined the conference?
Here's how to get the participants' numbers:
<?php
// Get the PHP helper library from twilio.com/docs/php/install
require_once('/path/to/twilio-php/Services/Twilio.php'); // Loads the library
// Your Account Sid and Auth Token from twilio.com/user/account
$sid = "ACXXXXX";
$token = "YYYYY";
$client = new Services_Twilio($sid, $token);
$response = new Services_Twilio_Twiml();
if( isset($_REQUEST['ConferenceSid']) ){
$participants = $client->account->conferences->get( $_REQUEST['ConferenceSid'] )->participants;
$cnt = count( $participants );
$response->Say( "There are ".$cnt." callers in this conference" );
foreach ($participants as $participant) {
$call = $client->account->calls->get( $participant->callsid );
$response->Say( $call->from );
}
}
$response->Redirect("conferencemod.xml");
print $response;
?>
Taken from: https://www.twilio.com/blog/2014/09/roll-call-roger-stringer-shows-you-how-to-take-a-headcount-during-a-twilio-conference-call.html
You can probably modify it to return $call->StartTime additionally. That would let the moderator know who called and when their call started. I hope that helps.

Resources