Интеграция систем 1С с облачными сервисами Google (такими как Google Диск и Google Таблицы) — востребованная задача при автоматизации совместной работы, выгрузки отчетов и обмена данными. Однако при работе с REST API сторонних сервисов разработчики часто сталкиваются с неочевидными техническими нюансами. Одной из распространенных проблем является ошибка "HTTP 400 Bad Request" с пояснением "Unsupported content with type: application/octet-stream" при попытке создать новые права доступа (метод permissions.create).
В этой статье мы подробно разберем, почему возникает данная ошибка, как правильно составить HTTP-запрос в 1С, а также рассмотрим важные скрытые параметры Google Drive API v3, без которых интеграция может работать некорректно или вызывать сбои в бизнес-процессах.
Давайте проанализируем ситуацию. При отправке POST-запроса к Google API для создания прав доступа мы передаем структурированные данные (тип прав, роль получателя, его e-mail) в формате JSON. В коде 1С для этого используется объект ЗаписьJSON, после чего сформированная строка помещается в тело запроса методом УстановитьТелоИзСтроки().
Однако по умолчанию платформа 1С при отправке запроса через объект HTTPСоединение не добавляет информацию о типе передаваемого контента. Веб-сервер Google, принимая этот запрос, не может автоматически определить формат данных и интерпретирует их как бинарный поток — application/octet-stream. Поскольку метод API ожидает строго JSON, сервер возвращает ошибку 400 Bad Request.
Для решения этой проблемы необходимо явно указать тип контента в заголовках HTTP-запроса. Для этого мы вставляем заголовок Content-Type со значением application/json в наше соответствие заголовков перед отправкой запроса:
Заголовки = Новый Соответствие;
Заголовки.Вставить("Authorization", "Bearer " + inAccessToken);
Заголовки.Вставить("Content-Type", "application/json"); // Явное указание формата данных
После добавления этого заголовка Google API успешно распознает тело запроса, и права доступа создаются. Однако это далеко не единственная сложность, с которой вы можете столкнуться. Ниже мы разберем еще 5 важнейших нюансов интеграции, которые уберегут вас от скрытых багов.
Давайте рассмотрим по шагам неочевидные параметры и настройки, которые критически важны для стабильной работы обмена.
В стандартном коде разработчики часто совершают опечатку, указывая в адресе запроса параметр получения ответа в единственном числе:
/drive/v3/files/<FileID>/permissions?field=*
В чем проблема: В спецификации Google API этот параметр называется во множественном числе — fields. Если написать его с ошибкой (field), Google проигнорирует некорректный параметр и вернет сокращенный стандартный ответ (содержащий только id, type и role). Если вашей системе в дальнейшем понадобятся другие возвращаемые данные (например, имя пользователя или адрес почты), вы их не получите.
Решение: Всегда указывайте fields=* для получения полной информации о созданных правах или перечисляйте конкретные поля через запятую (например, fields=id,emailAddress,role) для оптимизации трафика.
По умолчанию при успешном предоставлении прав на файл Google Диск автоматически отправляет на почту получателя письмо-уведомление. Если ваша обработка в 1С пачками раздает права пользователям в фоновом режиме, это приведет к массовому спаму на почтовые ящики сотрудников или клиентов.
Решение: Используйте специальный query-параметр sendNotificationEmail=false в строке URL-запроса. Обратите внимание, что его нужно передавать именно в URL, а не в теле JSON-документа:
/drive/v3/files/<FileID>/permissions?sendNotificationEmail=false&fields=*
Если целевой файл Google Sheets создан не на вашем личном диске, а находится в общем корпоративном пространстве (Shared Drive), обычный запрос вернет ошибку 404 Not Found, даже если ID файла указан абсолютно верно.
Решение: Для обеспечения совместимости с общими дисками организации обязательно добавляйте в строку запроса параметр supportsAllDrives=true. Полный URL-путь запроса примет следующий вид:
/drive/v3/files/<FileID>/permissions?supportsAllDrives=true&sendNotificationEmail=false&fields=*
Для того чтобы метод создания прав успешно отрабатывал, ваш действующий access_token должен обладать достаточными правами доступа. Области доступа (scopes), ограничивающиеся только чтением или работой непосредственно с таблицами (например, https://www.googleapis.com/auth/spreadsheets), не подойдут. Google вернет ошибку доступа 403 Forbidden.
Убедитесь, что при генерации токена авторизации вы запрашиваете одну из следующих областей видимости:
При получении ответа от сервера с помощью метода ПолучитьТелоКакСтроку() без явного указания кодировки русские символы (например, имена и фамилии пользователей в структуре ответа) могут отобразиться в виде нечитаемых символов ("кракозябр").
Решение: Всегда принудительно задавайте кодировку UTF-8 при чтении ответа сервера:
СтрокаОтвет = HTTPОтвет.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
Объединим все вышеперечисленные исправления и лучшие практики в один готовый, универсальный и отказоустойчивый программный код, который вы можете использовать в своих обработках:
Функция ПредоставитьДоступКФайлуGoogle(Знач ТокенАвторизации, Знач ИДФайла, Знач EmailПолучателя, Знач РольДоступа = "reader", Знач ТипПолучателя = "user") Экспорт
// 1. Настройка параметров подключения к API
СерверГугл = "www.googleapis.com";
SslПараметр = Новый ЗащищенноеСоединениеOpenSSL(Неопределено, Неопределено);
Соединение = Новый HTTPСоединение(СерверГугл, , , , , 15, SslПараметр);
// 2. Формирование заголовков запроса
Заголовки = Новый Соответствие;
Заголовки.Вставить("Authorization", "Bearer " + ТокенАвторизации);
Заголовки.Вставить("Content-Type", "application/json"); // Исправление ошибки 400
// 3. Формирование параметров запроса в URL
// Отключаем email-уведомления, включаем поддержку общих дисков и запрашиваем полный ответ fields
ПараметрыЗапроса = "sendNotificationEmail=false&supportsAllDrives=true&fields=*";
ПутьЗапроса = "/drive/v3/files/" + ИДФайла + "/permissions?" + ПараметрыЗапроса;
HTTPЗапрос = Новый HTTPЗапрос(ПутьЗапроса, Заголовки);
// 4. Формирование JSON-тела запроса
ТелоЗапроса = Новый Структура;
ТелоЗапроса.Вставить("kind", "drive#permission");
ТелоЗапроса.Вставить("type", ТипПолучателя);
ТелоЗапроса.Вставить("role", РольДоступа);
ТелоЗапроса.Вставить("emailAddress", EmailПолучателя);
НастройкиСериализации = Новый НастройкиСериализацииJSON;
НастройкиСериализации.ВариантЗаписиДаты = ВариантЗаписиДатыJSON.ЛокальнаяДатаСоСмещением;
НастройкиСериализации.ФорматСериализацииДаты = ФорматДатыJSON.ISO;
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, ТелоЗапроса, НастройкиСериализации);
СтрJSON = ЗаписьJSON.Закрыть();
HTTPЗапрос.УстановитьТелоИзСтроки(СтрJSON, КодировкаТекста.UTF8);
// 5. Выполнение запроса и обработка результата
Попытка
HTTPОтвет = Соединение.ВызватьHTTPМетод("POST", HTTPЗапрос);
СтрокаОтвет = HTTPОтвет.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8); // Защита от кракозябр
Если HTTPОтвет.КодСостояния > 299 Тогда
ВызватьИсключение "Ошибка API Google (Код " + HTTPОтвет.КодСостояния + "): " + СтрокаОтвет;
КонецЕсли;
Возврат СтрокаОтвет; // Возвращаем JSON-ответ с описанием созданных прав
Исключение
ЗаписьЖурналаРегистрации("Интеграция.GoogleDriveAPI",
УровеньЖурналаРегистрации.Ошибка, , ,
"Ошибка при предоставлении прав к файлу " + ИДФайла + ": " + ОписаниеОшибки());
ВызватьИсключение;
КонецПопытки;
КонецФункции
Используя данный шаблон, вы полностью застрахованы от ошибок форматирования контента, проблем с кодировками кириллицы в именах пользователей, спама на почтовые ящики клиентов и некорректной обработки файлов, находящихся на общих дисках вашей организации.