XMPP(jabber) на чистом 1С

16.06.17

Интеграция - Мессенджеры и боты

На сайте infostart, есть несколько реализаций работы 1С с протоколом XMPP (jabber), но в основном они на использование сторонних библиотек (нативных), которые надо регистрировать в операционке (и только в винде), или на основе других систем - php, python и т.п. Предлагаю пример реализации отправки сообщения через этот протокол только средствами 1С.

Файлы

ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.

Наименование Скачано Купить файл
Пример реализации отправки сообщения
.epf 14,18Kb
23 1 850 руб. Купить

Подписка PRO — скачивайте любые файлы со скидкой до 85% из Базы знаний

Оформите подписку на компанию для решения рабочих задач

Оформить подписку и скачать решение со скидкой

Предварительный разбор по 1С

  • Поддержка XML у 1С реализована хорошо, а протокол XMPP - это чистый XML.
  • XMPP сервер работает с клиентами через сокеты/потоки, на 1С реализовать это уже сложнее, но работу с сервером XMPP можно расширить через модули для работы по HTTP (BOSH - http-bind).
  • Работа с Base64 - реализован в 1С через команды: Base64Значение и Base64Строка.
  • Расчет хэш-суммы по алгоритму MD5, реализован в 8.3 объектом ХешированиеДанных.

Разбор по XMPP

Простая сессия представляет из себя следующую последовательность операций:

  • Соединение с сервером
  • Создание потока
  • Аутентификация
  • Привязывание (bind) потока к ресурсу (имя@сервер/ресурс)
  • Создание сессии
  • Рассылка статуса "доступен"
  • Отправка/получение сообщений, статусы, ростер(список контактов), "визитные карточки", работа с сервисами и транспортами и т.п.
  • Рассылка статуса "отключен"
  • Закрытие потока
  • Отключение от сервера

В качестве примера (он будет достаточен), реализуем самый минимум и заморачиваться с ростером, закрытием сессий - не будем. Самое последнее действие, которое реализеум - это просто отправка сообщения.  Оговоримся сразу, в примере буду использовать сервер jabber.ru, а ники вымышленные.

1 - Приветствие, получение кода сессии SID:

<body 
	content='text/xml; charset=utf-8' 
	from='myNickXMPP@jabber.ru'
	secure='true'
	hold='1'
	rid='678901'
	to='jabber.ru'
	route='http://jabber.ru/http-bind' 
	ver='1.10' wait='300' 
	xml:lang='en' xmpp:version='1.0' 
	xmlns='http://jabber.org/protocol/httpbind' 
	xmlns:xmpp='urn:xmpp:xbosh'/>

2 - Отправка серверу команды на авторизацию методом DIGEST-MD5:

<body rid='678902' sid='1234567890' xmlns='http://jabber.org/protocol/httpbind' xmlns:xmpp='urn:xmpp:xbosh'>
	<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='DIGEST-MD5'/>
</body>

3 - Авторизация методом DIGEST-MD5:

<body rid='678903' sid='1234567890' xmlns='http://jabber.org/protocol/httpbind'>
	<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
		МАССИВ ДАННЫХ АВТОРИЗАЦИИ ЗАКОДИРОВАННЫХ BASE64
	</response>
</body>

4 - После успешной авторизации, отправляем встречный ответ подтверждение:

<body rid='678904' sid='1234567890' xmlns='http://jabber.org/protocol/httpbind'>
	<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>
</body>

5 - Повторно посылаем приветствие и команду "рестарта":

<body 
	rid='678905' 
	sid='1234567890' 
	to='jabber.ru'
	xml:lang='en' 
	xmpp:restart='true' 
	xmlns='http://jabber.org/protocol/httpbind' 
	xmlns:xmpp='urn:xmpp:xbosh'/>

6 - Устанавливаем имя ресурса (отправим пустой):

<body rid='678906' sid='1234567890' xmlns='http://jabber.org/protocol/httpbind'>
	<iq id='bind_1' type='set' xmlns='jabber:client'>
		<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/>
	</iq>
</body>

7 - Затем сервер требовал создать сессию... Это нужно для отсылки статусов, сообщений, да и вообще. Не будем отказывать:

<body rid='678907' sid='1234567890' xmlns='http://jabber.org/protocol/httpbind'>
	<iq id='bind_2' type='set' xmlns='jabber:client'>
		<session xmlns='urn:ietf:params:xml:ns:xmpp-session' />
	</iq>
</body>

8 - Ну и теперь выходим в онлайн и становимся видимыми для ваших контактов:

<body rid='678908' sid='1234567890' xmlns='http://jabber.org/protocol/httpbind'>
	<presence>
		<show/>
		<status>1c input</status>
		<priority>10</priority>
	</presence>
</body>

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

9 - Отправка сообщения другому пользователю:

<body rid='678909' sid='1234567890' xmlns='http://jabber.org/protocol/httpbind'>
	<message to='poluchatel@jabber.ru' from='myNickXMPP@jabber.ru' xmlns='jabber:client' type='chat'>
		<body>test message</body>
	</message>
</body>

Как видите ничего сложного - нет, рассматривать ответ от сервера мы тут не будем, этого в инете достаточно. Рабочий код(пример) выложен ниже.

Разбор полёта

Обработка соединяется с сервером и отсылает сообщение, но так как это всего-навсего пример и его цель только показать, что ничего невозможного сейчас на 1С - нету, то есть недоработки и корявости(сырости) в реализации.

Хотел бы обратить внимание (на двух) уже на одной проблеме, которой пока не нашел решение(не забываем, что реализация на чистом 1С, без COM). Без решения данной проблемы - пример всёравно работает.

  1. Как сказано выше, не удалось отправить сообщение и статус на кириллице, поэтому отсылаем только на латинице.
  2. Генератор случайных чисел - работает коряво и часто вылетает по ошибке, поэтому вставил уже сгенерированый и закодированный случайны код - oUIOt7lGFY0Q3Z+/1qo0j9lhpB1MscW9Fu4MJM/nNhc=.

Вся сложность взаимодействия с XMPP из 1С, это создания ключа авторизации по особому способу:

Функция строкаРеспонсе(структураДляОтвета)
	// функция создания поля response для challenge
	СтрокаВозвр="";
	
	authzid = Ложь;
	authzid_знач = "";
	Для  каждого првСтрк из структураДляОтвета Цикл
		Если првСтрк.Ключ = "authzid" Тогда
			authzid=Истина;
			authzid_знач = првСтрк.Значение;
		КонецЕсли;
	КонецЦикла;
	
	realm="";
	Если НЕ структураДляОтвета.realm="-" Тогда
		realm=структураДляОтвета.realm;
	КонецЕсли;
	
	раскНЕХ64 = мд5бз64(Объект.Пользователь+":"+realm+":"+Объект.Пароль);
	Сообщить(раскНЕХ64);
		
	а1 = ":"+структураДляОтвета.nonce+":"+структураДляОтвета.cnonce;
	Если authzid Тогда
		а1 = а1+":"+authzid_знач;
	КонецЕсли;
	а2="AUTHENTICATE:"+структураДляОтвета.digest_uri;
	
	общаяСтрока = ""+мд5(а1,раскНЕХ64)+
		":"+ структураДляОтвета.nonce +
		":"+ структураДляОтвета.nc +
		":"+ структураДляОтвета.cnonce +
		":"+ структураДляОтвета.qop +
		":"+ мд5(а2);
		
	Сообщить("rD="+общаяСтрока);
	СтрокаВозвр = мд5(общаяСтрока);
	
	Возврат СтрокаВозвр;
КонецФункции

Функция СлучайноеЧисло(Мин,Макс,флЦелое = 0)
	ГСЧ = Новый ГенераторСлучайныхЧисел();
	СлучайноеЧисло = ГСЧ.СлучайноеЧисло(1, 12000);
	//вместо Randomize
	Для н = 1 По СлучайноеЧисло Цикл
		Уник = Новый УникальныйИдентификатор;
	КонецЦикла;
	//генерируем GUID
	Уник = СокрЛП(Новый УникальныйИдентификатор);
	//оставляем только цифры
	Уник = СтрЗаменить(Уник,"-","");
	Уник = СтрЗаменить(Уник,"a","");
	Уник = СтрЗаменить(Уник,"b","");
	Уник = СтрЗаменить(Уник,"c","");
	Уник = СтрЗаменить(Уник,"d","");
	Уник = СтрЗаменить(Уник,"e","");
	Уник = СтрЗаменить(Уник,"f","");
	//знаменатель должен иметь такое же количество нулей + 1
	Знаменатель = 10;
	Для н = 2 По (СтрДлина(СтрЗаменить(Уник,Символы.НПП,""))) Цикл
		Знаменатель = Знаменатель * 10;
	КонецЦикла;
	Случ = (Число(Уник)) / Знаменатель; //здесь получается дробное случайное число от 0 до 1
	//преобразуем его в случайное число из заданного интервала, округляем до целого
	
	ЧислоИзИнтервала = Мин(Макс(Окр(Мин + (Макс-Мин)*Случ),Мин),Макс);
	
	Возврат ЧислоИзИнтервала; 
КонецФункции

Функция _2()
          //--//--//--
              Если узл.ИмяУзла = "challenge" Тогда
				неХЭШстрока = расшф64(узл.ТекстовоеСодержимое);
				струк = строк_струк(неХЭШстрока);
				Если струк.количество()>0 Тогда
					// нормально разобрали, теперь добавляем доп.параметры
					
					// 1-добавление к challenge digest-uri если он не пришел в ответе от сервера
					digest_uri = Ложь;
					Для  каждого првСтрк из струк Цикл
						Если првСтрк.Ключ = "digest-uri" Тогда
							digest_uri=Истина;
						КонецЕсли;
					КонецЦикла;
					Если НЕ digest_uri Тогда
						струк.Вставить("digest_uri", "xmpp/"+Объект.Домен);
					КонецЕсли;
					// 2-генерация cnonce - уникальный номер сессии
					гуид = Новый УникальныйИдентификатор();
					уникномерсесс = СтрЗаменить(гуид,"-","");
					струк.Вставить("cnonce", зашф64(уникномерсесс));
					струк.Вставить("nc", "00000001");
					// 3-проверка в challenge -> qop пришел в ответе от сервера и правильный ли он
					qop = Ложь;
					Для  каждого првСтрк из струк Цикл
						Если првСтрк.Ключ = "qop" Тогда
							qop=Истина;
						КонецЕсли;
					КонецЦикла;
					Если НЕ qop Тогда
						струк.Вставить("qop", "auth");
					Иначе
						Если НЕ струк.qop = "auth" Тогда
							струк.qop = "auth";
						КонецЕсли;
					КонецЕсли;
					// 3-добавление к challenge realm если он не пришел в ответе от сервера
					realm = Ложь;
					Для  каждого првСтрк из струк Цикл
						Если првСтрк.Ключ = "realm" Тогда
							realm=Истина;
						КонецЕсли;
					КонецЦикла;
					Если НЕ realm Тогда
						струк.Вставить("realm", "-"); // надо учитывать что
					КонецЕсли;
				КонецЕсли;
			
				Если струк.realm = "-" Тогда
					Знач_realm="";
				Иначе
					Знач_realm=струк.realm;
				КонецЕсли;
				
				// 4-создание кодированной строки response на основании некоторых данных из challenge и логина-пароля
				респонсеСтр=строкаРеспонсе(струк);
				
				// формируем строку для запроса №3
				строкаВозвратаДля3 = 
					"username="""+Объект.Пользователь+""","+
					"realm="""+Знач_realm+""","+
					"nonce="""+струк.nonce+""","+
					"cnonce="""+струк.cnonce+""","+
					"nc="+струк.nc+","+
					"qop="+струк.qop+","+
					"digest-uri="""+струк.digest_uri+""","+
					"response="+респонсеСтр+","+
					"charset=utf-8";
					
				Объект.challenge_actv=Истина;
			КонецЕсли;
          //--//--//--
КонецФункции

P.S. Есть пару идей использования протокола: можно организовать свой домашний сервер ботов на 1С, который может обрабатывать некую информацию и результат обработки отсылать пользователю в том-же xml или json. Например: по заказу сделали отчет или некую конфу, закодировали часть кода и ключ раскодирования отдавать пользователю по его запросу; можно также ограничить по количеству запусков, не более 10 раз и хватит с клиента. Причем, серверную часть своего бота можете ораганизовать на любом языке (не только 1С). Приложить свои усилия по доработке можно на github.

Вступайте в нашу телеграмм-группу Инфостарт

платформа xmpp jabber xml messaging сообщения обмен сообщениями

См. также

SALE! 50%

Мессенджеры и боты SMS рассылки Email рассылки Пользователь 1С v8.3 1C:Бухгалтерия 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 1С:Розница 3.0 Управленческий учет Платные (руб)

Расширение 1С с полным набором инструментов для качественных транзакционных, триггерных и маркетинговых рассылок Email, SMS, WhatsApp, Telegram. Даже простые уведомления об оплате счетов способны существенно упростить сбор дебиторской задолженности. Применение всех возможностей прямого маркетинга выводит коммуникацию с клиентами, уровень сервиса и лояльность на новый уровень.

6000 3000 руб.

07.04.2014    90995    70    200    

152

Мессенджеры и боты 1С v8.3 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 1С:Розница 3.0 Платные (руб)

Интеграция мессенджера WhatsApp и 1С: УНФ, УТ, КА, ERP - отправка и получение сообщений, картинок, файлов и видео прямо в 1С. Расширение работает с сервисом GreenApi.

18000 руб.

23.06.2023    15083    53    24    

58

Мессенджеры и боты Системный администратор Программист Бизнес-аналитик Пользователь Руководитель проекта 1С v8.3 Платные (руб)

Развитие популярного решения для интеграции мессенджера Telegram с нашей любимой 1С - конструктор чат-ботов в Телеграм.

15000 руб.

18.06.2021    77915    322    273    

398

Мессенджеры и боты Учет документов 1С v8.3 1С:Управление нашей фирмой 1.6 1С:Бухгалтерия государственного учреждения 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление холдингом 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 Платные (руб)

Расширение для согласования справочников и документов в основных типовых конфигурациях. Ролевая адресация, условная маршрутизация, чат-бот telegram, интеграция с n8n, последовательное и параллельное согласование, уведомление о новых задачах на почту, блокировка объектов в зависимости от статуса, запрет проведения в зависимости от статуса, автозапуск процессов согласования, отчеты по исполнительской дисциплине. Не требуется снятие конфигурации с поддержки. Настройка без программирования. Версия для 1cfresh.com. Сертификат 1С-Совместимо.

14900 руб.

15.11.2018    39280    43    55    

78

Мобильная разработка Мессенджеры и боты 1С v8.3 Платные (руб)

Теперь создать telegram-бота - элементарно. Достаточно просто нарисовать блок-схему телеграм-бота, и он сразу заработает. Это возможно при использовании Графического конструктора телеграм-ботов. Это единственный конструктор ботов для telegram, чье качество и функционал подтверждены фирмой 1С, есть сертификат 1С:Совместимо. Расширение в интерактивном режиме, с помощью блок-схем, позволяет с минимальными трудозатратами создать телеграм-ботов в любой конфигурации, работающей на платформе «1С:Предприятие 8.3».

13200 руб.

27.12.2021    47628    126    172    

223

Мессенджеры и боты Учет документов 1С v8.3 1С:Документооборот Россия Платные (руб)

Сделайте взаимодействие сотрудников компании быстрым и удобным. В Личном кабинете в Телеграм сотрудники могут получать и выполнять задачи используя популярный мессенджер

11520 руб.

29.12.2022    8985    7    13    

13
Вознаграждение за ответ
Показать полностью
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. dmpas 419 28.12.16 10:14 Сейчас в теме
За находчивость +, теперь о грустном:

	ТестЗапроса = ""<body rid='""+Формат(Объект.РИД,""ЧГ=1000000"")+""' sid='""+Формат(Объект.СИД,""ЧГ=1000000"")+""' xmlns='http://jabber.org/protocol/httpbind'>
	|<presence><show/><status>1c input</status><priority>10</priority></presence>
	//|<presence><show/><status>1С вход</status><priority>10</priority></presence>
	|</body>"";


И охота XML рисовать руками? ЗаписьXML или XDTO - это же так удобно.
ValentinGushchin; brr; +2 Ответить
2. kodnik 74 28.12.16 10:32 Сейчас в теме
(1) С вами согласен, а так как это пример и его цель - показать возможности 1С, то намеренно оставил XML запросы в текстовом виде для наглядности и простоты запросов XMPP.
8. nytlenc 19.09.18 05:24 Сейчас в теме
(1) Сериализация? Не.... Не слышал.
3. SerVer1C 992 28.12.16 13:17 Сейчас в теме
"...не получается нормально сгенерировать 32 символа с кодами от 0 до 255 и потом закодировать данную строку методом Base64, часто происходит вылет 1С по ошибке. Нужна реализация функции СлучайноеЧисло - по другому алгоритму."
А в чем сложность? Берешь 2 ГУИДа, склеиваешь, убираешь черточки - получаешь число из 64-х шестнадцатиричных знаков, каждая пара которых представляет собой одно число в диапазоне от 0 до 255.
4. kodnik 74 28.12.16 17:33 Сейчас в теме
(3) Точно!!! Но два ГУИДа - это много (64символа), хватит и одного 32 символа.
гуид = Новый УникальныйИдентификатор();
уникномерсесс = СтрЗаменить(гуид,"-","");
струк.Вставить("cnonce", зашф64(уникномерсесс));

5. skyadmin 66 25.05.18 11:58 Сейчас в теме
Не подскажете в чем может быть ошибка?
В процедуре 3 отправляется запрос
<body
	rid='27815'
	sid='6s0zusd3yz'
	xmlns='http://jabber.org/protocol/httpbind'>
<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>dXNlcm5hbWU9ItC60L7QutC60L7QvdC10L3QsNCydkB0cm1zcnYiLH­JlYWxtPSJ0
cm1zcnYiLG5vbmNlPSJyaFozVjJjOFNIQ0RwM0M4dHNsaURNdDVhRFNuQVhD­eTNY
cVRkc2VGIixjbm9uY2U9IlpqSmtPR05sWkRCa1pXSm1ORFV3Tm1JMk5EZzBZ­V0Zs
T1RObE1XVXlaVEk9IixuYz0wMDAwMDAwMSxxb3A9YXV0aCxkaWdlc3QtdXJp­PSJ4
bXBwLzE5Mi4xNjguMi4yIixyZXNwb25zZT1lYWJiMjk0ZDIyZWYzMTU1ZDY1­NTVi
Y2Y5MTRiOTI2MSxjaGFyc2V0PXV0Zi04</response>
</body>
Показать

в не зашифрованном виде строка выглядит так
username="кокконенавv@trmsrv",realm="trmsrv",nonce="rhZ3V2c8SHCDp3C8tsliDMt5aDSnAXCy3XqTdseF",cnonce="ZjJkOGNlZDBkZWJmNDUwNmI2NDg0YWFlOTNlMWUyZTI=",nc=00000001,qop=auth,digest-uri="xmpp/192.168.2.2",response=eabb294d22ef3155d6555bcf914b9261,charset=utf-8

ответ от сервера приходит такой
<body xmlns='http://jabber.org/protocol/httpbind' ack='27815'><failure xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><incorrect-encoding/></failure></body>
11. user828418 1 08.06.21 15:27 Сейчас в теме
(5)
Не подскажете в чем может быть ошибка?
В процедуре 3 отправляется запрос


Не помните, как решилась эта ошибка?
12. skyadmin 66 08.06.21 19:07 Сейчас в теме
(11) Не помню решилась ли вообще, но вижу что в (5) username (был скопирован) с буквой v, а в логине ее быть не должно.
14. user828418 1 10.06.21 11:50 Сейчас в теме
(12)
Ошибка "incorrect-encoding" решилась удалением разделителя строк в зашифрованной(base64) строке в <response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> </response>

Теперь другая ошибка not-authorized
13. user828418 1 10.06.21 11:49 Сейчас в теме
(5)
Ошибка "incorrect-encoding" решилась удалением разделителя строк зашифрованной(base64) строки в <response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> </response>
6. Zixxx 18.09.18 16:49 Сейчас в теме
А как входящие сообщения приходят?
7. skyadmin 66 18.09.18 20:28 Сейчас в теме
(6) Уже не помню, отпала необходимость, после появления в платформе 1С сервиса обсуждений)
9. rusanov_aa 31.10.19 12:02 Сейчас в теме
(7) так и не понял - он через глобальный сервак в интернете работает или локально можно развернуть?
10. skyadmin 66 31.10.19 15:15 Сейчас в теме
Сервер обсуждений можно развернуть локально :)
+ Можно читать переписки
- Ставиться куча служб, которые то и дело приходиться пинать..

Сервер Jabber у меня стоял локально OpenFire
В данной обработке есть один минус, если пользователь запустит более одного сеанса с jabber клиентом, оба зависнут намертво
Для отправки сообщения требуется регистрация/авторизация