0 800 219 777

Отправка смс из 1C по протоколу SMPP v3.4

Отправка смс из 1C по протоколу SMPP v3.4

В жизни всякое бывает и, возможно, кому понадобится отправлять много СМС из 1C.

Главное, не забывать, что работа SMPP протокола подразумевает под собой поддержание постоянного подключения к поставщику.

В описании пойдет речь о подключении программы семейства «1C: Предприятие 8x».

Для реализации проекта, нам понадобится сторонний компонент – ActiveX: Winsock.

Для установки данного компонента достаточно просто скачать и установить его с официального сайта — http://www.microsoft.com/ru-ru/softmicrosoft/VisualStudioExpress.aspx

После установки – размещаем на форме компонент Winsock.

Отправка смс из 1C по протоколу SMPP v3.4

Добавление компонента

 

После установки – проверяем и настраиваем (при необходимости методы).

Отправка смс из 1C по протоколу SMPP v3.4

Методы Winsock

 

Если описать вкратце метод поднятия SMPP сессии, то этот процесс делится на два этапа: поднятие TCP подключения и поднятие SMPP подключения.

Сперва необходимо подключить по TCP протоколу (т. е. поднять / создать сокет соединение).

Процедура Иницилизация() ЭкспортмWinSocketActiveX = ПолучитьФорму(«Форма»).ЭлементыФормы.WinSocket;//иницилизация настроек для подключениямWinSocketActiveX.RemotePort = 2775;мWinSocketActiveX.RemoteHost = «smsc.smppc.com.ua»;ВыполнитьПодключение();КонецПроцедуры // Иницилизация()Процедура ВыполнитьПодключение()Если  мWinSocketActiveX.State = 0 ТогдамWinSocketActiveX.Connect();КонецЕсли;КонецПроцедуры

 

После успешного соединение с сервером, необходимо отправить команду BIND_TRANSMITTER или BIND_TRANSCEIVER (в зависимости от выбранного метода подключения). Если не отправить команду – то соединение оборвется.

Поэтому после проверки отправляем PDU пакет — (Protocol Data Units (Bind_Transceiver).

Процедура ОпроситьСоединение() Экспорт
    Если мWinSocketActiveX.State = 7 Тогда
        PDU = СобратьПакет_BIND_Transceiver();
        мWinSocketActiveX.SendData(PDU);
    Иначе //обработать другие состояния!!!
    КонецЕсли;
КонецПроцедуры // УстановитьСоединение()

 

Для обработки ответа (ответного PDU пакета) необходимо использовать многомерный массив 1C COMSafeArray.

Функция СобратьПакет_BIND_Transceiver()
    Матрица = Новый COMSafeArray("VT_UI1",37);
    Матрица.SetValue(0,0);
    Матрица.SetValue(1,0);
    Матрица.SetValue(2,0);
    Матрица.SetValue(3,37);
    //код сокращен для этой статьи***
    //***
    Матрица.SetValue(32,0);
    Матрица.SetValue(33,52);
    Матрица.SetValue(34,1);
    Матрица.SetValue(35,1);
    Матрица.SetValue(36,0);
    Возврат Матрица;
КонецФункции // СобратьПакет_BIND_Transceiver()

 

Клиент обязан отвечать на все пакеты, отправляемые сервером, в течение 10 – 60 секунд (в зависимости от требований поставщика) – resp пакетами. Если игнорировать запросы и не отвечать – соединение будет разорвано.

Отдельно нужно ответить команде ENQUIRE_LINK, которая используется для проверки работоспособности соединения. Отвечать на нее обязательно, если нужно чтобы СМС продолжали ходить.

Методом DataArrival() принимаем и обрабатываем входящие пакеты:

Процедура WinSocketDataArrival(Элемент, bytesTotal)
    ВходящийПакет = Неопределено;
    мWinSocketActiveX.GetData(ВходящийПакет);

 

    Если ТипЗнч(ВходящийПакет) = Тип("COMSafeArray") Тогда
        ОбработатьВходящийПакет(ВходящийПакет);
    КонецЕсли;
КонецПроцедуры
Процедура ОбработатьВходящийПакет(Пакет)  Экспорт
    //пришел пакет ENQUIRE_LINK
    Если Пакет.GetValue(4) = 0 И Пакет.GetValue(7) = 21 Тогда
        PDU = Фабрика_PDU_ENQUIRE_LINK_RESP(Пакет);
        ОтправитьПакет(PDU);
        Если мФлагОтправитьСМС Тогда
            СобратьИОтправитьПакет_CMC();//отсюда отправялем смс-сообщение
            мФлагОтправитьСМС = Ложь;
        КонецЕсли;
    КонецЕсли;
    //пришел пакет bind_transceiver_resp
    Если   Пакет.GetValue(4) = 128 И Пакет.GetValue(7) = 9 Тогда
        ОбработатьПакет_bind_transceiver_resp(Пакет);
    КонецЕсли;
    //пришел пакет submit_sm_resp
    Если   Пакет.GetValue(4) = 128 И Пакет.GetValue(7) = 4 Тогда
        ОбработатьПакет_submit_sm_resp(Пакет);
    КонецЕсли;
    //пришел пакет Query_sm_resp
    Если   Пакет.GetValue(4) = 128 И Пакет.GetValue(7) = 3 Тогда
        ОбработатьПакет_Query_sm_resp(Пакет);
    КонецЕсли;
    //пришел пакет UNBIND_resp
    Если   Пакет.GetValue(4) = 128 И Пакет.GetValue(7) = 6 Тогда
        мWinSocketActiveX = Неопределено;
    КонецЕсли;

 

КонецПроцедуры // ОбработатьВходящийПакет()

 

После того как клиент и сервер успешно обменялись пакетами ENQUIRE_LINK, можно отправить текст смс-сообщения.

Процедура СобратьИОтправитьПакет_CMC()
    Перем PDU;

 

    Если ЗаполнитьТаблицуЗначенийСМС() Тогда
        НомерТел             = мТабЗнДиспетчерСМС[0].НомерТелефона;
        НомерДок             = мТабЗнДиспетчерСМС[0].НомерДокумента;
        ДатаДок              = мТабЗнДиспетчерСМС[0].ДатаДокумента;
        СтатусСМС             = мТабЗнДиспетчерСМС[0].СтатусСМС;
        ИдентификаторСМС    = мТабЗнДиспетчерСМС[0].ИдентификаторСМС;
        ТипДокумента        = мТабЗнДиспетчерСМС[0].ЗаказПокупателя;
        Если СтатусСМС = 0 Тогда
            PDU = СобратьПакет_Submit_SM(НомерТел,НомерДок,ДатаДок,ТипДокумента);
            СтрокаСообщения = Формат(ТекущаяДата(),"ДЛФ=DT")+" <= Отправляю СМС
 на номер: " +НомерТел+". Inf...";
            Лог.ДобавитьСтроку(СтрокаСообщения);
        ИначеЕсли СтатусСМС = 10 Тогда
            PDU = СобратьПакет_Query_SM(ИдентификаторСМС);
            СтрокаСообщения = Формат(ТекущаяДата(),"ДЛФ=DT")+" <= Запрашиваю статус
 СМС для номера: "+НомерТел + " . Inf...";
            Лог.ДобавитьСтроку(СтрокаСообщения);
        КонецЕсли;
    Иначе
        СтрокаСообщения = Формат(ТекущаяДата(),"ДЛФ=DT")+" <= Нет данных для
 отправки смс. Закрываю канал связи. Inf...";
        Лог.ДобавитьСтроку(СтрокаСообщения);
        PDU = СобратьПакет_UNBIND(); // отправлять больше нечего. Закрываем
 соединение;
    КонецЕсли;
    ОтправитьПакет(PDU);
КонецПроцедуры // СобратьИОтправитьПакет_CMC()
// <Описание функции>
//
// Параметры
//  <Параметр1>  - <Тип.Вид> - <описание параметра>
//                 <продолжение описания параметра>
//  <Параметр2>  - <Тип.Вид> - <описание параметра>
//                 <продолжение описания параметра>
//
// Возвращаемое значение:
//   <Тип.Вид>   - <описание возвращаемого значения>
//
Функция СобратьПакет_Submit_SM(НомерТелефона,НомерДокумента,ДатаДокумента,Объект)
    Перем ИспользоватьРусский;
    ИспользоватьРусский = Истина; //настройка
    Если ТипЗнч(Объект) = Тип("ДокументСсылка.ЗаказПокупателя") Тогда
        СообщениеТекстЛатиница = "Vash tovar po zakazu N "+НомерДокумента+" ot " +
 Формат(ДатаДокумента,"ДФ=dd.MM.yyyy")+" dostavlen";
        СообщениеТекстРусский  = "Ваш товар по заказу № "+НомерДокумента+" от " +
 Формат(ДатаДокумента,"ДФ=dd.MM.yyyy")+" доставлен";
    ИначеЕсли ТипЗнч(Объект) = Тип("ДокументСсылка.АктПретензий") Тогда
        СообщениеТекстЛатиница = "Vash tovar gotov k vydachi. Akt pretenzii N "+
 НомерДокумента+" ot " + Формат(ДатаДокумента,"ДФ=dd.MM.yyyy");
        СообщениеТекстРусский  = "Ваш товар готов к выдаче. Акт претензии № "+
 НомерДокумента+" от " + Формат(ДатаДокумента,"ДФ=dd.MM.yyyy");
    КонецЕсли;
    Если ИспользоватьРусский Тогда
        СообщениеТекст           = СообщениеТекстРусский;
        МассивКодовРусскихБукв   = ЗакодироватьРусскийТекст(СообщениеТекстРусский);
        ДлинаСообщения           = СтрДлина(СообщениеТекст)*2;
        DataCod = 8;
    Иначе
        СообщениеТекст = СообщениеТекстЛатиница;
        ДлинаСообщения            = СтрДлина(СообщениеТекст);
        DataCod = 0;
    КонецЕсли;
    ДлинаНомераТелефона         = СтрДлина(НомерТелефона);
    ДлинаПакета = 32+ДлинаНомераТелефона+11+ДлинаСообщения;
    МатрицаДанных = Новый COMSafeArray("VT_UI1",ДлинаПакета-1);
    //Заголовок
    МатрицаДанных.SetValue(0,    0);
    МатрицаДанных.SetValue(1,    0);
    МатрицаДанных.SetValue(2,    0);
    МатрицаДанных.SetValue(3,    ДлинаПакета-1);
    МатрицаДанных.SetValue(4,    0);
    МатрицаДанных.SetValue(5,    0);
    МатрицаДанных.SetValue(6,    0);
    МатрицаДанных.SetValue(7,    4);
    МатрицаДанных.SetValue(8,    0);
    МатрицаДанных.SetValue(9,    0);
    МатрицаДанных.SetValue(10,    0);
    МатрицаДанных.SetValue(11,    0);
    МатрицаДанных.SetValue(12,    0);
    МатрицаДанных.SetValue(13,    0);
    МатрицаДанных.SetValue(14,    0);
    МатрицаДанных.SetValue(15,    2); //номер пакета
    //тело
    МатрицаДанных.SetValue(16,    0);
    МатрицаДанных.SetValue(17,    5);
    МатрицаДанных.SetValue(18,    1);
    МатрицаДанных.SetValue(19,    КодСимвола("S"));
    МатрицаДанных.SetValue(20,    КодСимвола("e"));
    МатрицаДанных.SetValue(21,    КодСимвола("n")); //
    МатрицаДанных.SetValue(22,    КодСимвола("d")); //
    МатрицаДанных.SetValue(23,    КодСимвола("e")); //
    МатрицаДанных.SetValue(24,    КодСимвола("r"));//
    МатрицаДанных.SetValue(25,    КодСимвола("s"));
    МатрицаДанных.SetValue(26,    КодСимвола("m"));
    МатрицаДанных.SetValue(27,    КодСимвола("s")); //
    МатрицаДанных.SetValue(28,    0);
    МатрицаДанных.SetValue(29,    1);
    МатрицаДанных.SetValue(30,    1);
    Индекс = 31;
    Для  НомерСтроки = 1 По ДлинаНомераТелефона Цикл
        МатрицаДанных.SetValue(Индекс,КодСимвола(НомерТелефона,НомерСтроки));
        Индекс = Индекс+1;
    КонецЦикла;
    МатрицаДанных.SetValue(42,    0);
    МатрицаДанных.SetValue(43,    0);
    МатрицаДанных.SetValue(44,    0);
    МатрицаДанных.SetValue(45,    0);
    МатрицаДанных.SetValue(46,    0);
    МатрицаДанных.SetValue(47,    0);
    МатрицаДанных.SetValue(48,    1);
    МатрицаДанных.SetValue(49,    1);
    МатрицаДанных.SetValue(50,    DataCod);//data coding
    МатрицаДанных.SetValue(51,    1);
    МатрицаДанных.SetValue(52,    ДлинаСообщения);
    Индекс = 53;
    Если ИспользоватьРусский Тогда
        Для  НомерСтроки1 = 0 По ДлинаСообщения-1 Цикл
            СимВ = МассивКодовРусскихБукв[НомерСтроки1];
            МатрицаДанных.SetValue(Индекс,СимВ);
            Индекс = Индекс+1;
        КонецЦикла;
    Иначе
        Для  НомерСтроки2 = 1 По ДлинаСообщения Цикл
            ЗначениеСимвола = КодСимвола(СообщениеТекст,НомерСтроки2);
            МатрицаДанных.SetValue(Индекс,ЗначениеСимвола);
            Индекс = Индекс+1;
        КонецЦикла;
    КонецЕсли;
    Возврат МатрицаДанных;
КонецФункции // СобратьПакет_Submit_SM()
Процедура ОтправитьПакет(PDU)
    Если мWinSocketActiveX.State = 7 Тогда
        мWinSocketActiveX.SendData(PDU);
    КонецЕсли;
КонецПроцедуры // ОтправитьПакет()

 

Несмотря на то, что SMPP подключение подразумевает под собой постоянное соединение, можно, конечно, и разрывать соединение (правильно это делать через команду UNBIND), но только, если в течение нескольких часов у Вас не предвидится отправка СМС. Иначе лучше оставлять соединение рабочим.

 

Источник – www.1c83.ru

5/5 - (1 vote)
Добавить комментарий