be kind, this is my first question and my english is not very good.
I have no problem to deal with standard messages from Nexmo API and I want to receive long SMS just like I do with standard ones (i.e. in one block).
Exemple of data received from Nexmo for a standard SMS:
$_GET['msisdn'] ==> "33612345678" // "from"
$_GET['to'] ==> "33687654321"
$_GET['messageId'] ==> "02000000478EBE09"
$_GET['text'] ==> "Hello world!"
$_GET['type'] ==> "unicode"
$_GET['keyword'] ==> "HELLO"
$_GET['message-timestamp'] ==> "2014-11-25 14:06:58"
Long one: (Nexmo sent it piece by piece)
$_GET['msisdn'] ==> "33612345678" // "from"
$_GET['to'] ==> "33687654321"
$_GET['messageId'] ==> "02000000478EBE09"
$_GET['text'] ==> "the first part of a too long text..."
$_GET['type'] ==> "unicode"
$_GET['keyword'] ==> "THE"
$_GET['message-timestamp'] ==> "2014-11-25 12:06:58"
$_GET['concat'] ==> "true"
$_GET['concat-ref'] ==> "108" // unique identifier for long SMS text
$_GET['concat-total'] ==> "4" // or more, or less...
$_GET['concat-part'] ==> "1" // index of the part, start at 1
See more on the Nexmo documetation: Here
So, I started from a library found on github (Nexmo-PHP-lib) and did this: (pretty ugly but it's for test purpose)
public function inboundText( $data=null ){
if(!$data) $data = $_GET;
if(!isset($data['text'], $data['msisdn'], $data['to']))
return false;
if(isset($data['concat']) && $data['concat'])
{
session_start();
if ($data['concat-part'] > 1) // first part ?
{
if ($data['concat-total'] == $data['concat-part']) // last part ?
{
// last part ! stock the data in the text and unset now useless $_SESSION entry!
$data['text'] = $_SESSION[(string)$data['concat-ref']] . $data['text'];
unset($_SESSION[(string)$data['concat-ref']]);
}
else // not the first or the last, so concat !
{
// concat the new part in the entry named after the concat-ref
$_SESSION[(string)$data['concat-ref']] .= $data['text'];
return false;
}
}
else // first part ! so creat a $_SESSION entry for that! (named after concat-ref)
{
$_SESSION[(string)$data['concat-ref']] = $data['text'];
return false;
}
}
// Get the relevant data
$this->to = $data['to'];
$this->from = $data['msisdn'];
$this->text = $data['text'];
$this->network = (isset($data['network-code'])) ? $data['network-code'] : '';
$this->message_id = $data['messageId'];
// Flag that we have an inbound message
$this->inbound_message = true;
return true;
}
It works perfectly with local test but not when it's hosted on my heroku server, the $_SESSION array seems to be reset at each part of the sms...
So, have you any idea of how to handle it properly? (and without an ugly temporary SQL table). How can I retreive the previous part of the message until I receive it completely?
Using a session to store the temporary sms parts would only work if there is an exchange of keys between the client and server with each HTTP request which identifies the session.
In PHP, when you create a session and store a value inside
$_SESSION
a file is created on the server to store this data (unless you are using a DB session handler, in which case the session data is stored in a database). This data is referenced with an identifier (e.g.,PHPSESSID=66dda288eb1947843c2341b4e470fa28
) which is normally provided to the client as a cookie. When the client returns at the next HTTP request, the identifier is returned to the server as a cookie value, and the server uses this to reference the same session data.While your server may be providing the cookie to the Nexmo client when it connects to your endpoint URL, Nexmo is probably not storing the cookie and returning it with its next request. (This is an assumption on my part, but I think it is a safe one—although I can't explain why it works on your local machine but not Heroku. Anyways, it is easy to test—just check if the Nexmo client provides any
$_COOKIE
value during subsequent requests).Bottom line: if the Nexmo client doesn't use cookies to save state between requests, you cannot use sessions to save temporary sms parts.
A better option, in any case (because the temporary saved message parts would persist in case of a server reboot), would be to save each temporary part to a small database table. (Don't worry, it's a beautiful temporary SQL table. ;) Here's an example using MySQL:
Here I've defined a
UNIQUE KEY
so we can avoid duplicate message parts with aREPLACE INTO
clause (in case the Nexmo client tries to submit the same part twice). Theadded_datetime
can be used to clean up orphaned messages in the future (in case the final part of a message is never received).Now let's insert some sample data:
Now we can use MySQL's
GROUP_CONCAT
function to grab all the parts in one query.We set the
group_concat_max_len
setting so the total string length may be longer than the default 1024 characters (although that's already lots of message). Here's the result:If you're not using MySQL, you might need to do a bit more work (some duplication check and then a loop) without
REPLACE INTO
andGROUP_CONCAT
.Here is a full working example using this technique:
And here's how to use this function: