How to Send Voice OTP on a Phone Call in Ruby Using Rails and Plivo

You can authenticate a phone number by delivering a one-time password (OTP) via a phone call. To do this, you call the number and read a sequence of digits to the recipient via text-to-speech. To verify the number, the user needs to confirm the digits by entering them using the phone’s keypad.

Developers commonly use voice OTP to verify new user registrations, online transactions, and login sessions in an app or website. In this blog post, we walk you through a sample implementation of sending a Voice OTP using the Plivo Voice platform and PHLO, our visual workflow builder. Plivo’s direct carrier connectivity and intelligent routing engine guarantee the best call connectivity and quality.

Prerequisites

Before you get started, you’ll need:

  • A Plivo account — sign up for one for free if you don’t have one already.
  • A voice-enabled Plivo phone number if you want to receive incoming calls. To search for and buy a number, go to Phone Numbers > Buy Numbers on the Plivo console. Buy a New Plivo Number
  • Rails and Plivo Ruby packages — run gem install rails and gem install plivo to install them.
  • ngrok — a utility that exposes your local development server to the internet over secure tunnels.

Create a PHLO to send OTP via phone call

PHLO lets you construct your entire use case and build and deploy workflows visually. With PHLO, you pay only for calls you make and receive, and building with PHLO is free.

To get started, visit PHLO in the Plivo console and click on Create New PHLO. Click Create New PHLO to build a new PHLO. On the Choose your use-case window, click Build my own. The PHLO canvas will appear with the Start node. Click on the Start Node, under API request, fill in the Keys as from, to, and otp and then click on Validate. From the list of components, on the left-hand side, drag and drop the Initial Call component onto the canvas and connect the Start node with the Initiate Call node, using the API Request trigger state.

Configure the Initiate Call node with the using the From field. in the To field. Once you have configured a node, click Validate to save the configurations. Similarly, create a node for the Play Audio component and connect it to the Initiate Call node using the Answered trigger state. Next, configure the Play Audio node to play a specific message to the user — in this case, “Your verification code is <otp>.” Under Speak Text, click on Amazon Polly and paste the following:

<Speak voice="Polly.Amy">
   <prosody rate="medium">
      Your verification code is
      <break/>
      <break/>
      <say-as interpret-as="spell-out">{{Start.http.params.otp}}</say-as>
   </prosody>
</Speak>

and click on Validate to save.

Connect the Initiate Call node with the Play Audio node, using the Answered trigger state. After you complete the configurations, provide a friendly name for your PHLO and click Save.

Create a PHLO for Voice OTP

Create a Rails Project

As we have Rails and its dependencies installed, we can use them to create a new Rails project. As the initial step, using rails we can auto-generate code in the ruby on rails folder structure. Use the below command to start your Rails project.

$ rails new plivotest

This will create a plivotest directory with the necessary folders & files for development.

Install Modules

As we have the rails application created, now, let’s add Plivo-Ruby by modifying the Gemfile. Open the Gemfile in any IDE/text-editor and add the following line:

gem 'plivo', '~> 4.16.0'
gem 'redis', '4.2.1'
gem 'json', '2.3.1'

You can use the below command to install the Plivo-Ruby gem into the bundle:

$ bundle install

Create a Rails Controller

Change the directory to our newly created project directory, i.e, plivotest directory and run the below command to create a rails controller for Voice OTP.

$ rails generate controller Plivo voice

This will generate a controller named plivo_controller in the app/controllers/ directory and a respective view will be generated in app/views/plivo directory. We can delete the View as we will not need it.

$ rm app/views/plivo/voice.html.erb

Run the PHLO to send OTP via phone call

Now you can trigger the PHLO and test it out. Copy the PHLO ID from the end of the URL of the workflow you just created. You’re also going to need your Auth ID and Auth Token.

Now, You have to open the app/controllers/plivo_controller.rb file and add the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
include Plivo
require 'redis'
require 'json'
include Plivo::Exceptions

class PlivoController < ApplicationController
	def dispatch_otp
		redis = Redis.new(host: "localhost")
		code = rand(999_999)
		dst_number = params[:dst_number]
		auth_id = '<auth_id>'
    auth_token = '<auth_token>'

    client = Phlo.new(auth_id, auth_token)
    	begin
    phlo = client.phlo.get('phlo_id')
    #parameters set in PHLO - params
    params = {
       from: +15671234567,
       to: dst_number,
       otp:code
  }
  response = phlo.run(params)
  puts response
rescue PlivoRESTError => e
  puts 'Exception: ' + e.message
end
		redis.setex(dst_number, 60, code) # Verification code is valid for 1 min
		puts JSON.pretty_generate({ :status=> 'success', :message=> 'verification initiated' })
	rescue PlivoRESTError => e
		puts 'Exception: ' + e.message
	end

	def verify_otp
		redis = Redis.new(host: "localhost")
		code = params[:otp]
		number = params[:number]
		original_code = redis.get(number)
		if original_code == code
			redis.del(number)  # verification successful, delete the code
			puts JSON.pretty_generate( { :status=> 'success', :message=> 'codes match! number verified'})
		elsif original_code != code
			puts JSON.pretty_generate({ :status => "failure", :message=> 'codes do not match! number not verified' })
		else
			puts JSON.pretty_generate( { :status=> 'rejected', :message=> 'number not found!' })
		end
	end
end

Substitute actual values for <auth_id>, <auth_token>, and <PHLO_ID>. Save the file and run it with the command

Add a Route

Now, to add a route for the outbound function in the PlivoController class, open the config/routes.rb file and change the line:

get 'plivo/voice' 

to

get 'plivo/verify_otp'
get 'plivo/dispatch_otp'

Test & Validate

Now the plivo_controller is ready for your first outbound call, you can use the below command to initiate your first outbound using Rails and Plivo Ruby SDK.

$ rails server

Run the following command in a new terminal tab to start the redis.

$ redis-server

And you should see your basic server app in action as below:

http://localhost:3000/plivo/dispatch_otp?destination_number=<destination_number>
http://localhost:3000/plivo/verify_otp?destination_number=<destination_number>&otp=<otp>

Boom — you’ve made an outbound call with the OTP as a text-to-speech message.

Simple and reliable

And that’s all there is to send OTP via a phone call using Plivo’s Ruby SDK. Our simple APIs work in tandem with our comprehensive global network. You can also use Plivo’s premium direct routes that guarantee the highest possible delivery rates and the shortest possible delivery times for your 2FA SMS and voice messages. See for yourself — sign up for a free trial account.

comments powered by Disqus

By submitting this form, you agree we may contact you in the manner described in our Privacy Policy