In today's world where online shopping is at an all-time high, the chances of your e-commerce site standing out are going to be based on how much you can get your customers to trust in your service(s) and the level of satisfaction gotten from using them. One way of improving customer satisfaction and "trust" in your online shop is by allowing your customers to gain knowledge about the current state of their package.
An order tracking system will allow your customers to gain more information about the current status/location of their package. Doing this will help increase the satisfaction of your customers, as they too will have detailed insight into where their package is at any given point in time until it arrives at their desired location.
In this tutorial, you will learn how to use Twilio’s Programmable SMS to create an order tracking system using Laravel and update users about their package(s) via SMS.
In order to follow this tutorial, you will need:
- Basic knowledge of Laravel
- Laravel installed on your local machine
- Composer globally installed
- MySQL setup on your local machine
- Twilio Account
We will begin by creating a new Laravel project. This can be done either using the Laravel installer or Composer. In this tutorial we will be making use of the Laravel installer. If you don’t have it installed, you can learn how to set it up from the Laravel documentation. To generate a Laravel project using the Laravel Installer, run the following command on your terminal:
$ laravel new order-tracking-sms
Next, set up a database for the application. For this tutorial, we will make use of a MySQL database. If you don't have MySQL installed on your local machine, head over to the official site to get it installed on your platform of choice. After successful installation, open up your terminal and run the following to login to MySQL:
$ mysql -u {your_user_name}
NOTE: Add the -p
flag if you have a password for your MySQL instance.
Once you are logged in, run the following command to create a new database:
mysql> create database order-tracking;
mysql> exit;
Next, update your .env
file with your database credentials. Open up .env
and make the following adjustments:
DB_DATABASE=order-tracking
DB_USERNAME={your_user_name}
DB_PASSWORD={password if any}
Next, install the Twilio SDK for PHP via Composer. Open up a terminal and run the following to install the Twilio SDK:
$ composer require twilio/sdk
If you don’t have Composer installed on your local machine you can do so by following the instructions in their documentation.
After the successful installation of the Twilio SDK, you need to also fetch your Twilio credentials and your active Twilio phone number from your Twilio console. Head over to your console and grab your account_sid
and auth_token.
Now navigate to the Phone Number section to get your SMS enabled phone number.
If you don’t have an active number, you can easily create one here. This is the phone number you will use for sending and receiving SMS and also making phone calls via Twilio.
Next, update your .env
file with the credentials. Open .env
located at the root of the project directory and add these values:
TWILIO_SID="INSERT YOUR TWILIO SID HERE"
TWILIO_AUTH_TOKEN="INSERT YOUR TWILIO TOKEN HERE"
TWILIO_NUMBER="INSERT YOUR TWILIO NUMBER IN [E.164] FORMAT"
At this point, you should have your base project ready! In order to complete this tutorial you will need to create a table that will hold the mock orders data for the application. To create the orders table, run the following command to generate an Eloquent model alongside a migration file which will hold the definitions for the orders table:
$ php artisan make:model Orders --migration
Now, open the create_orders_table
migration file (database/migrations/{timestamp}_create_orders_table.php
) and make the following changes:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateOrdersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('orders', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('order_id');
$table->string('current_location');
$table->string('last_location');
$table->string('status');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('orders');
}
}
Next, execute the migration to actually commit the changes to your database. To do this, open up a terminal and run the following:
$ php artisan migrate
Next, you will need to setup seeders for your database. This will be used to seed the Orders table with some sample data. To do this, generate a seeder class using the artisan
command:
$ php artisan make:seeder OrdersTableSeeder
Now, open up the just generated database/seeds/OrdersTableSeeder.php
file and make the following changes:
<?php
use Faker\Generator as Faker;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class OrdersTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run(Faker $faker)
{
DB::table('orders')->insert([
[
'order_id' => Str::random(10),
'current_location' => $faker->streetAddress,
'last_location' => $faker->streetAddress,
'status' => "approved",
],
[
'order_id' => Str::random(10),
'current_location' => $faker->streetAddress,
'last_location' => $faker->streetAddress,
'status' => "delivered",
],
[
'order_id' => Str::random(10),
'current_location' => $faker->streetAddress,
'last_location' => $faker->streetAddress,
'status' => "in transit",
],
[
'order_id' => Str::random(10),
'current_location' => $faker->streetAddress,
'last_location' => $faker->streetAddress,
'status' => "awaiting approval",
],
]);
}
}
This will create four dummy orders in your Orders table which will serve as the placed orders for this tutorial. Now open up your terminal and run the following to actually seed your database with the data:
$ php artisan db:seed --class=OrdersTableSeeder
At this point, you should have some test data in your database which will be used in the remaining part of this tutorial. First, generate a controller which will hold the logic for the application. Open up your terminal and run the following artisan
command to generate a controller class::
$ php artisan make:controller OrderController
Now, open up app/Http/Controllers/OrderController.php
and make the following changes:
<?php
namespace App\Http\Controllers;
use App\Orders;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Twilio\Rest\Client;
class OrderController extends Controller
{
/**
* Get a order using the order id.
*
* @param Request $request
* @return Response
*/
public function getOrder(Request $request)
{
$from = $request->input("From");
$body = $request->input("Body");
$order = Orders::where("order_id", $body)->first();
if (!$order) {
$response = "Invalid Order Id sent!";
} else {
$response = "Heres the current details of your order #{$order->order_id}: \n
Current location: {$order->current_location} \n
Previous location: {$order->last_location} \n
Status: {$order->status} \n
Arrival date: " . Carbon::tomorrow();
}
return $this->sendMessage($response, $from);
}
/**
* Sends sms to user using Twilio's programmable sms client
* @param string $message Body of sms
* @param string|array $recipients string or array of phone number of recepient
*/
private function sendMessage($message, $recipients)
{
$account_sid = getenv("TWILIO_SID");
$auth_token = getenv("TWILIO_AUTH_TOKEN");
$twilio_number = getenv("TWILIO_NUMBER");
$client = new Client($account_sid, $auth_token);
return $client->messages->create($recipients,
array('from' => $twilio_number, 'body' => $message));
}
}
The OrderController
now has two methods; getOrder
and sendMessage
. The getOrder()
method will be called whenever an order_id
is sent to your Twilio phone number. Upon receipt, an appropriate response is sent back to the sender based on the content of the message body. This method (getOrder
) gets the Body
of the SMS and also the sender's phone number from the body of the request which is sent by Twilio after receiving an SMS. After retrieving the SMS data, the Orders table is queried with the order_id
and a $response
is sent back to the sender using the sendMessage()
method depending on the results of the query.
The sendMessage()
method accepts two arguments; message
and recipients
. Internally, the sendMessage()
method makes use of Twilio programmable SMS SDK for sending out text messages:
/**
* Sends sms to user using Twilio's programmable sms client
* @param string $message Body of sms
* @param string|array $recipients string or array of phone number of recepient
*/
private function sendMessage($message, $recipients)
{
$account_sid = getenv("TWILIO_SID");
$auth_token = getenv("TWILIO_AUTH_TOKEN");
$twilio_number = getenv("TWILIO_NUMBER");
$client = new Client($account_sid, $auth_token);
return $client->messages->create($recipients,
array('from' => $twilio_number, 'body' => $message));
}
The Twilio Client SDK requires your Twilio credentials to be instantiated, using the built-in PHP getenv()
function. You can retrieve your Twilio credentials stored in your .env
from the earlier parts of this tutorial. After creating an instance of the Twilio Client, you can then proceed to send an SMS by calling the $client->messages->create()
method. This method accepts two arguments of a receiver which can either be a string
or an array
of phone numbers and an array with the properties of from
and body
where from
is your active Twilio phone number and body
is the text you want to be sent to the recipients.
The next step is to make the methods we just created accessible via a route that calls your controller method. Open routes/web.php
and make the following changes:
<?php
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
use App\Orders;
Route::get('/', function () {
return Orders::all();
});
Route::post('/order', "OrderController@getOrder");
NOTE: The GET /
route has been modified to return all the orders in your orders table as you will need to make use of an order_id
to test your application.
Before proceeding, you have to exclude your route from CSRF protection by adding your /order
route to the except
array in app/Http/Middleware/VerifyCsrfToken.php
:
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
class VerifyCsrfToken extends Middleware
{
/**
* Indicates whether the XSRF-TOKEN cookie should be set on the response.
*
* @var bool
*/
protected $addHttpCookie = true;
/**
* The URIs that should be excluded from CSRF verification.
*
* @var array
*/
protected $except = [
"/order"
];
}
As you might have figured, you will need a way to alert your application when an SMS is sent to your Twilio phone number. One of the best ways to allow such communication to your application from external services is via webhooks. Twilio supports using webhooks to send an HTTP request to your application after an event occurs, such as receiving an SMS or getting an incoming call. To allow Twilio to send this request to your application, you must first configure your webhook URL from your Twilio console.
Before your application can be accessed via a webhook, it must first be accessible remotely from the internet and not just your local machine. Luckily, this can easily be accomplished by using ngrok.
If you don’t have ngrok set up on your computer, head over to their official download page and follow the instructions to get it installed on your machine. If you already have it set up, then open up your terminal and run the following commands to start your Laravel application and expose it to the internet:
$ php artisan serve
Now open another instance of your terminal and run this command:
$ ngrok http 8000
NOTE: 8000
should be replaced with the port number that your Laravel application is running on.
After successful execution of the above command, you should see a screen similar to this:
Now, copy your forwarding
URL as this will be used shortly.
Next, you need to update the webhook URL for your Twilio phone number's SMS configuration. This will allow Twilio to forward requests to your application when an SMS message is received. Head over to the active phone number section in your Twilio console and select your active phone number from the list. This number will be used as the phone number for receiving messages. Scroll down to the "Messaging" section and update the webhook URL for the field labeled “A message comes in” as shown below. Be sure to append /order
to the end of your forwarding URL you copied earlier.
Awesome! Now that you have both your application running and exposed to the web, you can proceed to carry out the final test. Send a text message to your active Twilio number with any of the order_id
(this can be gotten by opening the /
route on your browser) and you should get a response back depending on the order_id
you sent.
You should now have a working SMS based order tracking system. You should have also learned how to make use of Laravel to accomplish this using Twilio’s programmable SMS and how to expose your local server using ngrok. If you would like to take a look at the complete source code for this tutorial, you can find it on Github.
I’d love to answer any question(s) you might have concerning this tutorial. You can reach me via:
- Email: brian.iyoha@gmail.com
- Twitter: thecodearcher
- GitHub: thecodearcher