Как успешно отправить PDF-файл из 1С в WhatsApp через Base64 без ошибок валидации?

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

Интеграция 1С с популярными мессенджерами — одна из наиболее частых задач автоматизации бизнеса. Отправка счетов, актов, расходных накладных и печатных форм напрямую в WhatsApp значительно ускоряет документооборот. Однако при попытке отправить файл в формате PDF разработчики часто сталкиваются с ошибкой сервера HTTP 422 (Unprocessable Entity) и текстом ошибки вида {"status":"ERROR","message":"The string is not valid base64 (body)"}.

В этой статье мы подробно разберем, почему возникает эта ошибка валидации строки Base64, как особенности платформы 1С влияют на кодирование двоичных данных, и как правильно сформировать JSON-пакет для гарантированной доставки файлов через API-шлюзы WhatsApp.

В чем причина ошибки "The string is not valid base64"?

Давайте проанализируем ситуацию. При использовании стандартного метода 1С Base64Строка() (или его современного аналога ПолучитьBase64СтрокуИзДвоичныхДанных()) платформа преобразует бинарный файл в текстовую строку. Однако по умолчанию это преобразование происходит в соответствии со спецификацией MIME (RFC 2045).

Согласно этому стандарту, кодируемый текст должен разбиваться на строки фиксированной длины (обычно 72 или 76 символов). Чтобы выполнить это разбиение, платформа автоматически вставляет в полученную строку невидимые управляющие символы:

Для платформы 1С и некоторых локальных декодеров такая строка остается валидной. Но современные Web-сервисы, API-шлюзы и парсеры на стороне серверов WhatsApp ожидают получить Base64 в виде одной сплошной непрерывной строки без каких-либо служебных переносов. Наличие спецсимволов CRLF приводит к сбою валидации на веб-сервере, и мы получаем ошибку 422.

Шаг 1. Очистка строки Base64 от переносов строк

Выяснив причину проблемы, мы можем легко устранить ее. Для этого достаточно принудительно удалить все символы перевода строк и возврата каретки из полученной Base64-строки. Выполним это с помощью функции СтрЗаменить().

Важно удалять оба спецсимвола, так как на разных операционных системах и в разных контекстах они могут комбинироваться по-разному. Посмотрим на пример кода:


// Получаем чистую Base64-строку без переносов
СтрокаBase64 = Base64Строка(ДвоичныеДанныеФайла);
СтрокаBase64 = СтрЗаменить(СтрокаBase64, Символы.ПС, "");
СтрокаBase64 = СтрЗаменить(СтрокаBase64, Символы.ВК, "");

После этой несложной операции наша строка превратится в единый непрерывный массив символов, который без проблем пройдет проверку любым веб-валидатором.

Шаг 2. Использование правильного MIME-префикса (Data URL)

Для того чтобы принимающий веб-сервис и сам клиент WhatsApp поняли, какой тип файла им передается, стандартной Base64-строки бывает недостаточно. Если передать просто набор закодированных символов, принимающая сторона не сможет определить расширение файла (будь то картинка, PDF или текстовый документ).

Для решения этой проблемы большинство API-интеграторов используют схему Data URI. Перед очищенной строкой Base64 необходимо добавить специальную маску-префикс, определяющую MIME-тип документа.

Для PDF-файлов этот префикс выглядит следующим образом:

data:application/pdf;base64,

Для картинок формата JPEG префикс будет другим:

data:image/jpeg;base64,

Посмотрим, как правильно собрать итоговое значение для параметра body в нашем коде:


ПрефиксMime = "data:application/pdf;base64,";
ИтоговыйБоди = ПрефиксMime + СтрокаBase64;

Шаг 3. Извлечение имени файла стандартными методами

В процессе подготовки параметров запроса нам обязательно нужно передать имя отправляемого файла. Часто разработчики пишут сложные циклы для парсинга полного пути к файлу и поиска символа обратного слэша. Рассмотрим более простой, быстрый и элегантный способ получения имени файла с помощью стандартного объекта Файл:


// Вместо ручного поиска символов "\" в пути к файлу
ОбъектФайл = Новый Файл(ПутьКФайлу);
ИмяФайла = ОбъектФайл.Имя; // Получаем "ИмяФайла.pdf"

Этот метод работает надежно, независимо от того, под какой операционной системой (Windows или Linux) запущен сервер 1С.

Шаг 4. Правильное формирование JSON в 1С

Частой ошибкой при формировании JSON-пакетов является попытка «ручной сборки» строки с помощью пошаговой записи через методы ЗаписатьНачалоОбъекта(), ЗаписатьИмяСвойства() и так далее. Ручной метод перегружает код, усложняет чтение и отладку, а также может привести к синтаксическим ошибкам или проблемам с экранированием спецсимволов.

Мы рекомендуем использовать встроенный механизм сериализации 1С. Для этого мы сначала конструируем структуру данных (или массив структур, если этого требует спецификация API), а затем преобразуем ее в JSON одной командой ЗаписатьJSON(). Платформа 1С самостоятельно позаботится о правильном экранировании кавычек, слэшей и кодировании спецсимволов.

Проанализируем готовый пример правильного формирования JSON-пакета:


// Создаем структуру с параметрами запроса
ПараметрыЗапроса = Новый Структура;
ПараметрыЗапроса.Вставить("chatId",   НомерТелефонаПолучателя);
ПараметрыЗапроса.Вставить("body",     ИтоговыйБоди);
ПараметрыЗапроса.Вставить("filename", ИмяФайла);

// Если API требует передавать массив объектов (как в некоторых интеграциях)
МассивЗапроса = Новый Массив;
МассивЗапроса.Добавить(ПараметрыЗапроса);

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

ЗаписатьJSON(ЗаписьJSON, МассивЗапроса); // или просто ПараметрыЗапроса, в зависимости от API
СтрокаJSON = ЗаписьJSON.Закрыть();

Комплексное решение: Полный готовый шаблон кода для 1С

Теперь объединим все наши шаги в один готовый, структурированный и рабочий модуль на языке 1С. Этот шаблон вы можете использовать в своих обработках или регламентных заданиях для отправки печатных форм в WhatsApp.


// Функция подготавливает JSON-строку для отправки файла в WhatsApp
Функция СформироватьПакетДляОтправкиPDF(ТабличныйДокумент, НомерТелефона) Экспорт
    
    // 1. Сохраняем табличный документ во временный PDF-файл
    ПутьКВременномуФайлу = ПолучитьИмяВременногоФайла("pdf");
    ТабличныйДокумент.ОриентацияСтраницы = ОриентацияСтраницы.Ландшафт;
    ТабличныйДокумент.Записать(ПутьКВременномуФайлу, ТипФайлаТабличногоДокумента.PDF);
    
    // 2. Извлекаем имя файла для передачи в API
    ОбъектФайл = Новый Файл(ПутьКВременномуФайлу);
    ИмяФайла = ОбъектФайл.Имя;
    
    // 3. Считываем двоичные данные файла
    ДвоичныеДанныеФайла = Новый ДвоичныеДанные(ПутьКВременномуФайлу);
    
    // 4. Кодируем в Base64 и очищаем от служебных символов CRLF
    СтрокаBase64 = Base64Строка(ДвоичныеДанныеФайла);
    СтрокаBase64 = СтрЗаменить(СтрокаBase64, Символы.ПС, "");
    СтрокаBase64 = СтрЗаменить(СтрокаBase64, Символы.ВК, "");
    
    // 5. Формируем тело с MIME-префиксом для PDF
    ПрефиксMime = "data:application/pdf;base64,";
    ПолеBody = ПрефиксMime + СтрокаBase64;
    
    // 6. Формируем структуру параметров в соответствии с API
    СтруктураДанных = Новый Структура;
    СтруктураДанных.Вставить("chatId",   СокрЛП(НомерТелефона));
    СтруктураДанных.Вставить("body",     ПолеBody);
    СтруктураДанных.Вставить("filename", ИмяФайла);
    
    // Некоторые шлюзы требуют отправки массива объектов в теле запроса
    МассивОбъектов = Новый Массив;
    МассивОбъектов.Добавить(СтруктураДанных);
    
    // 7. Сериализуем данные в JSON
    ЗаписьJSON = Новый ЗаписьJSON();
    ПараметрыЗаписи = Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.Нет);
    ЗаписьJSON.УстановитьСтроку(ПараметрыЗаписи);
    
    ЗаписатьJSON(ЗаписьJSON, МассивОбъектов);
    РезультатJSON = ЗаписьJSON.Закрыть();
    
    // Удаляем временный файл с диска после использования
    Попытка
        УдалитьФайлы(ПутьКВременномуФайлу);
    Исключение
        ЗаписьЖурналаРегистрации("Отправка WhatsApp.Ошибка удаления файла", 
            УровеньЖурналаРегистрации.Предупреждение,,, ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
    КонецПопытки;
    
    Возврат РезультатJSON;
    
КонецФункции

Рекомендация по отправке HTTP-запроса

После того как вы получили валидную строку JSON в переменной РезультатJSON, отправьте ее на эндпоинт вашего API-провайдера. Помните, что при отправке POST-запроса обязательно нужно указывать правильный заголовок Content-Type: application/json, чтобы принимающий сервер корректно распарсил тело запроса.

Используя данный подход, вы гарантированно избавитесь от ошибок валидации Base64 строк и обеспечите стабильную отправку ваших счетов и накладных клиентам прямо на мобильные устройства.

← На главную