Detect Cellphones and Verify Phone Numbers in Laravel PHP using Authy

June 10, 2019
Written by
Ugendu Ositadinma
Contributor
Opinions expressed by Twilio contributors are their own

Detect Cellphones and Verify Phone Numbers in Laravel PHP using Authy.png

↪️ We recommend using the Verify API V2 for new developement. Check out this post on How to Verify Phone Numbers in a Laravel PHP Application with the Twilio Verify API.

The Verify API is an evolution of the Authy API used in this article. Any new features and development will be on the Verify API. Check out the FAQ for more information and Verify API Reference to get started.

Introduction

There may be times in building your app that you will need to send an SMS to the phone number of a user. Wouldn't it be awesome if you could confirm that the number supplied is actually a cellphone? Or maybe you want to only send SMS to verified users. With Twilio's Authy API, these use cases are easy to implement. This tutorial is aimed at helping developers to build a phone number validator to verify users phone numbers in any PHP application and check if a number is a cellphone or landline before sending an SMS. 

Technical Requirements

For this tutorial, it is expected that you have basic knowledge of the following:

NOTE: Don’t forget to craft a Laravel project for this purpose. Here’s a link to a guide on the installation process for installing Laravel.

Phone Number Verification

First, we need to install the Twilio PHP SDK which makes available the functions we would need to carry out the task of verifying a phone number. In the root folder of your Laravel project, run the following command.

$ composer require twilio/sdk authy/php

After successfully installing the Twilio SDK, we need to configure the client application to be able to communicate with our Twilio account. To do this, please add the following to your .env file. This should be after you have created an Authy application in your Twilio Console:

AUTHY_API_KEY=XXXXXXXXXXXXXXXXXXXX
TWILIO_ACCOUNT_SID=ACXXXXXXXXXXXXXXXXXXX
TWILIO_AUTH_TOKEN=XXXXXXXXXXXXXXXXXXXXX
TWILIO_PHONE=APXXXXXXXXXXXXXXXXXXX

NOTE: Your "AUTHY_API_KEY” can be retrieved from the Settings tab of the Authy application you just created and “TWILIO_PHONE” is your Twilio Phone Number.

Now add the code below in config/app.php to access the Twilio configuration variables globally.

'twilio' => [
   'AUTHY_API_KEY'  => env('AUTHY_API_KEY'),
   'TWILIO_ACCOUNT_SID'  => env('TWILIO_ACCOUNT_SID'),
   'TWILIO_AUTH_TOKEN'  => env('TWILIO_AUTH_TOKEN'),
   'TWILIO_PHONE'  => env('TWILIO_PHONE'),
],

Now that we are done with the basic installation setup, we will begin building the controller methods to process our Twilio requests. This can be achieved by using the following command and should be done inside your project directory:

$ php artisan make:controller TwilioController

Open the newly created controller file located in app/Http/Controllers/TwilioController.php and import the Twilio AuthyApi class which will be used for phone number verification and checking verification codes.

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Twilio\Rest\Client;
use Authy\AuthyApi;

Next, we will initialize the constructor, define the needed variables, and make them accessible within the controller. Add the following code:

<?php

class TwilioController extends Controller
{
   protected $authy;
   protected $sid;
   protected $authToken;
   protected $twilioFrom;

   public function __construct() {
       // Initialize the Authy API and the Twilio Client
       $this->authy = new AuthyApi(config('app.twilio')['AUTHY_API_KEY']);
       // Twilio credentials
       $this->sid = config('app.twilio')['TWILIO_ACCOUNT_SID'];
       $this->authToken = config('app.twilio')['TWILIO_AUTH_TOKEN'];
       $this->twilioFrom = config('app.twilio')['TWILIO_PHONE'];
   }

}

Now create the controller method to verify the user’s phone number. Upon validation, it will send out a verification code to the user which will be used in the next step. Next, create another method to verify the verification code that was sent to the user.

<?php

public function verifyPhone(Request $request) {
       // Validate form input
       $this->validate($request, [
           'country_code' => 'required|string|max:3',
           'phone' => 'required|string|max:10',
           'via' => 'required|string'
       ]);

       //Call the "phoneVerification" method from the Authy API and pass the phone number, country code and verification channel(whether sms or call) as parameters to this method.
       $response = $this->authy->phoneVerificationStart($request->phone, $request->country_code, $request->via);
      
       if ($response->ok()) {
           print $response->message();
       } else  {
           print $response->message();
       }
}

public function verifyCode(Request $request) {
       // Call the method responsible for checking the verification code sent.
       $response = $this->authy->phoneVerificationCheck($request->phone, $request->country_code, $request->code);
       if($response->ok()) {
           print $response->message();
       } else {
           print $response->message();
       }
}

Open up web.php located in the routes folder and paste in the following code for the phone verification code verification methods:

Route::view('/verify', 'phone-verification');
Route::post('/verify', 'TwilioController@verifyPhone')->name('verify-phone');
Route::post('/verify-code', 'TwilioController@verifyCode')->name('verify-code');

Next, create a file in the resources/views directory called phone-verification.blade.php which will be used to receive user input. Add the following to the file you just created.

<html>
 <head>
   <title>Twilio + Laravel</title>

   <!-- Bootstrap -->
   <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous">
   <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

   <style>
     form {
       background-color: #fff;
       width: 600px;
       float: center;
       margin: auto;
       margin-top: 100px;
     }
   </style>
 </head>
 <body>
   @if ($errors->any())
     <div class="alert alert-danger">
         <ul>
             @foreach ($errors->all() as $error)
                 <li>{{ $error }}</li>
             @endforeach
         </ul>
     </div>
   @endif
   <form method="post" action="{{ route('verify-phone') }}">
     {{csrf_field()}}
     <h4>Phone Verification</h4>
     <div class="row">
       <div class="form-group col-md-3">
         <label>Country code</label>
         <input type="text" class="form-control" name="country_code" aria-describedby="emailHelp" placeholder="123">
         <small id="emailHelp" class="form-text text-muted">Country dial code for phone number.</small>
       </div>
       <div class="form-group col-md-6">
         <label for="phoneNumber">Phone Number</label>
         <input type="text" class="form-control" name="phone" id="phoneNumber" aria-describedby="phoneNumberHelp" placeholder="1234567890">
         <small id="emailHelp" class="form-text text-muted">Phone number to be verified.</small>
       </div>
       <div class="form-group col-md-3">
         <label for="via">via</label>
         <select class="form-control" name="via" id="exampleFormControlSelect1">
           <option value="sms">SMS</option>
           <option value="call">Call</option>
         </select>
       </div>
     </div>
     <button type="submit" class="btn btn-primary">Submit</button>
   </form>

   <form method="post" action="{{ route('verify-code') }}">
     {{csrf_field()}}
     <h4>Code Verification</h4>
     <div class="row">
       <div class="form-group col-md-3">
         <label>Country code</label>
         <input type="text" class="form-control" name="country_code" aria-describedby="codeHelp" placeholder="123">
         <small id="codeHelp" class="form-text text-muted">Country dial code for phone number.</small>
       </div>
       <div class="form-group col-md-6">
         <label for="phoneNumber">Phone Number</label>
         <input type="text" class="form-control" name="phone" id="phoneNumber" aria-describedby="phoneNumberHelp" placeholder="1234567890">
         <small id="phoneNumberHelp" class="form-text text-muted">Phone number to be verified.</small>
       </div>
       <div class="form-group col-md-3">
         <label for="code">Code</label>
         <input type="text" class="form-control" name="code" placeholder="1234">
       </div>
     </div>
     <button type="submit" class="btn btn-primary">Submit</button>
   </form>

   <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
   <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.6/umd/popper.min.js" integrity="sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut" crossorigin="anonymous"></script>
   <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script>
 </body>
</html>

Sending the SMS

We have created and defined the necessary variables we need for this app to verify our phone number. We will now proceed to create the logic to send our SMS.

Create a file in the resources/views directory called send-sms.blade.php and add the following code to it.

<html>
 <head>
   <title>Twilio + Laravel</title>

   <!-- Bootstrap -->
   <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous">
   <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

   <style>
     form {
       background-color: #fff;
       width: 600px;
       float: center;
       margin: auto;
       margin-top: 100px;
     }
   </style>
 </head>
 <body>
   @if ($errors->any())
     <div class="alert alert-danger">
         <ul>
             @foreach ($errors->all() as $error)
                 <li>{{ $error }}</li>
             @endforeach
         </ul>
     </div>
   @endif
  
   <form  method="post" action="{{ route('send-sms') }}">
     {{csrf_field()}}
     <h4>Send SMS</h4>
     <div class="row">
       <div class="form-group col-6">
         <label for="phoneNumber">Phone Number</label>
         <input type="text" class="form-control" name="phone" id="phoneNumber" aria-describedby="phoneNumberHelp" placeholder="+1231234567890">
         <small id="phoneNumberHelp" class="form-text text-muted">Phone number to send SMS.</small>
       </div>
     </div>
     <div class="row">
       <div class="form-group col-md-12">
         <label>Text Message</label>
         <input type="text" name="message" class="form-control" id="text" aria-describedby="phoneNumberHelp" placeholder="Message here...">
       </div>
     </div>
     <button type="submit" class="btn btn-primary">Submit</button>
   </form>

   <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
   <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.6/umd/popper.min.js" integrity="sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut" crossorigin="anonymous"></script>
   <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script>
 </body>
</html>

Route:

Route::view('/send-sms', 'send-sms');
Route::post('/send', 'TwilioController@verifyPhone')->name('send-sms');

TwilioController:

<?php

public function sendSMS(Request $request) {
       // Validate User input from form.
       $this->validate($request, [
           'phone' => 'required|string',
           'message' => 'required|string'
       ]);

       // Create REST API Client
       $client = new Client($this->sid, $this->authToken);

       try {
           $sms = $client->messages->create($request->phone,
               [
                   'from' => $this->twilioFrom,
                   'body' => $request->message
               ]
           );

           if($sms) {
               return redirect()->back()->with('success', 'SMS sent successfully');
           } else {
               return redirect()->back()->with('error', 'SMS failed!');
           }
       } catch(Exception $e) {
           echo 'Error: ' . $e->getMessage();
       }
   }

Here’s the complete TwilioController code.

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Twilio\Rest\Client;
use Authy\AuthyApi;

class TwilioController extends Controller
{
  protected $authy;
  protected $sid;
  protected $authToken;
  protected $twilioFrom;

  public function __construct() {
      // Initialize the Authy API and the Twilio Client
      $this->authy = new AuthyApi(config('app.twilio')['AUTHY_API_KEY']);
      // Twilio credentials
      $this->sid = config('app.twilio')['TWILIO_ACCOUNT_SID'];
      $this->authToken = config('app.twilio')['TWILIO_AUTH_TOKEN'];
      $this->twilioFrom = config('app.twilio')['TWILIO_PHONE'];
  }

  public function verifyPhone(Request $request) {
      // Validate form input
      $this->validate($request, [
          'country_code' => 'required|string|max:3',
          'phone' => 'required|string|max:10',
          'via' => 'required|string'
      ]);

      //Call the “phoneVerification” method from the Authy API and pass the phone number, country code and verification channel(whether sms or call) as parameters to this method.
      $response = $this->authy->phoneVerificationStart($request->phone, $request->country_code, $request->via);
     
      if ($response->ok()) {
          print $response->message();
      } else  {
          print $response->message();
      }
  }

  public function verifyCode(Request $request) {
      // Call the method responsible for checking the verification code sent.
      $response = $this->authy->phoneVerificationCheck($request->phone, $request->country_code, $request->code);
      if($response->ok()) {
          print $response->message();
      } else {
          print $response->message();
      }
  }

  public function sendSMS(Request $request) {
      $this->validate($request, [
          'phone' => 'required|string',
          'message' => 'required|string'
      ]);

$phone = $this->authy->phoneInfo( $request->phone, '1' );



       if ( 'landline' == $phone->bodyvar('type') ) {

           return redirect()->back()->withErrors( [ 'This is a landline' ] );

       }


      // Create REST API Client

       $client = new Client($this->sid, $this->authToken);

      try {
          $sms = $client->messages->create($request->phone,
              [
                  'from' => $this->twilioFrom,
                  'body' => $request->message
              ]
          );

          if($sms) {
              return redirect()->back()->with('success', 'SMS sent successfully');
          } else {
              return redirect()->back()->with('error', 'SMS failed!');
          }
      } catch(Exception $e) {
          echo 'Error: ' . $e->getMessage();
      }
  }
}

Testing

With all this done, you will want to see how this works. All you need to do is start your development server using the command below in your terminal(Unix)/Command Prompt(Windows).

$ php artisan serve

Now, using your preferred browser, visit http://localhost:8000/verify (for phone verification) or http://localhost:8000/send-sms (for sending SMS). Fill in the forms and submit. On /send-sms, input a landline number to test Authy’s phone information API. On submit, it should return an error.

Conclusion

Following this, you can see how easy it is to verify phone numbers and also send out SMS using the Twilio service. Now you can go ahead and build awesome communication-based projects.

 

Ugendu Martins Ositadinma
Email: ugendu04@gmail.com
Twitter: https://twitter.com/ohssie_
Github: https://github.com/ohssie