При интеграции 1С с внешними API, такими как Telegram Bot API, разработчики часто сталкиваются с ситуацией, когда один и тот же код идеально работает на свежих релизах платформы (например, 8.3.20+), но выдает необъяснимые ошибки на более старых версиях, таких как 8.3.16. Одной из самых коварных проблем является ошибка Bad Request: message text is empty. На первый взгляд кажется, что текст сообщения просто не передается, однако при отладке мы видим заполненную структуру JSON. В этой статье мы подробно разберем, почему старая платформа "скрывает" текст от Telegram и как это исправить несколькими способами.
Проанализируем ситуацию. Когда мы используем метод HTTPЗапрос.УстановитьТелоИзСтроки(ТелоЗапроса) в старых версиях 1С, платформа при кодировании строки в UTF-8 может автоматически добавлять в начало строки специальный невидимый символ — BOM (Byte Order Mark). Этот символ сообщает обработчику порядок байтов, но для Telegram API он становится камнем преткновения. Парсер Telegram, встречая в начале JSON-пакета лишний байт, не может корректно распознать структуру и считает, что тело запроса пустое или поврежденное. Именно поэтому возникает ошибка об отсутствии текста сообщения.
Рассмотрим альтернативный вариант передачи данных. Если ваше сообщение не слишком длинное (ограничение 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-параметры.
Если нам всё же необходимо использовать POST (например, для длинных текстов или передачи файлов), нам нужно гарантировать, что 1С не добавит лишних символов в начало JSON. Для этого мы откажемся от метода УстановитьТелоИзСтроки и воспользуемся записью в поток. Разберем этот процесс по шагам:
ЗаписьJSON.ДвоичныеДанные, явно указав кодировку UTF-8 без BOM.Проанализируем пример реализации:
&НаСервере
Процедура ОтправитьЧерез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.
В некоторых случаях, особенно если в сообщении используются эмодзи или специфические символы кириллицы, платформа 1С может некорректно упаковать суррогатные пары в стандартный UTF-8. Существует мнение, что использование кодировки CESU-8 может помочь, однако Telegram официально ожидает UTF-8. Рассмотрим, как принудительно задать кодировку в заголовках, если стандартные средства не помогают:
HTTPЗапрос.УстановитьТелоИзСтроки(ТелоЗапроса, "UTF-8", ИспользованиеByteOrderMark.НеИспользовать);
Обратите внимание на параметр ИспользованиеByteOrderMark.НеИспользовать. Он появился в более поздних версиях платформы, но если ваша версия 8.3.16 его поддерживает (в зависимости от конкретного патча), обязательно используйте его.
Иногда проблема кроется не в коде, а в системных настройках. Если код корректен, но запросы всё равно обрываются или возвращают пустые ответы, проанализируем следующие моменты:
ЗащищенноеСоединениеOpenSSL обычно использует встроенные библиотеки, но иногда может опираться на системные настройки криптографии.Заголовки.Вставить("Content-Length", Строка(ТелоЗапроса.Размер()));.1cv8.exe не заблокирован брандмауэром.Подводя итог, можно сказать, что основной причиной ошибки message text is empty на 8.3.16 является некорректная передача JSON в теле POST-запроса. Используйте GET-запросы для простых задач или ДвоичныеДанные без BOM для сложных интеграций, и ваша связь с Telegram будет работать стабильно.