Implement Two-Way SMS with PHP

SMS is used for various purposes these days. For example, major websites like Gmail and Facebook use SMS to improve their authentication process with multi-factor authentication and notifying users about the updates. These are one-way SMS applications since messages are sent only from these sites to the user.

Two-way SMS applications are more complex than one-way ones. In two-way SMS apps, a user can initiate a conversation by sending messages, and then the application responds according to the user’s commands.

In this article I will explain the process of two-way SMS interactions and show you how you can incorporate it in your PHP applications. There are many popular SMS gateways available around the world which provide two-way messaging; In my explanations here, I will be using Clickatell.

Two-Way SMS Life Cycle

The life cycle of two-way SMS can be divided into 4 main steps as shown below:

  1. User sends request to SMS gateway
  2. SMS gateway forwards request to application server
  3. Application server processes request and responds to SMS gateway
  4. SMS gateway forwards request back to user

Step 1 – User to SMS Gateway

The user initiates the conversation by sending an SMS message to the gateway. Initially it has to go through user’s mobile service provider. This part is not important to us since it is within the domain of the local service provider. Through the local service provider the message is received by the the SMS gateway.

The user obviously needs a specific number to send his messages to. You can use either shortcodes or dedicated long numbers (DID) specific to your application for two-way communication. These numbers are provided by SMS gateways, and normally you need to purchase these numbers.

A dedicated long number is a standard phone number, like +94112367899. A shortcode is a 4 – 6-digit code. Each have their own pros and cons:

  • Shortcodes are easier to remember than dedicated long numbers.
  • Dedicated numbers can be used globally while shortcodes are normally limited to a single service provider in a given country.
  • Dedicated long numbers can process a larger number of messages for a given time compared to shortcode numbers.

The choice whether to use a shortcode or dedicated long number is ultimately up to you.

Once the SMS is received by the gateway, it should be routed to the application for processing. Before the routing the message, the gateway needs to do two things:

  • Prepare the message data in a way that application can understand
  • Map an application URL to the dedicated long number or shortcode

Each gateway has its own methods for transferring data to the application server, though XML or SOAP over an HTTP connection are generally the most popular. The gateway should provide some sort of API documentation for which ever method is used.

The application developer has to create a specific entry point in the system to handle messages received from the gateway; this is called the application URL. The process of mapping application URLs to the dedicated number or shortcode varies from one gateway to another. Some allow the configuration directly through the user account interface, such as Clickatell does. If this option isn’t available, we have to contact the technical support resource for the gateway and provide them with the application URL to be configured.

Stage 2 – SMS Gateway to Application Server

The application owner then has to decide how to receive the data from the gateway. Clickatell allows you to specify this method inside the user account. If it’s not available, again you’ll need to contact the technical team of the particular gateway.

The following code example shows you how Clickatell sends the data via the HTTP GET method and now you can receive it. Other gateways will provide a similar method as well.

https://www.example.com/sms/sms.php?api_id=12345&from=279991235642&to=27123456789&timestamp=2008-08-0609:43:50&text=Hereisthe%20messagetext&charset=ISO-8859-1&udh=&moMsgId=b2aee337abd962489b123fda9c3480fa
<?php
$fromNo = $_GET["from"];
$toNo = $_GET["to"];
$message = $_GET["text"];
$msgID = $_GET["moMsgId"];

// Process the user command and generate output
...

And here’s an example where the data is POSTed as an XML document.

<?xml version="1.0"?>
<clickmo>
  <api_id>xxx</api_id>
  <moMsgId>fa6ba35b330ce1bc7e2008e5d92d57aa</moMsgId>
  <from>handset_number_here</from>
  <to>mo_number_here</to>
  <timestamp>2007-02-26 14:36:50</timestamp>
  <text>xxx</text>
  <charset>ISO-8859-1</charset>
  <udh></udh>
</clickmo>
<?php
$data = $_POST["data"];

$xmlDoc = new DOMDocument();
$xmlDoc->loadXML($data);

$fromNo = $xmlDoc->getElementsByTagName("from");
$fromNo = $fromNo->item(0)->nodeValue;

$toNo = $xmlDoc->getElementsByTagName("to");
$toNo = $toNo->item(0)->nodeValue;

$message = $xmlDoc->getElementsByTagName("text");
$message = $message->item(0)->nodeValue;

// Process User Message and Generate Response
...

The application needs to capture the incoming data using one of the available methods and process the user’s commands. In a simple scenario where user’s message is less than 160 characters, this code works perfectly. But what will happen if the message is more than 160 characters?

Let’s assume a television station starts an advertising campaign where users can send advertisements as SMS. Once the SMS is sent, the user will receive a time period from the server where the advertisement will be displayed. Advertisements are text only and will be displayed on the bottom of the screen. Let’s also assume we have the predefined format for sending messages as shown below.

advertisement sports title your advertisement title message content of your advertisement

All of the content in the message appears as value pairs. advertisement will be the label and sports will be the value representing the advertising category. Then, title is the next label and its value will be the heading of the advertisement. message is the final label and will be the content the user wants to display in the advertisement.

Depending on the length of the title and message, this SMS can have more than 160 characters. Every time a lengthy message is received, the gateway splits it into multiple 160-character parts. But still we have to handle those 2 parts as a single message.

If we use the previous code examples to parse the messages, parts 1 and 2 of the same message would be handled as two different messages. And since both parts do not have the full command, the application would send back an error to the user. UDH is the solution to this problem.

What is UDH?

UDH stands for User Data Header. When we send a lengthy message, the sending device (mobile phone) splits the message and sends it as separate messages. UDH values will be assigned to beginning of each message part so that receiving device can identify them as belonging to a single message and recombine them.

The UDH values for the earlier scenario would look like this:

Part 1 - 05 00 03 CC 02 01
Part 2 - 05 00 03 CC 02 02

The last two hex values will be the most important values in the UDH. The second to last digit is 02 in the above codes and defines the number of parts in the message. So, this message was split into two parts. If three parts were available, then this value should be 03, and so on. The next digit defines the part number of the message. 01 means it’s the first part, 02 mean the second part, etc.

Now we have what we need to know to process lengthier messages that were split up into multiple parts.

<?php
$fromNo = $_GET["from"];
$toNo = $_GET["to"];
$message = $_GET["text"];
$msgID = $_GET["moMsgId"];
$udh = $_GET["udh"];

$total = 1;
$count = 1;
if ($udh) {
    $tmp = str_split($udh, 2);
    $total = hexdec($tmp[4]);
    $count = hexdec($tmp[5]);
}

if ($count != $total) {
    // Save the message fragment in database
    saveMessagePart($db, $from, $message, $udh);
}
else if ($total != 1) {
	$prevParts = getMessageParts($db, $from);
	$message = $prevParts . $message;
}

// process $message
...

Now that we can handle a full message and act on it, this completes this stage of the request cycle. The next two stages show how the response is sent back to the user through the gateway.

Stage 3 and 4 – Application Server to SMS Gateway, Gateway to User

In the previous stage I explained the process up to receiving messages from the gateway and processing it within your application. Once the request is processed and the response is generated, we need to send it back to the gateway.

Generally, SMS gateways provide a callback URL for us to pass the response data. You usually have to provide the receiver’s number, the sender’s number, the message content, and some sort of authentication information. The exact parameters will vary according to the gateway, but for Clickatell they are to, from, text, and api_id, username, and password.

<?php
$message = array(
    "to" => 942288345,
    "from" => 944488345,
    "text" => "sample message",
    "api_id" => API_KEY,
    "user" => "myUsername",
    "password" => "secret"
);

$apiUrl = "http://api.clickatell.com/http/sendmsg?";
foreach ($message as $parameter => $value ) {
    $apiUrl .= $parameter . "=" . urlencode($value) . "&";
}
$apiUrl = rtrim($apiUrl, "&");

$ch = curl_init();
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
curl_setopt($ch, CURLOPT_URL, $apiUrl);

curl_exec($ch);
curl_close($ch);

The code sample above first encodes all of the parameters using urlencode() and appends them to the API’s callback URL. Then, we initialize a cURL request and call the URL. The response message has now been sent to the gateway, which concludes step 3.

Step 4 is straightforward and we don’t have to do anything in this part of the process. The gateway is responsible for sending all the messages in the correct order to the users mobile.

Summary

We started this tutorial by discussing what two-way SMS messaging is and why it is useful. Then, we discussed the process of two-way messaging through 4 major stages. Now you should be able to apply the concepts covered here with any given SMS gateway and implement two-way SMS in your PHP applications.

Image via Fotolia

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • http://www.serveradminblog.com SAb

    Clickatell is to expensive for some countries. SMSGlobal and Panacea works fine and they are much cheaper than Clickatell.

  • jay

    Thanks for sharing.

  • Viktor

    Hi Rakhitha Nimesh,
    Thanks.

  • bulk SMS service provider

    Nice article ! According to you , which is the best bulk SMS service provider?

    • http://www.innovativephp.com Rakhitha Nimesh

      Thanks for the comment.
      Clickatell is the best I have worked with so far :)

  • Andrew

    Hi Rakhitha
    thanks for a good, clear article. Looking at the code for receiving multi-part messages the code assumes that messages will always arrive in order. I’m sure this will normally be true but given the different routings that can be taken by IP packets I would not like to guarantee it. Your code has the advantage of making the processing simple to follow, which is good for an article, but for live use developers would need to write more defensive code to handle the situation where the messages came in out of order.

    • http://www.innovativephp.com Rakhitha Nimesh

      Hi Andrew
      Thanks for the comment and its a very good suggestion.

      Generally messages come in correct order. But there is a small possibility that they might arrive in incorrect order as well. So instead of appending parts, we can keep it in an array an append it into the correct position of the array according to the UDH value and then concatenate it later. Feel free to explain if I am wrong .

      • http://aasoftwares.net Joe

        Will the Device(mobile) Receiving the message have a problem if it receives messages in the wrong order?

        • http://www.innovativephp.com Rakhitha Nimesh

          Yes It can have problems and I have experienced problems in receiving messages properly when they are received in wrong order.

  • http://www.otoraby.com Omid

    I`m looking for it.
    Thanks! :)

  • Pardeep Kumar

    This article is good for beginner to know how 2 way sms works in php and thanks for providing a useful information.

  • http://www.itoctopus.com Fadi (itoctopus)

    I wonder whether SMS will still be relevant 2 years from now. There are much better and cheaper alternatives nowadays that will definitely render SMS obsolete worldwide in a couple of years.

    Thanks for sharing your code by the way!

  • jbohaj

    @ Fadi: Which are “sms alternatives”, please tell.

  • tomas

    you have to check http://www.2-waysms.com with api connection

  • Richard

    How to match the sending sms message with the receiving sms message? In case, we are doing two-way sms messaging.

    • http://www.innovativephp.com Rakhitha Nimesh

      Hi Richard
      Once the user sends the SMS to the application it will get and process the data. Then it will send the response to the receiving number.

      What do you mean by matching ? Please explain further.