Как исправить ошибку "Bad Request: message text is empty" при отправке сообщений в Telegram из 1С 8.3.16?

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

При интеграции 1С с внешними API, такими как Telegram Bot API, разработчики часто сталкиваются с ситуацией, когда один и тот же код идеально работает на свежих релизах платформы (например, 8.3.20+), но выдает необъяснимые ошибки на более старых версиях, таких как 8.3.16. Одной из самых коварных проблем является ошибка Bad Request: message text is empty. На первый взгляд кажется, что текст сообщения просто не передается, однако при отладке мы видим заполненную структуру JSON. В этой статье мы подробно разберем, почему старая платформа "скрывает" текст от Telegram и как это исправить несколькими способами.

Выясним причину проблемы: почему Telegram не видит текст?

Проанализируем ситуацию. Когда мы используем метод HTTPЗапрос.УстановитьТелоИзСтроки(ТелоЗапроса) в старых версиях 1С, платформа при кодировании строки в UTF-8 может автоматически добавлять в начало строки специальный невидимый символ — BOM (Byte Order Mark). Этот символ сообщает обработчику порядок байтов, но для Telegram API он становится камнем преткновения. Парсер Telegram, встречая в начале JSON-пакета лишний байт, не может корректно распознать структуру и считает, что тело запроса пустое или поврежденное. Именно поэтому возникает ошибка об отсутствии текста сообщения.

Решение №1: Переход на GET-запрос (самый простой способ)

Рассмотрим альтернативный вариант передачи данных. Если ваше сообщение не слишком длинное (ограничение URL обычно составляет около 2000 символов), проще всего отказаться от передачи JSON в теле запроса и передать все параметры напрямую в строке ресурса. Посмотрим на пример кода, который стабильно работает на обычных формах 8.3.13 и выше:


&НаСервере
Процедура ОтправитьЧерезGET()
    КлючБота = "ВАШ_ТОКЕН";
    IDЧата = "ID_ЧАТА";
    ТекстСообщения = "Привет, это тестовое сообщение!";
    
    // Формируем ресурс с параметрами прямо в строке
    Ресурс = СтрШаблон("bot%1/sendMessage?chat_id=%2&text=%3", КлючБота, IDЧата, ТекстСообщения);
    
    ЗащищенноеСоединение = Новый ЗащищенноеСоединениеOpenSSL;
    Соединение = Новый HTTPСоединение("api.telegram.org", 443, , , , , ЗащищенноеСоединение);
    
    Запрос = Новый HTTPЗапрос(Ресурс);
    Попытка
        Ответ = Соединение.Получить(Запрос);
        Если Ответ.КодСостояния = 200 Тогда
            Сообщить("Сообщение успешно отправлено!");
        Иначе
            Сообщить("Ошибка: " + Ответ.ПолучитьТелоКакСтроку());
        КонецЕсли;
    Исключение
        Сообщить("Ошибка связи: " + ОписаниеОшибки());
    КонецПопытки;
КонецПроцедуры

Этот метод хорош тем, что он исключает любые проблемы с телом POST-запроса и кодировкой application/json, так как данные передаются как стандартные URL-параметры.

Решение №2: Использование бинарных данных для POST-запроса (убираем BOM)

Если нам всё же необходимо использовать POST (например, для длинных текстов или передачи файлов), нам нужно гарантировать, что 1С не добавит лишних символов в начало JSON. Для этого мы откажемся от метода УстановитьТелоИзСтроки и воспользуемся записью в поток. Разберем этот процесс по шагам:

  1. Сформируем структуру сообщения.
  2. Запишем её в ЗаписьJSON.
  3. Преобразуем полученную строку в ДвоичныеДанные, явно указав кодировку UTF-8 без BOM.
  4. Установим тело запроса из двоичных данных.

Проанализируем пример реализации:


&НаСервере
Процедура ОтправитьЧерезPOST_Правильно()
    Сообщение = Новый Структура;
    Сообщение.Вставить("chat_id", "123456789");
    Сообщение.Вставить("text", "Тестовое сообщение через POST без BOM");
    
    ЗаписьJSON = Новый ЗаписьJSON;
    ЗаписьJSON.УстановитьСтроку();
    ЗаписатьJSON(ЗаписьJSON, Сообщение);
    СтрокаJSON = ЗаписьJSON.Закрыть();
    
    // Важный момент: преобразуем в двоичные данные БЕЗ использования BOM
    // В 1С 8.3.16 это делается через поток или временный файл
    ТелоЗапроса = ДвоичныеДанныеИзСтроки(СтрокаJSON, КодировкаТекста.UTF8, Ложь); 
    
    КлючБота = "ВАШ_ТОКЕН";
    Соединение = Новый HTTPСоединение("api.telegram.org", , , , , 15, Новый ЗащищенноеСоединениеOpenSSL);
    
    Заголовки = Новый Соответствие;
    Заголовки.Вставить("Content-Type", "application/json");
    
    HTTPЗапрос = Новый HTTPЗапрос("/bot" + КлючБота + "/sendMessage", Заголовки);
    HTTPЗапрос.УстановитьТелоИзДвоичныхДанных(ТелоЗапроса);
    
    Ответ = Соединение.ОтправитьДляОбработки(HTTPЗапрос);
    // Проверка ответа...
КонецПроцедуры

Использование метода УстановитьТелоИзДвоичныхДанных вместо УстановитьТелоИзСтроки — это наиболее профессиональный подход, который снимает большинство проблем взаимодействия 1С с современными веб-сервисами на платформе 8.3.16.

Решение №3: Проблема кодировки CESU-8

В некоторых случаях, особенно если в сообщении используются эмодзи или специфические символы кириллицы, платформа 1С может некорректно упаковать суррогатные пары в стандартный UTF-8. Существует мнение, что использование кодировки CESU-8 может помочь, однако Telegram официально ожидает UTF-8. Рассмотрим, как принудительно задать кодировку в заголовках, если стандартные средства не помогают:


HTTPЗапрос.УстановитьТелоИзСтроки(ТелоЗапроса, "UTF-8", ИспользованиеByteOrderMark.НеИспользовать);

Обратите внимание на параметр ИспользованиеByteOrderMark.НеИспользовать. Он появился в более поздних версиях платформы, но если ваша версия 8.3.16 его поддерживает (в зависимости от конкретного патча), обязательно используйте его.

Дополнительные рекомендации по настройке окружения

Иногда проблема кроется не в коде, а в системных настройках. Если код корректен, но запросы всё равно обрываются или возвращают пустые ответы, проанализируем следующие моменты:

  1. Версия TLS: Telegram требует протокол TLS 1.2 или выше. Если ваша 1С запущена на старой ОС (например, Windows Server 2008/2012 без обновлений), убедитесь, что в системе разрешено использование TLS 1.2. Платформа 8.3.16 при использовании ЗащищенноеСоединениеOpenSSL обычно использует встроенные библиотеки, но иногда может опираться на системные настройки криптографии.
  2. Заголовок Content-Length: Некоторые прокси-серверы или само API могут требовать явного указания длины контента. Попробуйте вычислить длину двоичных данных тела и добавить заголовок: Заголовки.Вставить("Content-Length", Строка(ТелоЗапроса.Размер()));.
  3. Firewall и антивирусы: На одном и том же компьютере разные версии платформы могут иметь разные права доступа к сети. Убедитесь, что исполняемый файл конкретной версии 1cv8.exe не заблокирован брандмауэром.

Подводя итог, можно сказать, что основной причиной ошибки message text is empty на 8.3.16 является некорректная передача JSON в теле POST-запроса. Используйте GET-запросы для простых задач или ДвоичныеДанные без BOM для сложных интеграций, и ваша связь с Telegram будет работать стабильно.

← На главную