Building A Phone Verification System With Twilio Voice, Java, and Yext

March 03, 2016
Written by

f1

Pull on the thread of user verification options and it will unravel. You’ll be on page 51 of your Google Search when you realize your looking at a user verification platform that wants to you verify your account so it can verify users while you verify users. It’s an Xibit meme feedback loop.

The folks at Yext kept their user verification simple. They used the Twilio API and a Java Play backend to create user verification via phone. When Yext customers need to verify their Yahoo free listings, all they have to do is answer the phone and enter in the verification code they’ll hear read aloud.
Yi Liu, software engineer at Yext, published this piece detailing how he built the backend of their phone verification service in a week.

How Yext Built Their Verification System

Yext has recently become the sole provider of Yahoo free basic listings. This transition involves verifying Yahoo listings for certain customers. One verification option is that customers choose to receive a phone call from Yext which contains a verification code. In order to accomplish this time-sensitive project, we built an outbound phone call system within one week using the Twilio API and the Play framework.

Play is an open source web application framework that is widely used at Yext, and Twilio REST API makes life easier to build a phone application. This blog illustrates how we combined them to build up the system.

The Call Flow

A database table has been created in order to track the calls history. The responsibilities of the Play server are to process the requests from Twilio API, send back the TwiML responses, and update the database. Twilio API acts like a middle layer between users and the server to create the phone calls and gather user inputs (e.g. a user presses a key). The overall call flow is shown below.

yahoo-phone-call-flow

 

Call Initialization 

After a user selects the option to receive a phone call from Yext to get the verification code, it triggers Twilio API to initialize a call.

**
  * Makes an outbound call to the provided customer phone number.
  *
  * @param toPhoneNumber The customer's phone number to call
  * @param phoneCallUrl the URL to which Twilio makes an HTTP request to get
  *                     the TwiML response when the call connects
  *
  * @return The call's Twilio Sid
  */
public static String makeOutboundCall(String toPhoneNumber, String phoneCallUrl)
throws TwilioRestException {
    // Initializes Twilio client
    TwilioRestClient client = new TwilioRestClient(ACCOUNT_SID, AUTH_TOKEN);
    CallFactory callFactory = client.getAccount().getCallFactory();

    // Sets the request parameters
    Map<String, String> callParams = new HashMap<String, String>();
    callParams.put("To", toPhoneNumber);
    callParams.put("Url", phoneCallUrl);
    // ...

    // Makes the call
    Call call = callFactory.create(callParams);
    return call.getSid();
}

Once the call connects, Twilio sends an HTTP request to the provided phoneCallUrl which hits the following Play endpoint.

public static void initialRequestHandler() throws TwiMLException {
    TwiMLResponse twiml = YahooHelper.generateTwiMLResponse();
    renderXml(twiml.toXML());
}

A sample TwiML response the above endpoint sends back:

?xml version="1.0" encoding="UTF-8"?>
<Response>
    <Gather>
        <Play>instruction...</Play>
        ...
        <Play>instruction...</Play>
    </Gather>
    <Play>GoodBye instruction</Play>
    <Hangup></Hangup>
</Response>

User Input
The following Play endpoint generates the TwiML response for the request that Twilio API would fire when the user presses a key on the phone.

public static void userInputHandler() throws TwiMLException {
    String digit = params.get("Digits");
	
    // Generates the TwiML response based on the user input
    TwiMLResponse twiml = new TwiMLResponse();
    // ...
	
    renderXml(twiml.toXML());
}

After The Call
The following Play endpoint handles the request that twilio API would send after the call ends and updates the call history table in the database.

public static void endCallHandler() throws SQLException {
    String statusParam = params.get("CallStatus");
    // Updates DB based on the call status, e.g. completed, no answer...
    // ...
}

That’s it! Now you’ve got a phone verification solution up and running.