Содержание

Описание сервиса

Сервис SMS Status позволяет пользователям отслеживать состояние отправленных SMS, а также переотправлять их при возникновении проблем с доставкой.

Для встраивания рекомендуется методом Script с использованием библиотеки SmsStatus.js (требуется jQuery версии 1.7.1 или выше).

Получение информации об SMS

Для получения информации по SMS обратитесь по URL вида: /Sms/{locale}/{timezone}/{format}/{id}

Параметры

  • Парамеры пути (path) URI:
    • {locale} - задаёт локаль вывода (например, ru-ru или en-us).
    • {timezone} - задаёт временную зону для представления дат. Список доступных зон можно посмотреть в документе по ссылке TimeZoneMapping.xml.
    • {format} - задаёт формат вывода информации.
    • {id} - идентификатор сообщения (secure ID).
  • Параметры строки запроса (query string):
    • Dtf - строка форматирования дат и времени. Необязательный. Задаётся в .NET формате.

Примеры URL

Объект, возвращаемый в форматах XML и JSON

При выводе информации в форматах XML и JSON присутствуют следующие поля:

  • SecureId - идентификатор сообщения.
  • Locale - локаль вывода.
  • Report - отчёт о сообщении. Содержит следующие поля:
    • Created - время создания SMS.
    • CreatedStr - строка, отображающая время создания SMS, в указанной локали и формате.
    • StatusUpdated - время последнего обновления статуса SMS.
    • StatusUpdatedStr - строка, отображающая время последнего обновления статуса SMS, в указанной локали и формате.
    • SendingRetries - количество попыток отправки.
    • ValidityPeriodMinutes - время жизни SMS в минутах.
    • ValidityPeriodStr - строка, отображающая время жизни SMS.
    • Status - текущее состояние сообщения.
    • StatusId - идентификатор текущего состояния сообщения.
    • StatusDetails - детальное описание статуса. В данный момент содержит краткое описание причины недоставки (1-2 предложения).
    • StatusInstruction - инструкции для пользователя по исправлению проблемы с доставкой. Также в инструкции может быть более детальное описание проблемы.
    • Resendable - может ли данное сообщение быть переотправлено по запросу пользователя в данный момент.
    • UntilResendableSeconds - количество времени в секундах до того, как сообщение сможет быть переотправлено по запросу пользователя. Поле принимает значение null либо отсутствует, если сообщение никто не сможет быть переотправлено или время неизвестно.
    • UntilResendableStr - строка, отображающая количество времени до того, как сообщение сможет быть переотправлено по запросу пользователя. Поле принимает значение null либо отсутствует, если сообщение никто не сможет быть переотправлено или время неизвестно.
    • IsFinalState - может ли состояние сообщения поменяться без явного участия пользователя или технической поддержки. Если флаг поднят, то следует прекратить опрос состояния сообщения.
    • SendingAtempts - отчёты об отдельных попытках отправить SMS. Поля отчёта:
      • AttemptNumber - номер попытки.
      • Created - время попытки.
      • CreatedStr - строка, отображающая время попытки, в указанной локали и формате.
      • Updated - время последнего обновления состояния попытки.
      • UpdatedStr - строка, отображающая время последнего обновления состояния попытки, в указанной локали и формате.
      • Status - текущее состояние попытки.
      • StatusId - идентификатор текущего состояния попытки.

Значения StatusId сообщения

Пожалуйста, обратите внимение, что список статусов может быть расширен в будущих версиях.

Значение Имя статуса Пояснение
1 Buffered Сообщение ожидает отправки.
2 Sending Сообщение отправляется.
3 Delivered Сообщение доставлено.
4 Sent Сообщение отправлено.
5 Undelivered Невозможно доставить сообщение (например, абонент не доступен и время жизни сообщения истекло).
6 Blacklist Номер получателя заблокирован системой.
7 Suspended Не удалось отправить сообщение, ожидается повторная отправка.
8 HlrPending Сообщение отложено в ожидании идентификации SIM карты.
9 HlrMismatch Проверка идентификации SIM карты выявила несовпадение. Если пользователь сменил SIM карту, то он может пройти обновить разрешённый идентификатор SIM карты на WebMoney Securty.

Значения StatusId попытки отправки

Пожалуйста, обратите внимение, что список статусов может быть расширен в будущих версиях.

Значение Имя статуса Пояснение
0 NotSent Сообщение не отправлялось.
1 Accepted Сообщение принято для отправки.
10 SentOk Сообщение было отправлено (отправка подтверждена).
11 SendingFailPaid Отправка провалилась, обращение тарифицировано.
12 SendingFailNotPaid Отправка провалилась, обращение не тарифицировано.
20 DeliveryOk Сообщение доставлено.
21 DeliveryFailPaid Не удалось доставить сообщение, обращение тарифицировано.
22 DeliveryFailNotPaid Не удалось доставить сообщение, обращение не тарифицировано.

Тарификация попыток учитывается для автоматического продолжения попыток переотправки.

Переотправка SMS

Для переотправки сообщения сделайте POST-запрос на URL вида /Resend/{locale}/{timezone}/{format}/{id}

Параметры переотправки

  • Парамеры пути (path) URI:
    • {locale} - задаёт локаль вывода (например, ru-ru или en-us).
    • {timezone} - задаёт временную зону для представления дат. Необязательный. Не используется в текщей версии.
    • {format} - задаёт формат вывода информации.
    • {id} - идентификатор сообщения (secure ID).
  • Параметры строки запроса (query string):
    • Dtf - строка форматирования дат и времени. Необязательный. Не используется в текщей версии.

Результат переотправки

В результате переотправки в форматах XML и JSON присутствуют следующие поля:

  • SecureId - идентификатор сообщения.
  • Locale - локаль вывода.
  • Status - описание результата переотправки.

Форматы вывода

  • HtmlPage - законченная HTML-страница.
  • HtmlDiv - фрагмент HTML-страницы, состоящий из одного div с данными сообщения.
  • Xml - XML-документ с данными SMS.
  • Json - JSON-документ с данными SMS.
  • Script - JavaScript, вызывающий функцию (callback) с данными сообщения или результатом переотправки в качестве аргумента. Передаваемый в функцию объект идентичен выводимому в формате JSON. При получении отчёта вызывается функция sms_status_on_load_callback, при переотправке - sms_status_on_resend_callback. Функции sms_status_on_load_callback и sms_status_on_resend_callback должны быть определены на странице, куда будет встраиваться информация об SMS. Запрос на переотправку в формате Script может выполняться при помощи GET-запроса.

Пример встраивания при помощи скрипта

Встраивание скрипта позволяет определить callback, вызываемый при загрузке скрипта, и загружать скрипт с помощью тега script с нужным src. Для переотправки следует создать включить в DOM тег script с адресом страницы переотправки в src.

Обратные вызовы

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);
}

Функции перезагрузки скрипта, обновления данных сообщения и переотправки

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);
}

Изменение параметра date в строке запроса позволяет перезагружать скрипт (и обновлять данные), при этом контролируя время между обновлениями. Не следует обновлять данные слишком часто, это создаёт лишнюю нагрузку на сервер.

Функция инициализации страницы

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);
}

Тело страницы

<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>

CSS-стили страницы

.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

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;
    };
}

Реализация всплывающего окна

Скрипты

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);
}

Стили

/* 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;
}