Библиотека стандартных подсистем
Картинка подсистемы «1С:Библиотека Стандартных Подсистем

Небольшая статья о том, как добавить нового провайдера SMS на примере конфигурации «Управление торговлей 11», используя библиотеку стандартных подсистем (БСП).Перед началом добавления нового провайдера услуг нужно убедиться в работоспособности его API. Поможет в этом замечательный инструмент-расширение к браузеру Google Chrome click.

Будем считать, что все тесты прошли успешно. Во-первых, нужно разрешить возможность редактирования общего модуля ОтправкаСМСПереопределяемый и перечисления ПровайдерыСМС:

Необходмо включить возможность изменения общего модуля в конфигурации.

Необходмо включить возможность изменения перечисления в конфигурации.


Во-вторых, добавить в перечисление ПровайдерыСМС название своего провайдера:

Необходимо добавить новый провайдер SMS в перечисление


В-третьих, выполнить настройку провайдера SMS, указать логин и пароль в базе данных. Вкладка «Администрирование»:

Указание параметров доступа для нового провайдера SMS в режиме «1С:Предприятие 8»


Далее нужно определить описание взаимодействия с API в общем модуле ОтправкаСМСПереопределяемый. Нужно переопределить 3 пустых процедуры:

// Проверяет правильность сохраненных настроек отправки SMS.
Процедура ПриПроверкеНастроекОтправкиSMS(НастройкиОтправкиSMS, Отказ)

// Отправляет SMS через настроенного поставщика услуги, возвращает идентификатор сообщения.
Процедура ОтправитьSMS(ПараметрыОтправки, Результат)

// Запрашивает статус доставки SMS у поставщика услуг.
Процедура СтатусДоставки(ИдентификаторСообщения, Провайдер, Логин, Пароль, Результат)

Важно, провайдер alphasms использует для коммуникации POST-запросы, на входе и выходе xml-файлы, у других провайдеров может быть все иначе (GET, POST, etc. и другие форматы).


Код процедуры ПриПроверкеНастроекОтправкиSMS у меня получился такой:

Процедура ПриПроверкеНастроекОтправкиSMS(НастройкиОтправкиSMS, Отказ) Экспорт

    Перем Провайдер, Логин, Пароль;

    Если ТипЗнч(НастройкиОтправкиSMS) = Тип("Структура") Тогда

        Если НастройкиОтправкиSMS.Свойство("Логин", Логин)
          И  НастройкиОтправкиSMS.Свойство("Пароль", Пароль)
          И  НастройкиОтправкиSMS.Свойство("Провайдер", Провайдер)Тогда

            Если Логин = Неопределено ИЛИ ПустаяСтрока(Логин) Тогда
                Отказ = Истина;
            КонецЕсли;

            Если Пароль = Неопределено ИЛИ ПустаяСтрока(Пароль) Тогда
                Отказ = Истина;
            КонецЕсли;

            Если Провайдер = Неопределено ИЛИ Провайдер = Перечисления.ПровайдерыSMS.ПустаяСсылка() Тогда
                Отказ = Истина;
            КонецЕсли;

        Иначе
            Отказ = Истина;
        КонецЕсли;

    Иначе
        Отказ = Истина;
    КонецЕсли;

КонецПроцедуры

Код отправки SMS у меня базировался на API провайдера:

  • тело POST запроса в кодировке «UTF-8»:XML-тело POST-запроса для отправки SMS
  • примерный ответ сервиса в результате успеха:XML-тело ответа на POST-запрос отправления SMS
  • примерный ответ сервиса в результате ошибки:XML-тело ответа при ошибке на POST-запрос отправления SMS
// Отправляет SMS через настроенного поставщика услуги, возвращает идентификатор сообщения.
//
// Параметры:
//  ПараметрыОтправки - Структура:
//      * Провайдер         - ПеречислениеСсылка.ПровайдерыSMS - поставщик услуги по отправке SMS.
//      * НомераПолучателей - Массив - массив строк номеров получателей в формате +7ХХХХХХХХХХ.
//      * Текст             - Строка - текст сообщения, максимальная длина у операторов может быть разной.
//      * ИмяОтправителя    - Строка - имя отправителя, которое будет отображаться вместо номера у получателей.
//      * Логин             - Строка - логин для доступа к услуге отправки SMS.
//      * Пароль            - Строка - пароль для доступа к услуге отправки SMS.
//  Результат - Структура - (возвращаемое значение):
//      * ОтправленныеСообщения  - Массив структур:
//      * НомерПолучателя        - Строка - номер получателя из массива НомераПолучателей;
//      * ИдентификаторСообщения - Строка - идентификатор SMS, по которому можно запросить статус отправки.
//      * ОписаниеОшибки         - Строка - пользовательское представление ошибки, если пустая строка, то ошибки нет.
//
Процедура ОтправитьSMS(ПараметрыОтправки, Результат) Экспорт

    Если ПараметрыОтправки.Провайдер = Перечисления.ПровайдерыSMS.AlfaSMS Тогда

        // проверка на заполнение обязательных параметров
        Если ПараметрыОтправки.НомераПолучателей.Количество() = 0 Или ПустаяСтрока(ПараметрыОтправки.Текст) Тогда
            Результат.ОписаниеОшибки = НСтр("ru = 'Неверные параметры сообщения'");
            Возврат;
        КонецЕсли;

        // отправка запроса
        ИмяФайлаОтвета = ВыполнитьЗапрос(ПараметрыОтправки);
        Если ПустаяСтрока(ИмяФайлаОтвета) Тогда
            Результат.ОписаниеОшибки = Результат.ОписаниеОшибки + НСтр("ru = 'Соединение не установлено'");
            Возврат;
        КонецЕсли;

        // обработка результата запроса (получение идентификаторов сообщений)
        СтруктураОтвета = Новый ЧтениеXML;
        СтруктураОтвета.ОткрытьФайл(ИмяФайлаОтвета);
        ОписаниеОшибки = "";
        ИндексНомера = 0;
        Пока СтруктураОтвета.Прочитать() Цикл
            Если СтруктураОтвета.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
                Если СтруктураОтвета.Имя = "msg" Тогда
                    ИдентификаторСообщения = "";
                    НомерПолучателя = "";
                    Пока СтруктураОтвета.ПрочитатьАтрибут() Цикл
                        Если СтруктураОтвета.Имя = "sms_id" Тогда
                            ИдентификаторСообщения = СтруктураОтвета.Значение;
                            НомерПолучателя = ФорматироватьНомер(ПараметрыОтправки.НомераПолучателей[ИндексНомера]);
                            ИндексНомера = ИндексНомера + 1;
                        КонецЕсли;
                    КонецЦикла;
                    Если Не ПустаяСтрока(НомерПолучателя) Тогда
                        ОтправленноеСообщение = Новый Структура("НомерПолучателя,ИдентификаторСообщения",
                                                             НомерПолучателя,ИдентификаторСообщения);
                        Результат.ОтправленныеСообщения.Добавить(ОтправленноеСообщение);
                    КонецЕсли;
                ИначеЕсли СтруктураОтвета.Имя = "error" Тогда
                    СтруктураОтвета.Прочитать();
                    ОписаниеОшибки = ОписаниеОшибки + СтруктураОтвета.Значение + Символы.ПС;
                КонецЕсли;
            КонецЕсли;
        КонецЦикла;
        СтруктураОтвета.Закрыть();
        УдалитьФайлы(ИмяФайлаОтвета);

        Результат.ОписаниеОшибки = СокрП(ОписаниеОшибки);

    КонецЕсли;

КонецПроцедуры // ОтправитьSMS()

Функция ВыполнитьЗапрос(ПараметрыЗапроса)

    Результат = "";

    ИмяФайлаЗапроса = СформироватьФайлДляPOSTЗапроса(ПараметрыЗапроса);
    ИмяФайлаОтвета = ПолучитьИмяВременногоФайла("xml");

    // формирование заголовка
    Заголовок = Новый Соответствие;
    Заголовок.Вставить("Content-Type", "application/x-www-form-urlencoded");
    Заголовок.Вставить("Content-Length", XMLСтрока(РазмерФайла(ИмяФайлаЗапроса)));

    // отправка запроса и получение ответа
    Попытка
        Соединение = Новый HTTPСоединение("alphasms.com.ua", , , , ПолучениеФайловИзИнтернетаКлиентСервер.ПолучитьПрокси("https"), 3);
        Соединение.ОтправитьДляОбработки(ИмяФайлаЗапроса, "api/xml.php", ИмяФайлаОтвета, Заголовок);
        Результат = ИмяФайлаОтвета;
    Исключение
        ЗаписьЖурналаРегистрации(
            НСтр("ru = 'Отправка SMS'", ОбщегоНазначенияКлиентСервер.КодОсновногоЯзыка()),
            УровеньЖурналаРегистрации.Ошибка,
            ,
            ,
            ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
    КонецПопытки;

    УдалитьФайлы(ИмяФайлаЗапроса);

    Возврат Результат;

КонецФункции // ВыполнитьЗапрос()

Функция СформироватьФайлДляPOSTЗапроса(ПараметрыЗапроса)

    ИмяФайлаЗапроса = ПолучитьИмяВременногоФайла("xml");

    ТелоЗапросаXML = Новый ЗаписьXML;
    ТелоЗапросаXML.ОткрытьФайл(ИмяФайлаЗапроса, "UTF-8");

    ТелоЗапросаXML.ЗаписатьОбъявлениеXML();
    ТелоЗапросаXML.ЗаписатьНачалоЭлемента("package");
        ТелоЗапросаXML.ЗаписатьАтрибут("login", ПараметрыЗапроса.Логин);
        ТелоЗапросаXML.ЗаписатьАтрибут("password", ПараметрыЗапроса.Пароль);
        Если ПараметрыЗапроса.Свойство("ИдентификаторСообщения") Тогда

            ТелоЗапросаXML.ЗаписатьНачалоЭлемента("status");
                ТелоЗапросаXML.ЗаписатьНачалоЭлемента("msg");
                    ТелоЗапросаXML.ЗаписатьАтрибут("sms_id", ПараметрыЗапроса.ИдентификаторСообщения);
                    ТелоЗапросаXML.ЗаписатьКонецЭлемента();
            ТелоЗапросаXML.ЗаписатьКонецЭлемента();

        Иначе

            ТелоЗапросаXML.ЗаписатьНачалоЭлемента("message");
            Для каждого НомераПолучателя Из ПараметрыЗапроса.НомераПолучателей Цикл
                ТелоЗапросаXML.ЗаписатьНачалоЭлемента("msg");
                    ТелоЗапросаXML.ЗаписатьАтрибут("recipient", ФорматироватьНомер(НомераПолучателя));
                    ТелоЗапросаXML.ЗаписатьАтрибут("sender", "KTC-ua.com");
                    ТелоЗапросаXML.ЗаписатьАтрибут("type", "0");
                    ТелоЗапросаXML.ЗаписатьТекст(ПараметрыЗапроса.Текст);
                ТелоЗапросаXML.ЗаписатьКонецЭлемента();
            КонецЦикла;
            ТелоЗапросаXML.ЗаписатьКонецЭлемента();

        КонецЕсли;
    ТелоЗапросаXML.ЗаписатьКонецЭлемента();

    ТелоЗапросаXML.Закрыть();

    Возврат ИмяФайлаЗапроса;

КонецФункции // СформироватьФайлДляPOSTЗапроса()

Функция ФорматироватьНомер(Номер)
    Результат = "";
    ДопустимыеСимволы = "+1234567890";
    Для Позиция = 1 По СтрДлина(Номер) Цикл
        Символ = Сред(Номер,Позиция,1);
        Если Найти(ДопустимыеСимволы, Символ) > 0 Тогда
            Результат = Результат + Символ;
        КонецЕсли;
    КонецЦикла;
    Возврат Результат;
КонецФункции // ФорматироватьНомер()

Функция РазмерФайла(ИмяФайла)
    Файл = Новый Файл(ИмяФайла);
    Возврат Файл.Размер();
КонецФункции // РазмерФайла()

После переопределения 2-х функций уже должна работать отправка sms. Чтобы выполнялась отправка sms конфигурацией, нужно настроить расписание предопределенного регламентного задания:

Настройка регламентного задания отправки SMS сообщений подсистемы БСПА вот и результат:

Результат отправки SMS сообщений регламентным заданием подсистемы БСП


Осталось переопределить последнюю процедуру СтатусДоставки, она нужна для обновления статуса sms-сообщения в базе. API провайдера:

  • тело POST запроса в кодировке «UTF-8»:
    XML-тело POST-запроса для обновления статуса SMS
  • примерный ответ сервиса в результате успеха:XML-тело ответа на POST-запрос обновления статуса SMS
// Запрашивает статус доставки SMS у поставщика услуг.
//
// Параметры:
//  ИдентификаторСообщения - Строка - идентификатор, присвоенный SMS при отправке;
//  Логин                  - Строка - логин для доступа к услуге отправки SMS.
//  Пароль                 - Строка - пароль для доступа к услуге отправки SMS.
//  Результат              - Строка - (возвращаемое значение) статус доставки,
//                                см. описание функции ОтправкаSMS.СтатусДоставки.
Процедура СтатусДоставки(ИдентификаторСообщения, Провайдер, Логин, Пароль, Результат) Экспорт

    Если Провайдер = Перечисления.ПровайдерыSMS.AlfaSMS Тогда

        // подготовка параметров запроса
        ПараметрыЗапроса = Новый Структура;
        ПараметрыЗапроса.Вставить("Логин", Логин);
        ПараметрыЗапроса.Вставить("Пароль", Пароль);
        ПараметрыЗапроса.Вставить("ИдентификаторСообщения", ИдентификаторСообщения);

        // отправка запроса
        ИмяФайлаОтвета = ВыполнитьЗапрос(ПараметрыЗапроса);
        Если ПустаяСтрока(ИмяФайлаОтвета) Тогда
            Результат = "Ошибка";
            Возврат;
        КонецЕсли;

        // обработка результата запроса
        SMSSTS_CODE = "";
        ТекущийSMS_ID = "";
        СтруктураОтвета = Новый ЧтениеXML;
        СтруктураОтвета.ОткрытьФайл(ИмяФайлаОтвета);
        Пока СтруктураОтвета.Прочитать() Цикл
            Если СтруктураОтвета.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
                Если СтруктураОтвета.Имя = "msg" Тогда
                    Пока СтруктураОтвета.ПрочитатьАтрибут() Цикл
                        Если СтруктураОтвета.Имя = "sms_id" Тогда
                            ТекущийSMS_ID = СтруктураОтвета.Значение;
                        КонецЕсли;
                    КонецЦикла;
                    СтруктураОтвета.Прочитать();
                    SMSSTS_CODE = СтруктураОтвета.Значение;
                КонецЕсли;
            КонецЕсли;
        КонецЦикла;
        СтруктураОтвета.Закрыть();
        УдалитьФайлы(ИмяФайлаОтвета);

        Результат = СтатусДоставкиSMS(SMSSTS_CODE);

    КонецЕсли;

КонецПроцедуры // СтатусДоставки()

Функция СтатусДоставкиSMS(СтатусСтрокой)

    СоответствиеСтатусов = Новый Соответствие;
    СоответствиеСтатусов.Вставить("", "НеОтправлялось");
    СоответствиеСтатусов.Вставить("100", "НеОтправлялось"); // SCHEDULED
    СоответствиеСтатусов.Вставить("101", "Отправляется");   // ENROUTE
    СоответствиеСтатусов.Вставить("102", "Доставлено");     // DELIVERED
    СоответствиеСтатусов.Вставить("103", "НеДоставлено");   // EXPIRED
    СоответствиеСтатусов.Вставить("104", "НеДоставлено");   // DELETED
    СоответствиеСтатусов.Вставить("105", "НеДоставлено");   // UNDELIVERABLE
    СоответствиеСтатусов.Вставить("106", "Отправлено");     // ACCEPTED
    СоответствиеСтатусов.Вставить("107", "НеОпознаноПровайдером"); // UNKNOWN
    СоответствиеСтатусов.Вставить("108", "НеОпознаноПровайдером"); // REJECTED
    СоответствиеСтатусов.Вставить("109", "НеОпознаноПровайдером"); // DISCARDED
    СоответствиеСтатусов.Вставить("110", "Отправляется");   // SENDING
    СоответствиеСтатусов.Вставить("111", "НеДоставлено");   // NOT_SUPPORTED
    СоответствиеСтатусов.Вставить("112", "НеДоставлено");   // WRONG_ALPHANAME
    СоответствиеСтатусов.Вставить("113", "НеДоставлено");   // WRONG_ALPHANAME_RETURNED

    Результат = СоответствиеСтатусов[НРег(СтатусСтрокой)];
    Возврат ?(Результат = Неопределено, "Ошибка", Результат);

КонецФункции // СтатусДоставкиSMS()

Для обновления статусов sms-сообщений, так же, нужно задать расписание предопределенного регламентного задания:

Настройка регламентного задания обновления статуса SMS сообщений подсистемы БСПА вот и результат:

Результат обновления статуса SMS сообщений регламентным заданием подсистемы БСП

От pbazeliuk

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *