Make Outbound calls to a phone using Twilio and Rails

Vipul

Vipul

September 29, 2014

In this blog post we will see how to make outbound phone calls from the browser to a phone using Twilio . We will make use of the Twilio-JS library and Twilio-Ruby gem.

The Rails App we will be creating, is based on the Twilio Client Quick-start tutorial. That Twilio tutorial makes use of Sinatra. We will see how we can achieve this in a Rails application.

Step 1 - Setup Twilio Credentials and TwiML App

We need to setup twilio credentials. We can find account ID and auth token from our account information.

When the call is made using browser then the phone that is receiving the call has to see a number from which the call is coming. So now we need to setup a Twilio verified number. This number will be used to place the outgoing calls from. How to setup a verified number can be found here.

When our app make a call from the browser using twilio-js client, Twilio first creates a new call connection from our Browser to Twilio. It then sends a request back to our server to get information about what to do next. We can respond by asking twilio to call a number, say something to the person after a call is connected, record a call etc.

Sending of this instructions is controlled by setting up a TwiML application. This application provides information about the end point on our server, where twilio should send the request to fetch instructions. TwiML is a set of instructions, that we can use to tell Twilio what to do in different cases like when an outbound phone call is made or when an inbound SMS message is received.

Given below is an example that will say a short message How are you today? in a call.


<?xml version="1.0" encoding="UTF-8"?>
<Response>
    <Say voice="woman">How are you today?</Say>
</Response>

The TwiML app can be created here. Once the app is configured then we will get appsid.

We need to configure following information in our Rails Application:

twilio:
  verified_number: <%= ENV['TWILIO_VERIFIED_NUMBER']%>
  account_sid: <%= ENV['TWILIO_ACCOUNT_SID'] %>
  auth_token: <%= ENV['TWILIO_AUTH_TOKEN'] %>
  call_app_sid: <%= ENV['TWILIO_CALL_APP_SID'] %>

Step 2 - Generate capability token to be used by twilio-js

After we have the config setup, we will proceed to create the capability token. This token will be generated using the ruby gem, and passed to the javascript SDK. The token helps the twilio-js client determine, what permissions the application has like making calls, accepting calls, sending SMS, etc.

We define a TwilioTokenGeneratorService for this purpose.


class TwilioTokenGeneratorService

  def process
    capability = twilio_capability()
    capability.generate
  end

  private

  def twilio_capability
    capability ||= Twilio::Util::Capability.new Settings.twilio.account_sid, Settings.twilio.auth_token
    capability.allow_client_outgoing Settings.twilio.call_app_sid
    capability
  end

end

As you can see, we first define a new Twilio::Util::Capability instance and pass credentials to it. We then call allow_client_outgoing method and pass the client Sid to it. This is the identifier for the TwiML application we have previously created on Twilio. Calling allow_client_outgoing gives permission to the client to make outbound calls from Twilio. Finally we call the generate method to create a token from the capability object.

Step 3 - Define view elements and pass token to it

The generated token will now be passed to the Twilio JS client for connecting with Twilio. In our App we define CallsController, and index action in this controller. This action takes care of setting the capability token. Our index view consists of two buttons- to place and hangup a call, a number input field, call logs, and data field to pass capability token to the javascript bindings. We import the Twilio-JS library in the view. The css styling being used is from the Twilio example.


<div id="twilioToken" data-token="<%= @twilio_token %>"></div>

<button id="caller" class="call">Call</button>
<button id="hangup" class="hangup">Hangup</button>

<input type="text" id="phoneNumber" placeholder="Enter a phone number to call"/>

<div id="log">Loading pigeons...</div>

<script type="text/javascript" src="//static.twilio.com/libs/twiliojs/1.2/twilio.min.js"></script>

Step 4 - Define coffeescript bindings to handle TwilioDevice connection to Twilio

Next we setup coffeescript bindings to handle initialization of TwilioDevice and making use of entered number to place calls Twilio. We are taking care of various events like connect, disconnect, ready, etc. on TwilioDevice instance. More information about TwilioDevice usage can be found here.


class TwilioDevice
  constructor: ->
    @initTwilioDeviceBindings()
    @initFormBindings()

  initTwilioDeviceBindings: ->
    twilio_token = $('#twilioToken').data('token')
    twilio_device = Twilio.Device

    # Create the Client with a Capability Token
    twilio_device.setup(twilio_token, {debug: true});

    #/* Let us know when the client is ready. */
    twilio_device.ready ->
      $("#log").text("Ready")

    #/* Report any errors on the screen */
    twilio_device.error (error) ->
      $("#log").text("Error: " + error.message)

    #/* Log a message when a call connects. */
    twilio_device.connect (conn) ->
      $("#log").text("Successfully established call")

    #/* Log a message when a call disconnects. */
    twilio_device.disconnect (conn) ->
      $("#log").text("Call ended")

  initFormBindings: ->
    $('#caller').bind "click", (event) ->
      params = {"phone_number": $('#phoneNumber').val()}
      Twilio.Device.connect(params)

    $('#hangup').bind "click", (event) ->
      Twilio.Device.disconnectAll()

$ ->
  new TwilioDevice()

If we now load this page, we should be able to see our app saying its ready to take calls.

Step 5 - Define TwiML Response Generator Service

The final step before we place calls from our App is to handle callbacks from Twilio and return TwiML response. For this we are going to define TwilioCallTwiMLGeneratorService which takes care of generating this response. More information about how we need to define the response and individual fields can be found from Twilio's docs.

What we need to define is a response as below:


<?xml version="1.0" encoding="UTF-8"?>
<Response>
  <Dial callerId="+15005550000">
    <Number>+15005550001</Number>
  </Dial>
</Response>

We are making use of two elements here - Dial, which makes Twilio place a call using defined callerId value, as the number from which the call is made, which is displayed on the callee's phone. Note that this is the same verified number that we had specified before. Then we specify Number which is the number, to which we want to place the call to. This number is passed first by the javascript client to Twilio, and then back to our application by Twilio, which we use to generate the response as above.

We define our TwilioCallTwiMLGeneratorService to take in a phone number as parameter. It creates an instance of Twilio::TwiML::Response and tapping on this instance we provide Dial element with a :callerId value, and the Number to place the call to. We validate the number before passing it back, and return an error if the number is invalid.


class TwilioCallTwiMLGeneratorService
  attr_reader :phone_number
  VALID_PHONE_NUMBER_REGEX = /^[\d\+\-\(\) ]+$/ # Matches valid phone numbers acceptable to Twilio

  def initialize phone_number
    @phone_number = phone_number
  end

  def process
    Twilio::TwiML::Response.new do |r|
      if VALID_PHONE_NUMBER_REGEX.match(phone_number)
        r.Dial :callerId => Settings.twilio.verified_number do |d| # callerId is number from which call is made.
          d.Number(CGI::escapeHTML phone_number) # The number to call
        end
      else
        r.Error("Invalid number!")
      end
    end.text.strip
  end

end

Step 6 - Send TwiML response on Twilio callback

We are now set to define twilio's callback handler. This will be handled by the create_call action in CallsController. Twilio will be sending this endpoint a POST request along with some information specified here. We make use of phone_number being passed to us by Twilio and pass it along to the TwilioCallTwiMLGeneratorService, which return us with valid TwiML response. Since TwiML is a flavor of XML, we make using render xml to return the response.


def create_call
  response_to_twilio_callback = TwilioCallTwiMLGeneratorService.new(call_params[:phone_number]).process
  render xml: response_to_twilio_callback
end

def call_params
  params.permit(:phone_number)
end

As create_call endpoint will be used by Twilio API, we need to skip authenticity token check for this action.

class CallsController < ApplicationController
  skip_before_action :verify_authenticity_token, only: [:create_call]
end

Finally we need to specify the callback url in our TwiML App on Twilio. For testing this locally, we can make use of a service like https://ngrok.com/, to expose this endpoint.

Our service is now ready to place calls. The complete Rails application code that we have created can be found here.

Happy calling everyone!

If this blog was helpful, check out our full blog archive.

Stay up to date with our blogs.

Subscribe to receive email notifications for new blog posts.