Create a Twilio Voice Pricing Calculator using PHP

May 28, 2020
Written by
Ugendu Ositadinma
Contributor
Opinions expressed by Twilio contributors are their own
Reviewed by

Create a Twilio Voice Pricing Calculator using PHP

A major concern when building web solutions with third-party services is estimating the costs of API requests. This tutorial will guide you through the process of finding the costs of voice calls for Twilio Programmable Voice, depending on the origin and destination.

Installation Requirements

Getting started with this tutorial, it is expected that you have the following modules/packages installed on your development machine:

Here is a guide that can be followed to  install Composer globally:

Creating the PHP project

Let’s create a folder named pricing on your local machine where the code will be housed.

Inside this folder, create an index.php file which will contain all the code for this tutorial.

Next, proceed to install Twilio's PHP SDK to call the necessary APIs needed for the functions to be shared. To achieve this, use Composer to install the dependency with the following command:

$ composer require twilio/sdk

Because we wouldn’t want private credentials such as your Twilio keys available to the public, you will create a .env file to store your environment variables. The .env file will be read using the popular PHP package vlucas/phpdotenv to store those variables.

To install the package, use the command below:

$ composer require vlucas/phpdotenv

Once the installation is complete, make sure to set the Twilio API credentials in your .env file, as they will be used for authenticating the email requests. Add the following block to the file:

TWILIO_ACCOUNT_SID=ACXXXXXXXXXXXXXXXXXXX
TWILIO_AUTH_TOKEN=your_auth_token
TWILIO_PHONE=your_twilio_phone_number

NOTE: Your Twilio credentials can be retrieved from the Twilio console. Your phone number can be purchased from the Active Numbers dashboard.

Next, create your index.php file and include the Composer autoloader, and the Twilio PHP SDK like so:

<?php
   // Required if your environment does not handle autoloading
   require __DIR__ . '/vendor/autoload.php';
   use Twilio\Rest\Client;

   $dotenv = Dotenv\Dotenv::createImmutable(__DIR__, '/.env');
   $dotenv->load();

After doing that, we will initialize the Twilio client so we can have a connection to the Twilio API using the Account SID and Auth Token. Add the following code:

   // Your Account SID and Auth Token from twilio.com/console
   $sid = getenv('TWILIO_ACCOUNT_SID');
   $token = getenv('TWILIO_AUTH_TOKEN');
   $twilioNumber = getenv('TWILIO_PHONE');
   $twilio = new Client($sid, $token);

Creating the View

It is important to have a visual interface where all code can be tested and viewed. For the sake of this guide, we will be calling it index.php. Add the following code to the created view, below the PHP code:

<!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <!-- Bootstrap CSS -->
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
  <title>PHP + Twilio Pricing API</title>
  <style>
    .container {
      padding-top: 50px;
    }
    p {
      font-size: 30px;
      font-weight: 700;
      text-align: center
    }
    .row {
      padding-top: 50px
    }
  </style>
</head>
<body>
  <div class="container">
    <p>PROGRAMMABLE VOICE</p>
    <div class="row">
      <div class="col-6">
        <div class="card">
          <h5 class="card-header">Fetch Number</h5>
          <div class="card-body">
            <form method="POST">
              <div class="form-group">
                <label for="phone_number">Phone number</label>
                <input type="text" class="form-control" name="phone_number" aria-describedby="numberHelp" required>
                <small id="numberHelp" class="form-text text-muted">Destination phone number.</small>
              </div>
              <input type="submit" name="fetch_number" class="btn btn-primary" value="Submit"/>
            </form>
          </div>
        </div>
      </div>
      <div class="col-6">
        <div class="card">
          <h5 class="card-header">Voice prices by origination number</h5>
          <div class="card-body">
            <form method="POST">
              <div class="form-group">
                <label for="destination_number">Destination number</label>
                <input type="text" class="form-control" name="destination_number" aria-describedby="numberHelp">
                <small id="numberHelp" class="form-text text-muted">Destination phone number.</small>
              </div>
              <input type="submit" name="price_by_origination" class="btn btn-primary" value="Submit"/>
            </form>
          </div>
        </div>
      </div>
    </div>
  </div>
  <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
  <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
  <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>

Fetching Number Information

The Twilio Programmable Voice API allows you to retrieve the prices required to make voice calls to phone numbers in specified countries and locations regardless of the origin country of the caller. To be able to access this information, add this code block below the existing PHP code:

  /** PROGRAMMABLE VOICE */
   if (!empty($_POST['fetch_number'])) {
     try {
       $phone = $_POST['phone_number'];
       /** Lookup the phone number to make sure it is valid before retrieving the pricing information */
       $validity = $twilio->lookups->v1->phoneNumbers($phone)->fetch();
       if($validity) {
         /** If the phone number is valid, proceed to retrieve the pricing information */
         $number = $twilio->pricing->v2->voice->numbers($phone)->fetch();
         if($number) {
           var_dump($number);
         } else  {
           echo 'Retrieving the information failed. Please try again';
         }
       } else {
         echo 'Invalid phone number. Please check it and retry';
       }
     } catch (Exception $e) {
       print 'Error: ' . $e->getMessage();
     }
   }
Voice prices by origination number form

Add the code below to determine the cost of the call from your Twilio number to the destination number:

/** PROGRAMMABLE VOICE */
if(!empty($_POST['price_by_origination'])) {
     try {
       $destinationNumber = $_POST['destination_number'];
       /** Lookup the phone number to make sure it is valid before retrieving the pricing information */
       $validity = $twilio->lookups->v1->phoneNumbers($destinationNumber)->fetch();
       if($validity) {
         /**
          * Call the API to retrieve the information for calls to the destination number.
          */
         $number = $twilio->pricing->v2->voice
                                             ->numbers($destinationNumber)
                                             ->fetch(['originationNumber' => $twilioNumber]);
         if($number) {
           var_dump($number);
         } else {
           print 'Retrieving the information failed. Please try again';
         }
       } else {
         echo 'Invalid phone number. Please check it and retry';
       }
     } catch (Exception $e) {
       print 'Error: ' . $e->getMessage();
     }
   }

Full Code

This is the complete code for this tutorial. If you haven’t already, copy and replace all of the code within your index.php file with the code below:

<?php
   // Required if your environment does not handle autoloading
   require __DIR__ . '/vendor/autoload.php';
   use Twilio\Rest\Client;

   $dotenv = Dotenv\Dotenv::createImmutable(__DIR__, '/.env');
   $dotenv->load();

   // Your Account SID and Auth Token from twilio.com/console
   $sid = getenv('TWILIO_ACCOUNT_SID');
   $token = getenv('TWILIO_AUTH_TOKEN');
   $twilioNumber = getenv('TWILIO_PHONE');
   $twilio = new Client($sid, $token);

   /** Retrieve a list of countries where Twilio phone number services are available */
   $phoneCountries = $twilio->pricing->phoneNumbers->countries->read();


   if (!empty($_POST['fetch_number'])) {
     try {
       $phone = $_POST['phone_number'];
       /** Lookup the phone number to make sure it is valid before retrieving the pricing information */
       $validity = $twilio->lookups->v1->phoneNumbers($phone)->fetch();
       if($validity) {
         /** If the phone number is valid, proceed to retrieve the pricing information */
         $number = $twilio->pricing->v2->voice->numbers($phone)->fetch();
         if($number) {
           var_dump($number);
         } else  {
           echo 'Retrieving the information failed. Please try again';
         }
       } else {
         echo 'Invalid phone number. Please check it and retry';
       }
     } catch (Exception $e) {
       print 'Error: ' . $e->getMessage();
     }
   }

   if(!empty($_POST['price_by_origination'])) {
     try {
       $destinationNumber = $_POST['destination_number'];
       /** Lookup the phone number to make sure it is valid before retrieving the pricing information */
       $validity = $twilio->lookups->v1->phoneNumbers($destinationNumber)->fetch();
       if($validity) {
         /**
          * Call the API to retrieve the information for calls to the destination number.
          */
         $number = $twilio->pricing->v2->voice
                                             ->numbers($destinationNumber)
                                             ->fetch(['originationNumber' => $twilioNumber]);
         if($number) {
           var_dump($number);
         } else {
           print 'Retrieving the information failed. Please try again';
         }
       } else {
         echo 'Invalid phone number. Please check it and retry';
       }
     } catch (Exception $e) {
       print 'Error: ' . $e->getMessage();
     }
   }
?>

<!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <!-- Bootstrap CSS -->
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
  <title>PHP + Twilio Pricing API</title>
  <style>
    .container {
      padding-top: 50px;
    }
    p {
      font-size: 30px;
      font-weight: 700;
      text-align: center
    }
    .row {
      padding-top: 50px
    }
  </style>
</head>
<body>
  <div class="container">
    <p>PROGRAMMABLE VOICE</p>
    <div class="row">
      <div class="col-6">
        <div class="card">
          <h5 class="card-header">Fetch Number</h5>
          <div class="card-body">
            <form method="POST">
              <div class="form-group">
                <label for="phone_number">Phone number</label>
                <input type="text" class="form-control" name="phone_number" aria-describedby="numberHelp" required>
                <small id="numberHelp" class="form-text text-muted">Destination phone number.</small>
              </div>
              <input type="submit" name="fetch_number" class="btn btn-primary" value="Submit"/>
            </form>
          </div>
        </div>
      </div>
      <div class="col-6">
        <div class="card">
          <h5 class="card-header">Voice prices by origination number</h5>
          <div class="card-body">
            <form method="POST">
              <div class="form-group">
                <label for="destination_number">Destination number</label>
                <input type="text" class="form-control" name="destination_number" aria-describedby="numberHelp">
                <small id="numberHelp" class="form-text text-muted">Destination phone number.</small>
              </div>
              <input type="submit" name="price_by_origination" class="btn btn-primary" value="Submit"/>
            </form>
          </div>
        </div>
      </div>
    </div>
  </div>
  <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
  <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
  <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>

Testing

To see the application in action, start up your development server using this command in the terminal:

$ php -S localhost:8000

Finally, using the web browser of your choice, visit http://localhost:8000. Fill in the forms and submit them to get the expected response.

Conclusion

Upon completing all of the enlisted steps, you can easily and successfully retrieve account-specific pricing for voice calls from different locations, and various telecommunication companies available in those locations, and lastly, the price for Twilio phone numbers.

This tutorial can also be extended to retrieve the call cost for various numbers on the go, and even create a trigger to either initiate calls (if the costs fall within your budget), or send out SMS and emails.

I will be delighted to see what you build and if for any reason you need my help with a task related to this tutorial, I will be glad to be of assistance. You can reach me through any of the channels provided below.

Ugendu Martins Ositadinma

  • Email: ugendu04@gmail.com
  • Twitter: https://twitter.com/ohssie_
  • Github: https://github.com/ohssie