Содержание

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

Сервис 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 формате.
    • UserData - произвольная строка ассоциированная с запросом.

Примеры URL

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

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

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

Значения StatusId ответа с информацией об SMS

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

Значение Имя результата Пояснение
0 Ok Отчёт успешно сформирован.
3 NotFound Сообщение не найдено.

Значение StatusInstruction

Инструкции форматируются как фрагмент документа в формате HTML. Инструкции могут содержать следующие элементы:

  • Элемент или элементы с атрибутом data-sms-status-instruction="until-resendable" - значение поля UntilResendableStrV2.
  • Элемент или элементы с атрибутом data-sms-status-instruction="resendable-later" - примечане о возможности переотправить сообщение позже (через UntilResendableSeconds).
  • Элемент или элементы с атрибутом data-sms-status-instruction="delivered" - примечание о возможности переотправить доставленное сообщение позже (через неопределённое время).
  • Элемент или элементы с атрибутом data-sms-status-instruction="promo" - дополнительная информация общего характера (например, о возможности подтверждения через E-NUM).
  • Элемент или элементы с классом CSS "sms-status-instruction-image" - изображения. Могут быть использованы как элементы img, так и svg.

Значения 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 Не удалось доставить сообщение, обращение не тарифицировано.

Значения LastTransportType сообщения и TransportType попытки отправки

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

Значение Имя траспорта Пояснение
1 Sms Сообщение отправлено в обычном SMS.
2 VoiceCall На номер получателя будет сделан звонок, сообщение будет зачитано голосом.
3 InternetMessenger Сообщение отправлено в мессенджер (например, Телеграм).
4 WmPush Сообщение отправлено пуш-уведомлением в мобильное приложение WebMoney.
5 CallPassword На номер получателя будет сделан звонок с номера, оканчивающегося на цифры кода.

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

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

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

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

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

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

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

  • SecureId - идентификатор сообщения.
  • Locale - локаль вывода.
  • UserData - строка, переданная в параметре запроса UserData.
  • Status - описание результата переотправки.
  • StatusId - результат переотправки сообщения.
  • Report - отчёт о состоянии сообщении послее переотправки. Отчёт идентичен полю Report, описанному в разделе Объект, возвращаемый в форматах XML и JSON.

Значения StatusId результата переотправки

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

Значение Имя результата Пояснение
0 Ok Сообщение успешно переотправлено.
1 TryAgainLater Переотправка в текущий момент невозможна, но может быть осуществлена позднее.
2 Unresendable Переотправка невозможна.
3 NotFound Сообщение не найдено.
4 TooManyResends Превышено максимальное число переотправок.

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

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