При интеграции 1С с внешними API (например, сервисами «Честный ЗНАК» (поможет модуль автоматизации интеграции с системой Честный ЗНАК по API) и его разрешительным режимом, логистическими компаниями или маркетплейсами) разработчики часто сталкиваются с ошибками вида Invalid UTF-8 start byte или Invalid symbol '\r'. Эти ошибки возникают на стороне сервера из-за некорректного формирования тела HTTP-запроса. В данной статье мы подробно разберем, как правильно подготовить данные, избежать проблем с кодировкой и корректно упаковать вложенные структуры в формат Base64.
Проанализируем первую распространенную ошибку. Часто начинающие разработчики пытаются передать объект типа Структура напрямую в метод УстановитьТелоИзСтроки. Рассмотрим, почему так делать нельзя.
Метод УстановитьТелоИзСтроки объекта HTTPЗапрос ожидает в качестве первого параметра именно текстовую строку. Если вы передадите туда Структура, 1С не выполнит автоматическую конвертацию в JSON. Вместо этого сервер получит либо пустые данные, либо ошибку приведения типов еще на стороне клиента. Выясним, как выглядит правильный алгоритм:
ЗаписьJSON.Посмотрим на пример правильной подготовки тела запроса:
// 1. Формируем структуру
ДанныеЗапроса = Новый Структура;
ДанныеЗапроса.Вставить("documentBody", ЗашифрованныеДанные);
// 2. Сериализуем в JSON
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, ДанныеЗапроса);
СтрокаТела = ЗаписьJSON.Закрыть();
// 3. Устанавливаем тело запроса
HTTPЗапрос.УстановитьТелоИзСтроки(СтрокаТела, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
Одной из самых коварных проблем является ошибка Invalid symbol '\r' (или символ с кодом 15/13). Разберем причину ее появления. Стандартная функция 1С Base64Строка() работает по спецификации MIME, которая требует вставлять символы переноса строки (CRLF) через каждые 72 символа. Однако большинство современных веб-сервисов ожидают Base64 в виде одной непрерывной строки.
Если в вашем JSON-поле documentBody окажутся символы \r (возврат каретки) или \n (перенос строки), сервер вернет ошибку 400 (Bad Request), так как парсер JSON на стороне сервера споткнется о неэкранированные спецсимволы внутри строки. Проанализируем, как очистить строку перед отправкой:
// Получаем двоичные данные из строки вложенного документа
ДвоичныеДанныеВложения = ПолучитьДвоичныеДанныеИзСтроки(ВложенныйJSONСтрокой, КодировкаТекста.UTF8, Ложь);
// Кодируем в Base64
СтрокаBase64 = Base64Строка(ДвоичныеДанныеВложения);
// КРИТИЧЕСКИ ВАЖНО: Удаляем все символы переноса строк
СтрокаBase64 = СтрЗаменить(СтрокаBase64, Символы.ПС, "");
СтрокаBase64 = СтрЗаменить(СтрокаBase64, Символы.ВК, "");
Важный момент: использование метода СтрЗаменить гарантирует, что итоговый JSON будет валидным и принят сервером без ошибок парсинга.
Рассмотрим ситуацию с ошибкой Invalid UTF-8 start byte 0xa1. Эта ошибка сигнализирует о том, что сервер получил байты, которые не соответствуют стандарту UTF-8. В контексте 1С это чаще всего происходит по двум причинам:
ИспользованиеByteOrderMark.НеИспользовать.ЗаписьJSON.ОткрытьФайл(), а затем читаете его как ДвоичныеДанные, 1С может использовать кодировку Windows-1251 или добавить тот же BOM.Для решения этой проблемы, особенно если требуется надежная интеграция 1С с Google Таблицами через сервисный аккаунт, рекомендуется избегать промежуточной записи в файл и работать напрямую с памятью (строками или потоками). Посмотрим на реализацию надежного метода формирования вложенного зашифрованного документа:
НастройкиСериализации = Новый НастройкиСериализацииJSON;
НастройкиСериализации.ВариантЗаписиДаты = ВариантЗаписиДатыJSON.УниверсальнаяДата;
НастройкиСериализации.ФорматСериализацииДаты = ФорматДатыJSON.ISO;
ЗаписьJSON = Новый ЗаписьJSON;
// Записываем сразу в строку, чтобы избежать влияния файловой системы
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, ВнутренняяСтруктураДокумента, НастройкиСериализации);
ВнутреннийJSON = ЗаписьJSON.Закрыть();
// Преобразуем в Base64 без лишних промежуточных звеньев
ТелоBase64 = Base64Строка(ПолучитьДвоичныеДанныеИзСтроки(ВнутреннийJSON, КодировкаТекста.UTF8, Ложь));
ТелоBase64 = СтрЗаменить(СтрЗаменить(ТелоBase64, Символы.ПС, ""), Символы.ВК, "");
Теперь объединим все знания в единый блок кода, который обеспечит корректную отправку данных. Мы проанализируем настройку заголовков, создание защищенного соединения и безопасную передачу тела запроса.
// 1. Подготовка заголовков
Заголовки = Новый Соответствие;
Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
// Если API требует авторизации, например, как при получении токена RuStore с RSA-подписью
Заголовки.Вставить("Authorization", "Bearer " + ТокенДоступа);
// 2. Формирование финальной структуры JSON
ФинальнаяСтруктура = Новый Структура;
ФинальнаяСтруктура.Вставить("documentBody", ТелоBase64);
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, ФинальнаяСтруктура);
СтрокаЗапроса = ЗаписьJSON.Закрыть();
// 3. Отправка через HTTPСоединение
Попытка
SSL = Новый ЗащищенноеСоединениеOpenSSL();
Соединение = Новый HTTPСоединение(ХостСервиса, 443, , , , 30, SSL);
Запрос = Новый HTTPЗапрос(ПутьКМетодуAPI, Заголовки);
Запрос.УстановитьТелоИзСтроки(СтрокаЗапроса, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
Ответ = Соединение.ОтправитьДляОбработки(Запрос);
Если Ответ.КодСостояния = 200 Тогда
// Обработка успешного ответа
Сообщить("Данные успешно отправлены!");
Иначе
// Анализируем ошибку от сервера
Сообщить("Ошибка сервера: " + Ответ.КодСостояния);
Сообщить(Ответ.ПолучитьТелоКакСтроку());
КонецЕсли;
Исключение
Сообщить("Ошибка связи: " + ОписаниеОшибки());
КонецПопытки;
Рассмотрим еще несколько важных нюансов, которые помогут избежать ошибок при интеграции:
ЗаписатьJSON по умолчанию может экранировать прямой слеш (превращая / в \/). Если принимающая сторона (API) чувствительна к таким символам, это может привести к ошибке валидации подписи или Base64.Number в JSON, убедитесь, что в Структура передано именно число (Число(Значение)). Предварительно проверить структуру можно, используя обработку проверки обязательных полей в строке JSON.Соблюдение этих правил позволит вам создавать надежные интеграции, устойчивые к проблемам кодировок и специфике работы протокола HTTP в платформе 1С:Предприятие.