Как исправить проблему с отображением клавиатуры в Telegram при отправке из 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При интеграции 1С с Telegram многие разработчики сталкиваются с ситуацией, когда текстовое сообщение успешно доставляется пользователю, но прикрепленная к нему клавиатура (inline_keyboard) упорно не появляется. Проблема чаще всего кроется не в логике формирования кнопок, а в способе передачи данных через протокол HTTP. Давайте подробно разберем, почему клавиатура может "теряться", и как правильно настроить обмен данными с Telegram API.

Анализируем причину ошибки

Первоначальный подход, который часто выбирают новички, заключается в передаче параметров сообщения (таких как chat_id, text и parse_mode) прямо в строке URL. Это работает для простых текстовых сообщений, так как Telegram API принимает GET-параметры. Однако, когда мы пытаемся передать reply_markup (структуру клавиатуры), мы сталкиваемся с тем, что этот параметр представляет собой сложный вложенный JSON-объект. Попытка "запихнуть" такой объект в URL-строку часто приводит к ошибкам парсинга на стороне сервера Telegram, либо к обрезанию строки из-за ограничений по длине.

Основная причина проблемы: Передача сложных структур данных через параметры URL вместо использования тела POST-запроса в формате JSON.

Шаг 1. Формирование структуры клавиатуры

Для начала проанализируем, как должна выглядеть структура кнопок в 1С. Telegram ожидает "массив массивов" для inline_keyboard. Каждый вложенный массив — это отдельный ряд кнопок в интерфейсе мессенджера.


МассивСтрок = Новый Массив; // Основной контейнер клавиатуры

Пока Выборка.Следующий() Цикл
    // Создаем массив для одного ряда (одна кнопка на ряд)
    МассивКнопокРяда = Новый Массив;
    
    // Формируем структуру самой кнопки
    Кнопка = Новый Структура;
    Кнопка.Вставить("text", Лев(Выборка.НазваниеЗадания, 80));
    Кнопка.Вставить("callback_data", "/Gettask" + Выборка.ID);
    
    // Добавляем кнопку в ряд, а ряд — в основной массив клавиатуры
    МассивКнопокРяда.Добавить(Кнопка);
    МассивСтрок.Добавить(МассивКнопокРяда);
КонецЦикла;

Клавиатура = Новый Структура;
Клавиатура.Вставить("inline_keyboard", МассивСтрок);

Обратите внимание: если вы добавите все кнопки в один МассивКнопокРяда, они выстроятся в одну горизонтальную линию, что может быть неудобно на экране телефона. Используя добавление ряда в цикле, мы располагаем кнопки вертикально друг под другом.

Шаг 2. Сериализация данных в JSON

Чтобы Telegram "понял" нашу структуру, ее нужно превратить в строку формата JSON. В 1С для этого используются объекты ЗаписьJSON и ПараметрыЗаписиJSON. Рассмотрим, как правильно подготовить текстовый пакет данных.


// Формируем общую структуру запроса
ПараметрыЗапроса = Новый Структура;
ПараметрыЗапроса.Вставить("chat_id", ЧатID);
ПараметрыЗапроса.Вставить("text", ТекстСообщения);
ПараметрыЗапроса.Вставить("parse_mode", "HTML");
ПараметрыЗапроса.Вставить("reply_markup", Клавиатура);

// Превращаем структуру в JSON-строку
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, ПараметрыЗапроса);
ТекстЗапросаJSON = ЗаписьJSON.Закрыть();

Важно помнить, что ЗаписатьJSON корректно обработает вложенные массивы и структуры, превратив их в валидный объект, который ожидает сервер Telegram.

Шаг 3. Настройка HTTP-запроса (POST)

Теперь перейдем к самой критичной части — отправке сообщения. Мы должны использовать метод POST и обязательно указать заголовок Content-Type: application/json. В 1С метод ОтправитьДляОбработки объекта HTTPСоединение по умолчанию выполняет POST-запрос.

Разберем обновленную функцию отправки:


Функция ОтправитьСообщениеВTelegram(ТекстСообщения, Клавиатура = Неопределено) Экспорт
    МойToken = "ВашТокен";
    АдресTelegramAPI = "api.telegram.org";
    ЧатID = "ВашID";

    СоединениеHTTP = Новый HTTPСоединение(АдресTelegramAPI, 443,,,,, Новый ЗащищенноеСоединениеOpenSSL);
    
    // Адрес теперь НЕ содержит параметров после знака вопроса
    АдресМетода = "bot" + МойToken + "/sendMessage";
    
    // Готовим JSON (аналогично Шагу 2)
    ПараметрыЗапроса = Новый Структура;
    ПараметрыЗапроса.Вставить("chat_id", ЧатID);
    ПараметрыЗапроса.Вставить("text", ТекстСообщения);
    Если Клавиатура <> Неопределено Тогда
        ПараметрыЗапроса.Вставить("reply_markup", Клавиатура);
    КонецЕсли;

    ЗаписьJSON = Новый ЗаписьJSON;
    ЗаписьJSON.УстановитьСтроку();
    ЗаписатьJSON(ЗаписьJSON, ПараметрыЗапроса);
    ТекстЗапросаJSON = ЗаписьJSON.Закрыть();

    // Создаем запрос и устанавливаем тело
    ЗапросHTTP = Новый HTTPЗапрос(АдресМетода);
    ЗапросHTTP.Заголовки.Вставить("Content-Type", "application/json");
    ЗапросHTTP.УстановитьТелоИзСтроки(ТекстЗапросаJSON, КодировкаТекста.UTF8);

    Попытка
        ОтветHTTP = СоединениеHTTP.ОтправитьДляОбработки(ЗапросHTTP);
        Если ОтветHTTP.КодСостояния = 200 Тогда
            Возврат Истина;
        Иначе
            // Полезно прочитать ошибку, если статус не 200
            ТекстОшибки = ОтветHTTP.ПолучитьТелоКакСтроку();
            ЗаписьЖурналаРегистрации("TelegramAPI", УровеньЖурналаРегистрации.Ошибка,,, ТекстОшибки);
            Возврат Ложь;
        КонецЕсли;
    Исключение
        Возврат Ложь;
    КонецПопытки;
КонецФункции

Важные нюансы и подводные камни

Проанализируем дополнительные моменты, которые могут помешать корректной работе клавиатуры даже при правильном методе отправки:

  1. Лимит callback_data: Поле callback_data в каждой кнопке имеет жесткое ограничение — не более 64 байт. Если вы пытаетесь передать туда длинную ссылку или GUID документа целиком, Telegram просто отклонит весь пакет reply_markup. В этом случае сообщение придет без кнопок. Рекомендуется использовать короткие идентификаторы.
  2. Обязательные поля: В каждой кнопке обязательно должно быть поле text. Если оно окажется пустым (например, из-за пустой строки в базе 1С), клавиатура не отобразится.
  3. Кодировка: Всегда используйте КодировкаТекста.UTF8 при вызове УстановитьТелоИзСтроки. Telegram API работает только с этой кодировкой.
  4. Типизация JSON: Убедитесь, что chat_id передается корректно. Хотя Telegram понимает и строки, и числа, в некоторых случаях (особенно с супергруппами) это может иметь значение.

Выясним причину, если клавиатура все равно не видна. Для этого всегда анализируйте тело ответа сервера при коде состояния, отличном от 200. Используйте метод ОтветHTTP.ПолучитьТелоКакСтроку(). Там часто содержится подробное описание ошибки, например: "Bad Request: can't parse reply_markup JSON object". Это явно укажет на ошибку в структуре вашего массива кнопок.

Таким образом, перейдя от формирования URL-запроса к полноценному JSON-телу в POST-запросе, мы обеспечиваем надежную передачу клавиатуры и любых других сложных структур данных в Telegram.

← На главную