Contents

Service description

SMS Status service allows end-users to track status of the SMS sent to them and resend the messages if message delivery fails.

It is recommended to use Script embedding methods with the SmsStatus.js library (jQuery version 1.7.1 or newer is required).

Getting information about SMS

Send a GET-request to a URL matching the following template to get SMS data: /Sms/{locale}/{timezone}/{format}/{id}

Parameters

  • URI path parameters:
    • {locale} - sets the locale (for example, ru-ru, or en-us).
    • {timezone} - sets the time zone for dates. List of available time zones is available here: TimeZoneMapping.xml.
    • {format} - specifies the output format.
    • {id} - the message ID (secure ID).
  • URI query string parameters:
    • Dtf - dates and time formatting string. Optional. The string must be in the .NET format.
    • UserData - An arbitrary string associated with the request by the request sender.

URL examples

XML and JSON object

Message data in XML and JSON formats contains the following fields:

  • SecureId - the message ID.
  • Locale - the output locale.
  • UserData - the string passed in the UserData parameter of the request.
  • Status - message status query outcome description.
  • StatusId - message status query outcome identifier.
  • Report - message status report. Contains the following fields:
    • Created - the time the message was created.
    • CreatedStr - string representing the time the message was created in the specified locale and format.
    • StatusUpdated - last message status update time.
    • StatusUpdatedStr - string representing last message status update time in the specified locale and format.
    • SendingRetries - the number of attempts to send.
    • ValidityPeriodMinutes - message lifetime in minutes.
    • ValidityPeriodStr - string representation of the SMS lifetime.
    • ValidUntil - the time message lifetime expires.
    • ValidUntilStr - the string representing the time message lifetime expires in the specified locale and format.
    • LastTransportTypeStr - the message transport used in the latest attempt to deliver the message.
    • LastTransportType - the identifier of the message transport used in the latest attempt to deliver the message.
    • Status - current message status.
    • StatusId - current message status identifier.
    • StatusDetails - a detailed description of current status. Currently contains brief delivery failure reasons description (1-2 sentences).
    • StatusInstruction - user instructions on how to fix delivery issues. May also contain more detailed description of the issue.
    • Resendable - indicates if the message can be resent on user request immediately.
    • UntilResendableSeconds - the time in seconds until the message can be resent on user request. The field is null or abscent if the message can not be resent or the time when the message becomes resendable is currently unknown.
    • UntilResendableStr - string representing the time until the message can be resent on user request. The field is null or abscent if the message can not be resent or the time when the message becomes resendable is currently unknown.
    • UntilResendableStrV2 - string representing the moment in time relative to the current moment when the message can be resent on user requestю This value is formatted according to CLDR. The field is null or abscent if the message can not be resent or the time when the message becomes resendable is currently unknown.
    • IsFinalState - indicates if message state can change without explicit user or tech support action. Message status poll should be stopped when this flag is on.
    • SendingAtempts - reports on attempts to send the SMS. Report fields:
      • AttemptNumber - the number of the attempt.
      • Created - the time the attempt was made.
      • CreatedStr - string representing the time the attempt was made in the specified locale and format.
      • Updated - the time of the last attempt status update.
      • UpdatedStr - string representing the time of the last attempt status update in the specified locale and format.
      • Status - current attempt status.
      • StatusId - current attempt status identifier.
      • TransportTypeStr - the message transport used in this attempt to deliver the message.
      • TransportType - the identifier of the message transport used in this attempt to deliver the message.

Status query result StatusId values

Please note that the request results list can be extended in future releases.

Value Result name Description
0 Ok The message report was successfully created.
3 NotFound The message was not found.

StatusInstruction value

The instructions are formatted as an HTML document fragment. The instructions may contain the following elements:

  • An element or elements with attribute data-sms-status-instruction="until-resendable" - the value of the UntilResendableStrV2 field.
  • An element or elements with attribute data-sms-status-instruction="resendable-later" - a note informing the user that the message can be resent later (after UntilResendableSeconds).
  • An element or elements with attribute data-sms-status-instruction="delivered" - a note informing the user that a delivered message can be resent later (after an indeterminate amount of time).
  • An element or elements with attribute data-sms-status-instruction="promo" - additional general information (e.g. about confirmation using E-NUM).
  • An element or elements with CSS class "sms-status-instruction-image" - images. Note that img elements as well as svg elements may be used.

Message StatusId values

Please note that the status list can be extended in future releases.

Value Status name Description
1 Buffered The message is queued for sending.
2 Sending The message is being sent.
3 Delivered The message is delivered.
4 Sent Them message is sent.
5 Undelivered Message could not be delivered (e.g., subscriber is unavailable and message has expired).
6 Blacklist Receiver phone number is blacklisted.
7 Suspended Sending attempt failed, the message is waiting to be resent.
8 HlrPending The message is waiting for SIM card identification to complete.
9 HlrMismatch SIM card identity mismatch. If the client has changed the SIM card he can update the allowed SIM card identity on WebMoney Securty.

Delivery attempts StatusId values

Please note that the status list can be extended in future releases.

Value Status name Description
0 NotSent The message was not sent.
1 Accepted The message is accepted for sending.
10 SentOk The message is sent (sending is confirmed).
11 SendingFailPaid The message could not be sent, the attempt is tariffed.
12 SendingFailNotPaid The message could not be sent, the attempt is not tariffed.
20 DeliveryOk The message is delivered.
21 DeliveryFailPaid The message could not be delivered, the attempt is tariffed.
22 DeliveryFailNotPaid The message could not be delivered, the attempt is not tariffed.

Message LastTransportType and sending attempt TransportType values

Please note that the transport list can be extended in future releases.

Value Transport name Description
1 Sms The message was sent in a plain SMS.
2 VoiceCall A call will be made to the receiver phone number and the message will be read aloud.
3 InternetMessenger The message was sent to a messenger service (e.g. Telegram).
4 WmPush The message was sent in a push-notification to WebMoney mobile application.
5 CallPassword The receiver phone number will receive a call from a phone number ending with the code.

Attempt tariffication affects whether further automatic attempts to resend the message are made.

Resending messages

Perform POST-request to a URL matching the following template to resend a message: /Resend/{locale}/{timezone}/{format}/{id}

Resend parameters

  • URI path parameters:
    • {locale} - sets the locale (for example, ru-ru, or en-us).
    • {timezone} - sets the time zone for dates. List of available time zones is available here: TimeZoneMapping.xml.
    • {format} - specifies the output format.
    • {id} - the message ID (secure ID).
  • URI query string parameters:
    • Dtf - dates and time formatting string. Optional. The string must be in the .NET format.
    • UserData - An arbitrary string associated with the request by the request sender.

Resending result

Resending result in XML and JSON formats contains the following fields:

  • SecureId - the message ID.
  • Locale - the output locale.
  • UserData - the string passed in the UserData parameter of the request.
  • Status - reseding outcome description.
  • StatusId - reseding outcome identifier.
  • Report - message status report completed after the message was resent. The report is identical to the Report field in XML and JSON object.

Resending result StatusId values

Please note that the resending outcomes list can be extended in future releases.

Value Result name Description
0 Ok The message was successfully resent.
1 TryAgainLater The message can not be resent now but it may be resent later.
2 Unresendable The message can not be resent.
3 NotFound The message was not found.
4 TooManyResends Resend requests limit is exceeded.

Output formats

  • HtmlPage - a complete HTML-page.
  • HtmlDiv - an HTML page fragment consisting of a single div with the message data.
  • Xml - XML document with SMS data.
  • Json - JSON document with SMS data.
  • Script - JavaScript calling a callback function passing message data or resending request result as a parameter. The object passed to the function is identical to the one returned in the JSON document. sms_status_on_load_callback function is called when a message status report is retreived. sms_status_on_resend_callback function is called to process resending request result. sms_status_on_load_callback and sms_status_on_resend_callback functions must be defined on the page the script being embedded in. A GET request may be used to resend a message using Script output format.

Sample embedding using a script

Embedding script allows you to define callback function called when loading a script and load the script using a script tag with the correct src. Create a script tag with resending URL in the src attribute and insert it in the DOM to resend a message.

Callbacks

var status_update_timeout = 10000;

var sms_poll_id = undefined;
function sms_status_on_load_callback(response) {
    /// <summary>The callback function called by the SmsStatus script when
    /// message report is requested as JavaScript.
    /// </summary>
    /// <param name="response" optional="false" mayBeNull="false">
    /// The server response to the report request.
    /// </param>
    if (sms_poll_id !== undefined) {
        clearTimeout(sms_poll_id);
    }

    var report = response.Report;
    if (report !== null) {
        set_text('report-created', report.Created.toLocaleString());
        set_text('report-retries', report.SendingRetries);
        set_text('report-validity', report.ValidityPeriodMinutes);
        set_text('report-status', report.Status);

        set_text('report-status-description', (report.StatusDetails || '') + ' ');

        var instruction = report.StatusInstruction  || '';
        var hide_instruction = (instruction === '' && !report.Resendable);
        set_hidden('report-show-instruction-button', hide_instruction);
        set_text('report-show-instruction', report.StatusInstruction);

        set_hidden('message-resend-button', !report.Resendable);

        if (!response.Report.IsFinalState) {
            sms_poll_id = setTimeout(reload_script, status_update_timeout);
        }
    }
}

function sms_status_on_resend_callback(response) {
    /// <summary>The callback function called by the SmsStatus script when
    /// message resend result is requested as JavaScript.
    /// </summary>
    /// <param name="response" optional="false" mayBeNull="false">
    /// The server response to the resend request.
    /// </param>

    var resend_result = document.getElementById('resend-result');
    set_hidden(resend_result, false);
    set_text(resend_result, response.Status);

    sms_poll_id = setTimeout(reload_script, 1);
}

Script reloading, data update and resending functions

var status_url_base = 'http://sms.webmoney.ru/SmsStatus/Sms/ru-ru/Script/SecurID_1_12345678901234567890123456';
var resend_url_base = 'http://sms.webmoney.ru/SmsStatus/Resend/ru-ru/Script/SecurID_1_12345678901234567890123456';

function load_script(url) {
    /// <summary>Loads and executes JavaScript at the specified URL using GET.
    /// </summary>
    /// <param name="url" type="string" optional="false" mayBeNull="false">
    /// The script URL.
    /// </param>
    var elems = document.getElementsByClassName('script-in-action');
    var script_fired = false;

    for (var i = 0; i < elems.length && !script_fired; i++) {
        var node = elems[i];
        var scripts = node.getElementsByTagName('script');
        for (var j = 0; j < scripts.length && !script_fired; j++) {
            var old_script = scripts[j];
            var new_script = document.createElement('script');
            new_script.type = old_script.type;
            new_script.src = url;

            node.replaceChild(new_script, scripts[j]);

            script_fired = true;
        }
    }
}

function reload_script() {
    /// <summary>Reloads script contating the message report from the server.</summary>
    var now = new Date();
    var url = status_url_base + '?date=' + now.getHours() + now.getMinutes();
    load_script(url);
}

function resend_message() {
    /// <summary>Resends the message.</summary>
    var now = new Date();
    var url = resend_url_base + '?date=' + now.getHours() + now.getMinutes();
    load_script(url);
}

Changing the 'date' query string parameter allows to reload the script (and update the message data) while controlling the time between updates. You should not update the data too often, it is creates an extra load on the server.

Page initialization function

window.onload = function () {
    document.getElementById('reload').onclick = reload_script;
    document.getElementById('report-show-instruction-button').onclick = function () {
        set_hidden('resend-result', true);
        show_pop_up('pop-up')
    };
    document.getElementById('pop-up-close-button').onclick = function () { hide_pop_up('pop-up') };
    document.getElementById('message-resend-button').onclick = resend_message;

    sms_poll_id = setTimeout(reload_script, 1);
}

The page body

<div class="script-in-action">
    <p>
        <button id="reload">Refresh</button>
    </p>
    <div class="sms-status-report">
      <div class="sms-status-report-field">
        <span>Created: </span>
        <span id="report-created"></span>
      </div>
      <div class="sms-status-report-field">
        <span>Sending attempts: </span>
        <span id="report-retries"></span>
      </div>
      <div class="sms-status-report-field">
        <span>Timespan: </span>
        <span id="report-validity"></span>
      </div>
      <div class="sms-status-report-field">
        <span>Status: </span>
        <span id="report-status"></span>
      </div>
      <div class="sms-status-report-field">
        <span>Status description: </span>
        <span>
            <span id="report-status-description"></span>
            <span id="report-show-instruction-button" class="hidden">[Details]</span>
        </span>
      </div>
    </div>
    <div id="pop-up" class="hidden">
        <div class="pop-up-close"><span id="pop-up-close-button">Close</span></div>
        <div class="pop-up-content">
            <p id="report-show-instruction"></p>
            <p id="resend-result" class="hidden"></p>
            <button id="message-resend-button">Resend</button>
        </div>
    </div>
    <script type="text/javascript"></script>
</div>
<div id="blanket" class="hidden"></div>

The CSS styles of the page

.hidden
{
    display: none;
}
.sms-status-report
{
    width: 100%;
}
.sms-status-report-field
{
    display: table;
    width: 100%;
}
.sms-status-report-field>span
{
    display: table-cell;
    width: 75%;
}
.sms-status-report-field>span:first-child
{
    width: 25%;
}
#report-show-instruction-button
{
    cursor: pointer;
    text-decoration: underline;
}

DOM manipulation utility functions

function set_text(node, text) {
    /// <summary>Sets the text of the specified node to the specified value.
    /// </summary>
    /// <param name="node" type="HTMLElement|string" optional="false" mayBeNull="false">
    /// The node to receive the specified text or its id.
    /// </param>
    /// <param name="text" type="string" optional="false" mayBeNull="false">
    /// The new node text value.
    /// </param>
    if (typeof (node) === 'string') {
        node = document.getElementById(node);
    }

    var childNodes = node.childNodes;
    var found = false;
    for (var i = 0; i < childNodes.length; i++) {
        var childNode = childNodes[i];
        if (childNode.nodeType === 3 || childNode === 4) {
            if (found) {
                node.removeChild(childNode);
            } else {
                childNode.nodeValue = text;
                found = true;
            }
        }
    }
    if (!found) {
        var textNode = document.createTextNode(text);
        node.appendChild(textNode);
    }
}

function get_text(node) {
    /// <summary>Gets the text of the specified node.
    /// </summary>
    /// <param name="node" type="HTMLElement|string" optional="false" mayBeNull="false">
    /// The node to receive the specified text or its id.
    /// </param>
    if (typeof (node) === 'string') {
        node = document.getElementById(node);
    }

    var result = '';
    var childNodes = node.childNodes;

    for (var i = 0; i < childNodes.length; i++) {
        var childNode = childNodes[i];
        if (childNode.nodeType === 3 || childNode.nodeType === 4) {
            result += childNode.nodeValue;
        }
    }

    return result;
}


function set_hidden(element, hide) {
    /// <summary>Sets the display mode of the specified element by
    /// adding or removing 'hidden' class to its CSS classes list.
    /// </summary>
    /// <param name="element" type="HTMLElement|string" optional="false" mayBeNull="false">
    /// The node to receive the specified text or its id.
    /// </param>
    /// <param name="hide" type="boolean" optional="false" mayBeNull="false">
    /// Set to <c>true</c> to hide the element;
    /// set to <c>false</c> to display it.
    /// </param>
    var hidden_class = 'hidden';
    var hidden_re = new RegExp('\\b' + hidden_class + '\\b', 'gi');

    if (typeof (element) === 'string') {
        element = document.getElementById(element);
    }

    if (hide) {
        var existing = element.className;
        if (existing !== undefined && existing !== null) {
            if (!hidden_re.test(existing)) {
                if (existing.length > 0 && existing.charAt(existing.length - 1) !== ' ') {
                    element.className = existing.concat(' ', hidden_class);
                } else {
                    element.className = existing.concat(hidden_class);
                }
            }
        } else {
            element.className = hidden_class;
        }
    } else {
        element.className = element.className.replace(hidden_re, '');
    }
}

if (document.getElementsByClassName === undefined) {
    document.getElementsByClassName = function (class_name) {
        /// <summary>Gets array of elements with the specified class name.
        /// </summary>
        /// <param name="class_name" type="string" optional="false" mayBeNull="false">
        /// The name of the class.
        /// </param>
        var result = [];
        var class_name_re = new RegExp('\\b' + class_name + '\\b', 'i');
        var elements = this.getElementsByTagName('*');
        for (var i = 0; i < elements.length; i++) {
            var element_class = elements[i].className;
            if (class_name_re.test(element_class)) {
                result.push(elem[i]);
            }
        }
        return result;
    };
}

Pop up window implementation

Scripts

function show_pop_up(element_id) {
    /// <summary>Displays the pop up element with the specified id.
    /// </summary>
    /// <param name="node" type="string" optional="false" mayBeNull="false">
    /// The if of the pop up element.
    /// </param>
    var blanket = document.getElementById('blanket');
    var pop_up = document.getElementById(element_id);

    set_hidden (blanket, false);
    set_hidden (pop_up, false);

    var doc_el = document.documentElement;
    var cl_w = doc_el.clientWidth;
    var cl_h = doc_el.clientHeight;
    var cl_l = doc_el.scrollLeft;
    var cl_t = doc_el.scrollTop;

    pop_up.style.left = Math.round(cl_l + (cl_w - pop_up.clientWidth) / 2) + 'px';
    pop_up.style.top = Math.round(cl_t + (cl_h - pop_up.clientHeight) / 3) + 'px';
}

function hide_pop_up(element_id) {
    /// <summary>Hides the pop up element with the specified id.
    /// </summary>
    /// <param name="node" type="string" optional="false" mayBeNull="false">
    /// The if of the pop up element.
    /// </param>
    var blanket = document.getElementById('blanket');
    var pop_up = document.getElementById(element_id);

    set_hidden (blanket, true);
    set_hidden (pop_up, true);
}

Styles

/* Pop up window  */
#blanket {
   background-color: #111;
   opacity: 0.65;               /* Non-IE */
   filter: Alpha(opacity=65);   /* IE */
   position: absolute;
   z-index: 9001;
   top: 0px;
   left: 0px;
   width: 100%;
   min-height: 100%;
   position: fixed;
}
#pop-up {
    position: absolute;
    opacity: 1.00;
    background-color: #ffffff;
    position: absolute;
    width: 450px;
    z-index: 9002;
    border: 2px solid #505050;
}
#pop-up>.pop-up-content
{
    padding: 5px 15px 25px 15px;
    width: 420px;
    height: 100%;
}
.pop-up-close
{
    padding: 5px 10px;
    position:relative;
    right: 20px;
    width: 100%;
    text-align: right;
}
.pop-up-close>span
{
    text-decoration: underline;
    cursor: pointer;
}