A Few Notes about Twilio TwiML Transcriptions

twilio-logo-06
Twilio Logo

Recently, we had to create an Interactive Voice Response (IVR) application in PHP using the Twilio TwiML API. Part of this task involved retrieving transcriptions of the called party responses using the TwiML API, so they could be stored in the database.  While doing the work, we noticed some aspects that are not mentioned in the TwiML documentation:

Transcription callbacks do not contain session info.

If you set a session cookie for the TwiML calls, the responses will include said cookie, but not the transcription callbacks. To work around this, you can add GET parameters to the callback URL in the TwiML call.

Transcription callback URLs.

You can use full (https://example.com/twilio_app/callback_handler.php), or relative (twilio_app/callback_handler.php or callback_handler.php) URLs.

Empty voice responses do not generate a transcription.

When the called party leaves an empty voice response, the transcription callback is not generated. While developing the application we expected to receive an empty transcription, and we spent some time wondering what could be wrong in the code until Twilio Support told us about this behavior.

It seems other developers have also found this confusing, so it’s possible that Twilio will implement callbacks on empty transcriptions in the future.

If you need help with your Twilio application, you can contact us.

Advertisements

Measure Twice, Code Once (or How To Make Your GUI Pixel Perfect with GIMP)

GIMP logo
GIMP logo.

Several of the projects I’m currently managing, like MockupData and MockupScreens, have complex graphical user interfaces. I have noticed that it’s hard to make this kind of program pixel perfect just by trying to measure the sizes and distances by eye, especially if you have an old/bad/small screen, so here is a small tutorial showing why GIMP should be another of your development tools.

1. Download and install GIMP.

GIMP (acronym of GNU Image Manipulation Program) is open source and completely free. It runs on several platforms, including Windows, Mac OS and Linux. Installation is pretty straightforward: just download and run the installer for your platform in Windows and Mac OS. In Linux, it’s probably already installed; if not you should be able to install it using your favorite software package management utility from your distribution.

2. Take a screenshot of your GUI.

Focus the window you want to capture and then press Alt+Print Screen in windows or Control+Command+Shift+3 in Mac OS. For Linux  you can check this site, which also contains more options for Windows and Mac OS. Then, open GIMP and select Edit → Paste as → New Image.

Alternatively, drag and drop an existing screenshot image file into the GIMP title bar, or use the File menu item to open an existing disk file or an image URL.

3. Use the GIMP measuring tool.

Take a look at the following icons. Are these of the same size?

Original buttons
Original buttons.

Let’s use the GIMP measuring tool. First use the zoom so you get a big image on the screen, and then click on the Measure icon in the toolbox, and then make sure the Use Info window checkbox is enabled. Next, left click on the starting point and drag with the mouse to the ending one, then release the mouse button. The distance between the two points will be displayed on the screen:

Measuring the left button with GIMP
Measuring the left button with GIMP. Click to enlarge.

Now let’s measure the second one.

Measuring the right button with GIMP
Measuring the right button with GIMP. Click to enlarge.

There is a 5 pixel difference. We asked our developer to fix this and make some other changes to the buttons:

  • Making  them smaller, as they looked so big compared to other items in our app. We resized them from 35*26px (left) and 30*26px (right), to 28*22px (both).
  • Adding 2 pixels between the icons.
  • Make the font a bit smaller.
  • Place the plus and minus signs just under the shadow line (this is the line where the background color of the icon changes, thus giving a 3D effect).

Here is the result. You can download and zoom it with GIMP if you want to check the changes:

Fixed buttons
Fixed buttons.

4. Use the GIMP color picker.

Now let’s look at the following toolbar:

Original toolbar
Original toolbar.

Are all buttons of the same color? Let’s check it with the color picker tool. Click on the pointed icon in the toolbox, and then check that the Show info window option is enabled. Click on the background of the Go Screen button.

Using the GIMP color picker on one of the correct buttons
Using the GIMP color picker on one of the correct buttons. Click to enlarge.

We get a color value of  eae8ed. Let’s check the Toggle Comments one.

Using the GIMP color picker on the incorrect button
Using the GIMP color picker on the incorrect button. Click to Enlarge.

Now we get f6f6f2, so the colors are actually different. We also fixed it, and here is how it looks now:

Fixed toolbar
Fixed toolbar.

5. Conclusion.

The appearance of your product is as important as its functionality. With similar features and functionality, a user will choose the one with better appearance, and even if you can’t notice them in your old laptop, people with modern monitors will be able to see them. GIMP allows you to make sure that your GUI elements will look homogeneous to every user with little time and effort, while being completely free software.

Twilio Tutorial: Sending an SMS with the PHP REST API

Note: this post was previewed and approved by the customer.

Twilio Logo
Twilio Logo

Update: One day after publishing this post, Kevin from Twilio suggests in the comments to use the last version from Github instead the 3.2.3 twilio-php library zip archive from the Twilio page. That fixed an SSL certificate validation issue. This is what we call great support!

In a recent project, we used the Twilio REST API to send SMS messages. Here is a very simple tutorial about it.

If you need help integrating Twilio in your application, you can contact us.

1. Register your phone number with Twilio (or get  a production account).

At the time of writing this post, Twilio offers a trial account with $30 free credit. Just go to the Twilio site and create a new one. The trial account requires verification of the phone numbers you want to use with their service. You can do this, at no extra cost, by going to Numbers → Verify a number in their control panel. You will then receive a call to that number asking for confirmation.

For your caller ID, you can use the sandbox number you will find after logging in to, buy a number from them or use a verified number. Alternatively, you can upgrade your account to a production one, which will allow you to use any phone number (you have to register a credit card with them, but you don’t need to make a payment until you spend the initial $30 credit).

2. The configuration file

Now, download the twilio-php library from their site (I used version 3.2.3 for this tutorial), or get it from Github  and install it in your server (I used the twilio-lib directory). In the root of your site (or in your test dir) create a twilio.config.php file with the following:

require_once("twilio-lib/Twilio.php");

$AccountSid = "Your Account SID";
$AuthToken = "Your Auth Token";

Replace the values with the ones you will find after login into Twilio.

3. Send an SMS.

This is pretty straightforward:

require_once("twilio.config.php");

try {
    // Instantiate a new Twilio Rest Client
    $client = new Services_Twilio($AccountSid, $AuthToken);

    /*
     * If you get an "Services_Twilio_TinyHttpException: SSL certificate problem [...]";
     * exception, uncomment the two lines below. More about this issue at
     * http://unitstep.net/blog/2009/05/05/using-curl-in-php-to-access-https-ssltls-protected-sites/
     *
     * UPDATE: using a twilio-php library version newer than 3.2.3 or the last version
     * from Github fixes this issue, making the two lines below unnecessary.
     */

     // $http = new Services_Twilio_TinyHttp("https://api.twilio.com", array("curlopts" => array(CURLOPT_SSL_VERIFYPEER => false)));
     // $client = new Services_Twilio($AccountSid, $AuthToken, "2010-04-01", $http);

    /*
     * The number we are sending from, it must be a valid Twilio number
     * You can use the default number which you will find in the sandbox,
     * buy a number from them or port your own number to Twilio.
     */
    $from = "415-599-2671"; // this is the default sandbox number
    // The number we are sending to - any phone number
    $to = "A Phone Number";
    // The SMS body
    $message = "Testing the Twilio SMS REST API";

    // Send a new outgoing SMS
    $response = $client->account->sms_messages->create($from, $to, $message);

    // Get the delivery status
    echo $response->status;
} catch (Exception $e) {
    echo "Caught exception: " . $e->getMessage();
}

4. Check the results.

If everything went well, you will receive an SMS message in your phone. You can also go to Logs → SMS in the Twilio site and see the results there:

Twilio SMS Logs
Twilio SMS Logs Screen

Any questions? Feel free to post a comment.

Braintree Payments Tutorial: Managing Subscriptions with the Server-to-Server (S2S) API

Note: this post was previewed and approved by the customer.

Braintree Logo White Background
Braintree Payments Logo

Recently we integrated Braintree Payments as part of a sales lead routing site project . Here is a small tutorial based on the example we wrote to learn how their API works. Their documentation is great and easy to follow, but we found that it sometimes lacked detail so I had to find some things looking at their (excellent) PHP library source code.

The code is just a quick demo, so it’s far from perfect. However it will be fine for the purposes of this tutorial.

If you need help integrating Braintree in your site, feel free to contact us.

1. Set up a plan in the sandbox.

After signing up with Braintree, you will get an email with your sandbox credentials. For this tutorial, we will create one plan with one add-on.

Go to Recurring Billing → Add-ons and Discounts → New Add-on and create a new one. You should end with something like:

Braintree Create Add-on
Braintree add-on created. Click to enlarge.

Next, go to Recurring Billing → Plans → New and do the same but selecting the add-on you just created in the step above in the “add-ons” section. You should get something like:

Braintree Create a Plan
Braintree plan created. Click to enlarge.

Now we can start to code.

2. The configuration file.

You will find the api keys in their sandbox. Just go to Account → My User → Authorization → Api Keys.

Now, download or clone from Github their PHP Client Library (I used version 2.12.3 for this tutorial) and install it in your server (I used the braintree-lib directory).

In the root of your site (or in your test dir) create a braintree.config.php file with the following:

require_once('braintree-lib/Braintree.php');

Braintree_Configuration::environment('sandbox');
Braintree_Configuration::merchantId('yourmerchantId');
Braintree_Configuration::publicKey('yourpublicKey');
Braintree_Configuration::privateKey('yourprivateKey');

3. Create a customer record with a credit card.

You can do this in separate steps, but in this example we will do at once. Check that I have split the code in several parts, so you will have to join them.

require_once 'braintree.config.php';

$planId = 2000;
$addOnId = 1000;
$includeAddOn = false;

try {
    /* First we create a new user using the BT API */
    $result = Braintree_Customer::create(array(
                'firstName' => 'My First Name',
                'lastName' => 'My Last Name',
                'company' => 'My Company',
                // we can create a credit card at the same time
                'creditCard' => array(
                    'cardholderName' => 'My Name On Card',
                    'number' => '5105105105105100',
                    'expirationMonth' => "02",
                    'expirationYear' => "15",
                    'cvv' => '123',
                    'billingAddress' => array(
                        'firstName' => 'My Billing Address First Name',
                        'lastName' => 'My Billing Address Last Name',
                        'company' => 'My Billing Address Company',
                        'streetAddress' => 'My Billing Address Address',
                        'locality' => 'My Billing Address City',
                        'region' => 'IL', // Two letter code
                        'postalCode' => '60622',
                        'countryCodeAlpha2' => 'US'
                    )
                )
            ));
    if ($result->success) {
        echo("Customer ID: " . $result->customer->id . "
");
        echo("Credit card ID: " . $result->customer->creditCards[0]->token . "
");
    } else {
        foreach ($result->errors->deepAll() as $error) {
            echo($error->code . ": " . $error->message . "
");
        }
        exit;
    }

4. Create a subscription.

By default the subscription includes all associated add-ons, but you can remove them using an option.

    // Now we create a subscription
    $subscriptionData = array(
        'paymentMethodToken' => $result->customer->creditCards[0]->token,
        'planId' => $planId
    );

    // The addons are included by default, but we can remove them
    if (!$includeAddOn) {
        $subscriptionData['addOns'] = array(
            'remove' => array($addOnId)
        );
    }

    $result = Braintree_Subscription::create($subscriptionData);

    if ($result->success) {
        echo("Subscription ID: " . $result->subscription->id . "
");
        echo("Transaction ID: " . $result->subscription->transactions[0]->id . "
");
    } else {
        foreach ($result->errors->deepAll() as $error) {
            echo($error->code . ": " . $error->message . "
");
        }
        exit;
    }

5. Modify the subscription.

We add or remove the add-on depending on whether it had been added in the previous step.

When adding it, we can decide if we prorate the addon value. If not it will be charged next month.

    // we add or remove the addon depending on its state
    if (!$includeAddOn) {
        // add
        $result = Braintree_Subscription::update($result->subscription->id, array(
                    'options' => array(
                        'prorateCharges' => true,
                        'revertSubscriptionOnProrationFailure' => true
                    ),
                    'addOns' => array(
                        'add' => array(
                            array(
                                'inheritedFromId' => $addOnId
                            )
                        )
                    )
                ));
    } else {
        // remove
        $result = Braintree_Subscription::update($result->subscription->id, array(
                    'addOns' => array(
                        'remove' => array($addOnId)
                    )
                ));
    }

    if ($result->success) {
        echo("Subscription ID: " . $result->subscription->id . " updated
");
    } else {
        foreach ($result->errors->deepAll() as $error) {
            echo($error->code . ": " . $error->message . "
");
        }
        exit;
    }

6. Cancel the subscription.

This is pretty straightforward. In the last catch the getMessage() method of the thrown exception returns an empty string (a client library bug maybe?).

    // Finnally we cancel the subscription
    $result = Braintree_Subscription::cancel($result->subscription->id);

    if ($result->success) {
        echo("Subscription ID: " . $result->subscription->id . " cancelled
");
    } else {
        foreach ($result->errors->deepAll() as $error) {
            echo($error->code . ": " . $error->message . "
");
        }
        exit;
    }
} catch (Exception $e) {
    echo 'Caught exception: ' . $e . "
"; // $e->getMessage() is empty
}

7 .Check the result in the sandbox.

Go to Search → Subscriptions, click on “Search”, and then select the subscription id to be found in the output of the PHP program. If everything went right, you should find something like this:

Braintree Subscription Page
Braintree subscription page after running the program. Click to enlarge.