Save Voicemails to Dropbox with Twilio Voice API, PHP, and Laravel

April 17, 2019
Written by
Michael Jaroya
Contributor
Opinions expressed by Twilio contributors are their own

Save Voicemails to Dropbox with Twilio Voice API and Laravel.png

There are a number of ways to record calls with Twilio. Whichever method you decide to use, it is very important to keep the storage space used below the chargeable limit to prevent added cost. To achieve this, you need to backup up and delete your voice recording occasionally. Storage over 10,000 minutes per project is billed by the minute, once a month.

In this tutorial, we are going to discuss how to automate recordings management with recording status callback, download recordings programmatically via the REST API, save the recordings in Dropbox and finally delete the recordings programmatically via the REST API.

Prerequisites

You will need the following technologies and tools:

To follow along, you should have a basic understanding of PHP. Knowledge of the Laravel framework is not required. You can choose to use any other PHP framework of choice or even “Vanilla PHP”.

If you choose to use Laravel, a guide on how to install and use Laravel can be found in the official Laravel documentation.

Install Twilio SDK For PHP

To get started, we first need to install the Twilio SDK for PHP in our project.

In your terminal, navigate to the project directory and run the command below:

$ composer require twilio/sdk

Purchase A Twilio Phone Number

Next, we need to purchase a voice-enabled Twilio phone number. Follow the steps below:

  1. Login into your Twilio account and go to the console numbers page.
  2. Click the plus button to purchase a phone number if you don't have one already.

Twilio number dashboard

Set Environment Variables

Retrieve your Account SID and Auth Token from your console dashboard.

Go to the console numbers page and retrieve the phone number we created above and update the values in the .env file:

TWILIO_TOKEN='Auth Token'
ACCOUNT_SID='Account SID'
TWILIO_NUMBER='Twilio Number' #In E.164 format
RECEIVER_NUMBER='Receiver Number' #Your number that will receive the calls

Record An Outbound And Inbound Call

The first step is to create a route to generate TwiML for the outbound and inbound calls.

Run the following command to create the controller:

$ php artisan make:controller HomeController

Open the file app/Http/Controllers/HomeController.php and add the code below:

<?php
use Twilio\TwiML\VoiceResponse;

class HomeController extends Controller
{
  /**
   * TwiML for call
   * @return $this
   */
   public function Response(){
      $response = new VoiceResponse();
       $response->say('Please leave a message at the beep. Press the star key when finished.');
       $response->record(['maxLength' => 30, 'finishOnKey' => '*','action'=>'https://a62b61cb.ngrok.io/save', 'method' => 'GET']);
       $response->say('I did not receive a recording');

       echo $response;

   }
}

NOTE: Remember to update 'recordingStatusCallback' attribute with the route  in your application that will receive the request recording details once it is available for access.

Now, let's create the route we’ll hit to trigger the outbound call.

Open app/Http/Controllers/HomeController.php and add the function:

<?php
use Twilio\Rest\Client;

class HomeController extends Controller
{
    /**
    * make the call
    */
    public function Makecall() {

        $sid    = getenv('ACCOUNT_SID');
        $token  = getenv('TWILIO_TOKEN');
        $twilio_number = getenv('TWILIO_NUMBER');
        $receiver_number = getenv('RECEIVER_NUMBER');
        $twilio = new Client( $sid, $token );
        $call = $twilio->calls
            ->create( $receiver_number, // the receiver
            $twilio_number, // your voice enabled number from the console
            array( "url" => "BASE_URL/response" ) // path to the outbound TwiML url
        );
    }
}

Next, create the route to receive the recording details when on call completion. Add the code to the controller:

<?php

class HomeController extends Controller
{

    /**
     * save the Twilio recording
     */
    public function save(Request $request){
        $url = $request->RecordingUrl;
        $img = $request->CallSid . "_" . $request->RecordingSid . ".wav";
        file_put_contents( $img, file_get_contents( $url ) );
    }
}

To enable your Twilio phone number to receive inbound calls, you should configure it to send a request to your webhook. This can be done in the number's configuration page. If you’re unsure about how to generate a publicly accessible URL for your localhost, set up and run ngrok via the documentation.

In the Number settings, update the value for when “A call comes in” to BASE_URL/response.

Twilio webhook for Voice

Next, register the web routes to be used.

Inside routes/web.php, add these lines of code:

<?php
Route::post('/response', 'HomeController@Response');
Route::get('/makecall', 'HomeController@Makecall');
Route::get('/save', 'HomeController@save');

To ensure that the TwiML route can accept posted request from an external source without verification, inside app/Http/Middleware/VerifyCsrfToken.php, add the following code: 

<?php
/**
 * The URIs that should be excluded from CSRF verification.
 *
 * @var array
 */
protected $except = [
   'response'
];

Save The Recording In Dropbox

The next step is to save the recording in your Dropbox.

To use the Dropbox API, you’ll need an app. Follow the steps below to create the app:

  • Go to the Dropbox developers' page.
  • Choose “Dropbox API” as the API you intend to use.
  • Then choose the type of access you need and finally assign your app a name.

Dropbox new app guide

Install Dropbox Third Party API For PHP

Install the Dropbox Third Party API for PHP in our project.

In your terminal, navigate to the project directory and run the command below:

$ composer require kunalvarma05/dropbox-php-sdk

Update The Environment Variables

Retrieve your App key, App secret, and Access Token from your Dropbox Developer App Dashboard, by creating an application and update the values in the .env file:

DROPBOX_APP_KEY='App Key'
DROPBOX_APP_SECRET='App Secret'
DROPBOX_ACCESS_TOKEN='Access Token'

Create Save To Dropbox Script

Let’s create a function that will receive the recording and upload it to Dropbox through the Dropbox API.

Open app/Http/Controllers/HomeController.php and add upload  function:

<?php

use Kunnu\Dropbox\Dropbox;
use Kunnu\Dropbox\DropboxApp;
use Kunnu\Dropbox\DropboxFile;
use Kunnu\Dropbox\Exceptions\DropboxClientException;

class HomeController extends Controller {

    /**
     * upload recording to Dropbox account
     * @param $file_name
     */
    public function upload($file_name) {
        //Configure Dropbox Application
        $app = new DropboxApp( getenv('DROPBOX_APP_KEY'), getenv('DROPBOX_APP_SECRET'), getenv('DROPBOX_ACCESS_TOKEN') );

        //Configure Dropbox service
        $dropbox  = new Dropbox( $app );
        $fileName = $file_name;
        $filePath = $file_name;

        try {
            // Create Dropbox File from Path
            $dropboxFile = new DropboxFile( $filePath );

            // Upload the file to Dropbox
            $uploadedFile = $dropbox->upload( $dropboxFile, "/" . $fileName, [ 'autorename' => true ] );

            // File Uploaded
        } catch ( DropboxClientException $e ) {
             echo $e->getMessage();
        }
    }
}

Update the save  function with:

<?php
class HomeController extends Controller {
    /**
     * save the twilio recording
     */
    public function save( Request $request ) {
        $url = $request->RecordingUrl;
        $img = $request->CallSid . "_" . $request->RecordingSid . ".wav";
        file_put_contents( $img, file_get_contents( $url ) );
        $this->upload($img);
    }
}

Delete Twilio Recording

To delete the Twilio recording to create space and also delete the local copy.

Open app/Http/Controllers/HomeController.php and add the code below:

<?php
use Twilio\Rest\Client;

class HomeController extends Controller {
    /**
     * delete recording and local file
     * @param $RecordingSid
     * @param $file_name
     */
    public function delete($RecordingSid,$file_name){
        // Find your Account Sid and Auth Token at twilio.com/console
        $sid    = getenv('ACCOUNT_SID');
        $token  = getenv('TWILIO_TOKEN');
        $twilio = new Client($sid, $token);
        $twilio->recordings($RecordingSid)
               ->delete();
        // delete local copy
        unlink($file_name) or die("Couldn't delete file");
    }
}

Update the save  function to consume the function:

<?php
class HomeController extends Controller {
    /**
     * save the Twilio recording
     */
    public function save( Request $request ) {
        $url = $request->RecordingUrl;
        $img = $request->CallSid . "_" . $request->RecordingSid . ".wav";
        file_put_contents( $img, file_get_contents( $url ) );
        $this->upload($img);
        $this->delete($request->RecordingSid,$img);
    }
}

Test The App

That is it! Lets go ahead and test the app.

As a reminder, to test the app locally, you need to set up Ngrok.

Run the command below to expose our local web server running on port 8000 to the internet.

/.ngrok http 8000

Give your Twilio Number a call or visit “BASE_URL/makecall” to test. You should see a copy of the recording in your Dropbox account once you hang up.

Dropbox recent upload view

NOTE: Remember to update the BASE URLs we defined earlier with your production or ngrok base URL.

 

The complete code for the tutorial can be found on Github.

What Next

If you choose to record calls, you need to comply with certain laws and regulations, including those regarding obtaining consent to record. Additional information on the legal implications of call recording can be found here.

 

By: Michael Jaroya
Twitter:@mikelidbary
website:www.talwork.net