0
votes

I send calls out by building an html file that contains twiml markup, and use the php lib to place the call to the outgoing number (see e.g.)

$tw_call = $twilio_client->calls->create(
        "+1".$recipient['address'], "+1".$org['twilio_number'], 
        array(
            'Url' => VOICE_CALL_LINK.'/'.$file, (this contains the SAY verbs and text)
            'Timeout' => '30',
            'StatusCallback' => CALLBACK_LINK.'/voice_call_handler.php',
            'StatusCallbackEvent' => array('initiated', 'ringing', 'answered', 'completed')
            )

I want to know if it is possible to record a dtmf code from the call recipient via the method I am using for placing the call?

Can an additional callback url be placed in the text file? If so how would I capture which call the was coming back? Would the call sid be available to the possible callback url within the text file?

Ok I must be missing something. I tried the following:

<Response>
    <Pause length='1'/>
    <Say voice='alice'>$intro</Say>
    <Pause length='1'/>
    <Say voice='alice'>$msg_body</Say>
    <Pause length='1'/>
    <Gather action='absolute html path' numDigits='1'>
        <Say Please respond by selecting 1 for I can come.  Select 2 for I cannot come.</Say>
    </Gather>
</Response>";

I get back from Twilio "an application error has occurred". If I remove the Gather tags and the Say tag within the Gather tags, I receive a perfect call.

Same error occurs if I leave the tags and remove the action and path.

Can you gather responses on outbound calls? I ask because all twilio docs refer to inbound call.

2

2 Answers

1
votes

Twilio developer evangelist here.

In order to capture DTMF tones from a call you can use the <Gather> TwiML verb. This would probably go in the file which contains your <Say> that you point to in the code above. <Say> can be nested within <Gather> in order to allow you to ask the user for input and start taking it as soon as they start typing.

The TwiML might look like this:

<Response>
  <Gather action="/gather_result.php" numDigits="1">
    <Say>Welcome to the free beer hotline, dial 1 for free beer, dial 2 for other beverages.</Say>
  </Gather>
</Response>

Then, when the user dials the number (you can control how many numbers with the numDigits attribute) Twilio will make a request to the URL in the action attribute. Within that request will be a Digits parameter which will contain the numbers the user pressed. The call SID would also be among the parameters.

Let me know if that helps at all.

0
votes

I had similar issue where Gather TwiML was not capturing the user dtmf input from a call sent out of twilio. For some reasons, it failed to capture my input digit. I did press 1#, but the voice message keep playing and repeating the same message. Sometimes it works and twilio able to get the digit that I inputted, but more than 80% of the times I tried, it failed to capture the inputted digit. Below is the TwiML in node js looks like:

var promise = new Parse.Promise();

twilioClient.calls.create({
    to: phoneNumber,
    from:'+6598124124',
    url: hosturl + '/gather_user_dial',
    body: callParam,
    statusCallback: hosturl + '/callback_user',
    statusCallbackMethod: 'POST',
    statusCallbackEvent: ["completed", "busy", "no-answer", "canceled", "failed"]
}).then(function(call) {
    if (res) res.success(call);
    promise.resolve(call);
}, function(error) {
    console.error('Call failed!  Reason: ' + error.message);
    if (res) res.error(error);
    promise.reject(error);
});
app.post('/gather_user_dial', (request, response) => {
  const twiml = new VoiceResponse();

  const gather = twiml.gather({
    numDigits: 1,
    timeout: 5,
    actionOnEmptyResult: true,
    action: '/gather',
  });
  gather.say('You are receiving a call from company A because you press the emergency button. Press 1 if you are okay or Press 9 if you need help, followed by the pound sign.');

  twiml.redirect('/gather_user_dial');
  response.type('text/xml');
  response.send(twiml.toString());
});

app.post('/gather', (request, response) => {
  const twiml = new VoiceResponse();
  if (request.body.Digits) {
    switch (request.body.Digits) {
      case '1':
        twiml.say('User has been notified!');
        userPressOne(request.body.Called);
        break;
      case '9':
        twiml.say('User has been notified!');
        userPressNine(request.body.Called);
        break;
      default:
        twiml.say("Sorry, I don't understand that choice.").pause();
        twiml.redirect('/gather_user_dial');
        break;
    }
  } else {
      twiml.redirect('/gather_user_dial');
  }
  response.type('text/xml');
  response.send(twiml.toString());
});