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:
- User sends request to SMS gateway
- SMS gateway forwards request to application server
- Application server processes request and responds to SMS gateway
- 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×tamp=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