Разработка Telegram-ботов на платформе 1С становится всё более востребованной задачей для автоматизации бизнес-процессов: от подтверждения заявок до уведомления о критических событиях. В этой статье мы подробно разберем, как не только отправить пользователю сообщение с вариантами выбора, но и правильно обработать его ответ, особенно если речь идет об интерактивных кнопках.
Для начала рассмотрим ситуацию, когда нам необходимо отправить пользователю сообщение с кнопками "Разблокировать" и "Не разблокировать". В Telegram существует два основных типа клавиатур: ReplyKeyboardMarkup (обычные кнопки вместо текстовой клавиатуры) и InlineKeyboardMarkup (кнопки, привязанные непосредственно к сообщению). Для обработки конкретных действий программисты чаще всего выбирают именно Inline-кнопки.
Проанализируем пример кода на стороне 1С для формирования такой клавиатуры:
&НаСервере
Процедура ОтправитьСообщениеНаСервере()
мСтрок = Новый Массив;
мКнопок = Новый Массив;
// Формируем кнопки. В callback_data передаем идентификатор действия
мКнопок.Добавить(Новый Структура("text, callback_data", "Разблокировать", "1"));
мКнопок.Добавить(Новый Структура("text, callback_data", "Не разблокировать", "2"));
мСтрок.Добавить(мКнопок);
СтруктураОтвета = Новый Структура;
СтруктураОтвета.Вставить("inline_keyboard", мСтрок);
// Сериализуем структуру в JSON для передачи через API
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку(Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.Нет,,,ЭкранированиеСимволовJSON.СимволыВнеASCII));
ЗаписатьJSON(ЗаписьJSON, СтруктураОтвета);
Клавиатура = ЗаписьJSON.Закрыть();
// Формируем ресурс и отправляем запрос
Ресурс = "bot" + Объект.ТокенБота + "/sendMessage?chat_id=" + Формат(ChatID, "ЧГ=0") + "&text=" + ТекстСообщения
+ "&reply_markup=" + Клавиатура;
Соединение = Новый HTTPСоединение("api.telegram.org", 443,,,,, Новый ЗащищенноеСоединениеOpenSSL());
Запрос = Новый HTTPЗапрос(Ресурс);
Ответ = Соединение.Получить(Запрос);
КонецПроцедуры
В данном примере крайне важно поле callback_data. Именно это значение (в нашем случае "1" или "2") вернется в 1С, когда пользователь нажмет на кнопку. Текст кнопки при этом в обработку не попадает, что удобно для локализации или изменения визуальной части без правки логики.
Типичная проблема, с которой сталкиваются разработчики: при использовании метода getUpdates в поле message пусто, хотя пользователь нажал на кнопку. Выясним причину этого поведения.
Telegram разделяет типы входящих данных:
message.callback_query.Посмотрим на структуру входящего JSON при нажатии на кнопку:
{
"update_id": 123456789,
"callback_query": {
"id": "12345",
"from": { "id": 987654321, "first_name": "Иван" },
"message": { "message_id": 456, "text": "Вариант ответа?" },
"data": "1"
}
}
Как мы видим, текст нажатой кнопки или ответ пользователя нужно искать в callback_query.data. Если вы анализируете только message, то нажатие на кнопку будет проигнорировано.
Рассмотрим подробнее механизм получения ответов через периодический опрос серверов Telegram. Этот метод проще в настройке, так как не требует публикации базы 1С во внешнюю сеть.
Чтобы эффективно обрабатывать очередь сообщений и не получать одно и то же по кругу, используем параметр offset. Рассмотрим алгоритм:
Процедура ОбработатьОбновления()
// Последний обработанный UpdateID храним в константе или параметрах
ПоследнийID = Константы.ПоследнийUpdateID.Получить();
Ресурс = "bot" + Токен + "/getUpdates?offset=" + Формат(ПоследнийID + 1, "ЧГ=0");
// Отправляем запрос...
// После получения JSON, разбираем его:
Чтение = Новый ЧтениеJSON;
Чтение.УстановитьСтроку(СтрокаОтветаJSON);
Данные = ПрочитатьJSON(Чтение);
Для Каждого Обновление Из Данные.result Цикл
Если Обновление.Свойство("callback_query") Тогда
// Обрабатываем нажатие кнопки
КодДействия = Обновление.callback_query.data;
Если КодДействия = "1" Тогда
// Логика разблокировки
КонецЕсли;
// ОБЯЗАТЕЛЬНО: подтверждаем получение callback_query
ОтправитьПодтверждениеCallback(Обновление.callback_query.id);
ИначеЕсли Обновление.Свойство("message") Тогда
// Обрабатываем обычный текст
ТекстОтвета = Обновление.message.text;
КонецЕсли;
ПоследнийID = Обновление.update_id;
КонецЦикла;
Константы.ПоследнийUpdateID.Установить(ПоследнийID);
КонецПроцедуры
Важный нюанс: Метод answerCallbackQuery. Если не отправить этот запрос после обработки callback_query, у пользователя на кнопке будет продолжать крутиться индикатор ожидания (часики). Рассмотрим, как его вызвать:
Процедура ОтправитьПодтверждениеCallback(IDЗапроса)
Ресурс = "bot" + Токен + "/answerCallbackQuery?callback_query_id=" + IDЗапроса;
// Можно также добавить параметр text, чтобы показать всплывающее уведомление
Запрос = Новый HTTPЗапрос(Ресурс);
Соединение.Получить(Запрос);
КонецПроцедуры
Для более высоконагруженных или оперативных систем рекомендуется использовать Webhook. В этом случае Telegram сам будет присылать данные в вашу 1С в момент совершения действия пользователем. Разберем по шагам, как это реализовать.
1. Создание HTTP-сервиса в конфигурации:
Создадим новый объект HTTP-сервис (например, с именем TelegramWebhook). В нем определим шаблон URL и метод POST. В обработчике метода мы будем считывать тело запроса:
Функция ОбработатьВходящийЗапрос(Запрос)
ТелоJSON = Запрос.ПолучитьТелоКакСтроку();
// Далее логика разбора JSON, аналогичная getUpdates
// ...
Ответ = Новый HTTPСервисОтвет(200); // Обязательно возвращаем 200 OK
Возврат Ответ;
КонецФункции
2. Регистрация Webhook:
Чтобы Telegram узнал, куда слать данные, нужно один раз вызвать метод setWebhook. Проанализируем требования:
// Пример регистрации
Ресурс = "bot" + Токен + "/setWebhook?url=https://myserver.com/base/hs/TelegramWebhook/v1";
Запрос = Новый HTTPЗапрос(Ресурс);
Ответ = Соединение.Получить(Запрос);
3. Обеспечение безопасности:
Поскольку ваш HTTP-сервис теперь доступен из интернета, выясним, как защитить его от поддельных запросов. Рекомендуется включить в URL секретный токен, известный только вам и Telegram:
https://myserver.com/base/hs/Telegram/SECRET_GUID_HERE
В коде 1С проверяйте этот GUID в начале обработки запроса.
Проанализируем ситуацию: какой метод выбрать? getUpdates идеально подходит для внутренних нужд предприятия, когда 1С находится за NAT, и вы не хотите возиться с пробросом портов и SSL-сертификатами. Однако он создает лишнюю нагрузку на сервер из-за постоянных опросов.
Webhook работает быстрее, экономит ресурсы сервера и считается более профессиональным подходом, но требует публикации базы и настройки веб-сервера (Apache или IIS) с поддержкой защищенного соединения.
Независимо от выбранного способа, помните, что работа с Telegram — это всегда работа с объектами 1С ЧтениеJSON и ЗаписьJSON. Правильное обращение к свойствам структуры (Обновление.callback_query.data вместо Обновление.message.text) — ключ к успешной обработке действий пользователя.