Need dialer with call transfer after answer - twilio

I'm looking for a twimlet or php script for the Twilio API that would implement an outbound calling list function with optional transfer to recorded message -
Sales person Clicks number in a list to dial outbound call
dialed party answers
Sales person realizes it's a machine and clicks a link to transfer the call to a recorded message that will be left on the machine.
Or, if it's not a machine sales person proceeds with the call.
Is something like that available already canned or scripted?

Since the initial ask we've updated the click-to-call solution in a code complete tutorial.
In the last step, after a call is connected and Twilio asks for TwiML instructions you might consider adapting from the call screening tutorial to handle voicemail:
public function agentVoicemail(Request $request, $agentId)
{
$response = new Services_Twilio_Twiml;
$callStatus = $request->input('DialCallStatus');
if ($callStatus !== 'completed') {
$response->say(
'It appears that no agent is available. ' .
'Please leave a message after the beep',
['voice' => 'alice', 'language' => 'en-GB']
);
$response->record(
['maxLength' => '20',
'method' => 'GET',
'action' => route('hangup', [], false),
'transcribeCallback' => route(
'store-recording', ['agent' => $agentId], false
)
]
);
$response->say(
'No recording received. Goodbye',
['voice' => 'alice', 'language' => 'en-GB']
);
$response->hangup();
return $response;
}
return "Ok";
}

Related

Twilio Make call and send digits multiple times using DTMF

Scenario: I want to dial a number where an IVR is setup. That has press 1 for English and press 2 for Spanish. Once a number is chosen then it asks for 6 digit key. How I can pass the next 6 digits using DTMF?
I had read the documentation thoroughly and searched on StackOverflow too but didn't got the relevant data.
What I tried is;
$twilio = new Client("AC8b2cc96be2a8dbc059f2908exxxxxxxx", "88db8eeb71124a3effd6c196xxxxxxxx");
$from = "+1289724xxxx";
$to = "+1289670xxxx";
$call = $twilio->calls
->create($to, // to
$from, // from
[
"method" => "GET",
"sendDigits" => "wwwwwwwwww1",
"sendDigits" => "wwwwwwwwwwwwwwwwww123456", // Whithout this line it's working for first digit press
"url" => "http://demo.twilio.com/docs/voice.xml"
]
);
print($call->sid);
I am trying it using PHP Rest API. https://www.twilio.com/docs/voice/make-calls#example-3
I had also read this question: How to send digits in twilio call
You can't send the same parameter twice, instead, you should combine that sendDigits parameter into one string, like this:
$call = $twilio->calls
->create($to, // to
$from, // from
[
"method" => "GET",
"sendDigits" => "wwwwwwwwww1wwwwwwwwwwwwwwwwww123456",
"url" => "http://demo.twilio.com/docs/voice.xml"
]
);
Then it will wait, press 1, wait some more then press 123456.

Twilio outgoing call to recipient with call screening (Google voice)

I have a working service, where we do outgoing calls something like this.
$sid = getenv("TWILIO_ACCOUNT_SID");
$token = getenv("TWILIO_AUTH_TOKEN");
$twilio = new Client($sid, $token);
$call = $twilio->calls
->create("+14155551212", // to
"+14155551212", // from
["url" => "http://demo.twilio.com/docs/classic.mp3"]
);
print($call->sid);
The issue is when the recipient has call screening, the callback to the URL parameter is done as soon as the screening starts (with callbackstatus "in-progress"!), which means we have to add a pause in the response.
<Response>
<Pause length="10"/>
<Say>
This is an important message
</Say>
<Gather action="https://xxx" method="GET" timeout="15" speechTimeout="auto" numDigits="1" input="dtmf speech">
<Say>Please press 1 followed by the pound sign or say confirm to confirm your appointment</Say>
</Gather>
<Redirect method="GET">https://xxx</Redirect>
</Response>
Is there some way to bypass the screening or have the system not start the response in screening?
EDIT:
I've added the AMD options and it seems to be correctly somewhat working. Right now the only issue that remains is when calling in to Google Voice, when there's call screening, my added voice recording start reading before the recipient actually answers
$call = $client->calls->create(
$to, $from,
array(
"url" => $url,
"statusCallback" => $statusURL,
"statusCallbackMethod" => 'POST',
"machineDetection" => "DetectMessageEnd",
"machineDetectionTimeout" => 5
)
);
You are looking for answering machine detection (AMD).
You can make a call with AMD enabled by setting the MachineDetection parameter to Enable or DetectMessageEnd.
$call = $twilio->calls
->create("+14155551212", // to
"+14155551212", // from
[
"url" => "http://demo.twilio.com/docs/classic.mp3",
"machineDetection" => "Enabled"
]
);
When you use the MachineDetection parameter the request to your url will include an AnsweredBy parameter. From the docs:
Use Enable if you would like Twilio to return an AnsweredBy value as soon as it identifies the called party. This is useful if you would like to take a specific action — for example, connect to an agent, play a message) — for a human but hang up on a machine.
If you would like to leave a voicemail on an answering machine, specify DetectMessageEnd. In this case, Twilio will return an AnsweredBy immediately when a human is detected but for an answering machine, AnsweredBy is returned only once the end of the greeting is reached, usually indicated by a beep.
There is also an option for asynchronous AMD. With asynchronous detection your url is called immediately as if a normal call, but once Twilio has performed the detection an asynchronous webhook is made to a different URL and you can use the callback data to decide whether to update the call.

Twilio callStatusCallback for conferences not working

I'm trying to setup a flow where i'm using the twilio client sdk to start a conference.
Frontend creates a device and connects, which in turn calls the route I have setup in the twiml application. Then the following is returned:
$response = new VoiceResponse();
$dial = $response->dial('');
$dial->conference($x->getRoomName(), [
'participantLabel' => 'A participant label',
'startConferenceOnEnter' => 'True',
'endConferenceOnExit' => 'True',
'statusCallbackEvent' => 'start end join leave mute hold',
'statusCallback' => "https://example.com/conference-call/status-callback",
'statusCallbackMethod' => 'POST',
'callStatusCallbackEvent' => 'ringing completed initiated answered',
'callStatusCallback' => "https://example.com/conference-call/call-status-callback",
'callStatusCallbackMethod' => 'POST',
]);
I can get status callbacks for the conference, but not for the call that is actually initiating the conference. As such I am unable to track the call status of the one who is initiating the conference.
Inviting a participant via the API works fine, the callStatusCallback works when creating a participant via the rest API.
Twilio must be creating a participant in the background when we use the Conference term, but there doesn't seem to be a way to subscribe to the call status?
If there is no solution for this, is there a way to use the client sdk to inititate the call, then take care of the business logic only via the rest API? It seems like the twiml is not as powerful as the rest API, but i couldn't find a way to make calls from the browser without a twiml app.

Difference between CallTo/To and CallFrom/From in Twilio

When I make an outgoing call using Twilio API & TwiML App Twilio makes request to my server with following params:
'AccountSid' => '...',
'ApplicationSid' => '...',
'Caller' => 'client:2',
'CallStatus' => 'ringing',
'callFrom' => 'some_phone_number',
'Called' => '',
'To' => '',
'callTo' => 'some_phone_numeber',
'CallSid' => '...',
'From' => 'client:2',
'Direction' => 'inbound',
'ApiVersion' => '2010-04-01',
what's the difference between CallTo (which equals the actual phone number I'm calling to) and To (which is empty for some reason) ? Same for From and CallFrom. I couldn't find any info in the docs about callTo/callFrom. Plus, why To is empty?
Update
Some additional info. I make a call from twilio number to real Russian phone number. I actually hangup the call. There is no forwarding/redirecting. The Twiml app for outgoing calls is:
<Response>
<Dial callerId="{{ $callFrom }}"
record="record-from-ringing"
action="{{ $action }}">
<Number>{{ $callTo }}</Number>
</Dial>
</Response>
CallFrom and CallTo equals those which are passed with the request. So the data I mentioned above is what Twilio passes with the request, and then Twilio gets the TwiML instructions.
What I do not understand if that what's the difference between to/from? Are from/to fields used when dealing with client names, like for internal conversation or kind of...?
And another question is: when the call is finished and the action url called, twilio passes DialCallStatus and CallStatus, what's the difference there? I need to store call status so that I know if the client was busy and didn't answer, but DialCallStatus has different value from CallStatus.
Thanks

Invalid fingerprint exception when processing through securepay using omnipay

I am trying to understand the flow for a payment using Omnipay/SecurePay but always get an error when trying to complete the purchase.
From what I can see from the online docs the completePurchase function should be called with the same params as the purchase function but when I call completePurchase I receive an "Invalid fingerprint" exception.
Also these errors are being thrown :
Undefined index: merchant in /var/www/vendor/omnipay/securepay/src/Message/DirectPostCompletePurchaseRequest.php on line 28
Undefined index: refid in /var/www/vendor/omnipay/securepay/src/Message/DirectPostCompletePurchaseRequest.php on line 30
Undefined index: timestamp in /var/www/vendor/omnipay/securepay/src/Message/DirectPostCompletePurchaseRequest.php on line 32
Undefined index: summarycode in /var/www/vendor/omnipay/securepay/src/Message/DirectPostCompletePurchaseRequest.php on line 33
Am I missing a step somewhere that adds this missing data? or should this data be coming back in the response?
Code:
$params = array(
'amount' => $data->payment['amount'] . '.00',
'currency' => $this->getOptions()->getCurrency(),
'description' => 'test purchase',
'transactionId' => '12345',
'transactionReference' => $data->course['course_code'],
'returnUrl' => 'http://test.localhost/register/55622/confirmation',
'cancelUrl' => 'http://test.localhost/register/55622/summary',
'card'=>$card
);
$gateway = new DirectPostGateway();
$gateway->setMerchantId( $this->getOptions()->getGateway( $type )['merchant_id'] );
$gateway->setTransactionPassword( $this->getOptions()->getGateway( $type )['password'] );
$gateway->setTestMode( $this->getOptions()->getTestMode() );
$response = $gateway->purchase($params)->send();
var_dump($response->getRedirectData());
$response = $gateway->completePurchase($params)->send();
var_dump($response);
//"Invalid fingerprint" exception thrown
if ($response->isSuccessful()) {
// payment was successful: update database
return $response;
} elseif ($response->isRedirect()) {
// redirect to offsite payment gateway
if($response->getRedirectData()){
var_dump($response->getRedirectData());
} else {
return $response->redirect();
}
exit;
return $response->redirect();
} else {
// payment failed: display message to customer
// echo $response->getMessage();
throw new Exception("Error Processing Request", 1);
}
You are doing things correctly. When SecurePay returns to your website, there should be POST data containing those parameters, as well as the fingerprint parameter which confirms the authenticity of the request.
I would watch the Network tab of your browser while making a payment with SecurePay, and check the HTTP POST data after payment is complete (and redirecting to your site). My guess is that some htaccess or other script is making a second redirect, and stripping the important POST data at the same time.
Omnipay will automatically check the POST data, so there is no need to explicitly send it through. As long as you call completePurchase() from the same request it should process the payment correctly.
See: https://github.com/omnipay/securepay/blob/master/src/Message/DirectPostCompletePurchaseRequest.php
Securepay was using endpoint https://test.securepay.com.au and then switchign to https://test.api.securepay.com.au

Resources