Интеграция 1С с маркетплейсами — одна из самых частых задач современного разработчика. При работе с Wildberries API одной из наиболее коварных проблем является получение ошибки HTTP 401 (Unauthorized). Ситуация усложняется тем, что у одних клиентов код может работать исправно, а у других тот же самый запрос возвращает ошибку авторизации. При этом сам токен API выглядит вполне рабочим и активным.
В этой статье мы подробно разберем, почему возникает ошибка 401 при попытке получить остатки через метод /api/v1/warehouse_remains, как правильно диагностировать эту проблему, настроить права доступа на портале Wildberries и адаптировать код 1С под современные стандарты безопасности и асинхронности API.
Главная и самая распространенная причина ошибки HTTP 401 при вызове метода получения остатков — недостаточные права доступа (категории) созданного токена. При создании токена в личном кабинете партнера Wildberries (в разделе «Доступ к API») пользователю предлагается выбрать чекбоксы для различных разделов системы: «Цены и скидки», «Контент», «Маркетплейс», «Аналитика», «Статистика» и другие.
Разработчики часто совершают логическую ошибку, полагая, что получение остатков на складах относится к разделу «Статистика». Исторически старые методы (например, /api/v1/supplier/stocks) действительно требовали только категорию «Статистика». Однако современный и более точный метод получения остатков /api/v1/warehouse_remains относится к категории «Аналитика».
Если у токена клиента активна только категория «Статистика», сервер авторизации Wildberries вернет ошибку 401 Unauthorized при попытке обратиться к методам аналитики. Чтобы исправить это, выполним следующие шаги:
Проанализировать права уже имеющегося токена можно без доступа в личный кабинет клиента. Токен Wildberries представляет собой JWT-токен, который можно легко декодировать. Для этого можно воспользоваться встроенными инструментами на портале для разработчиков Wildberries или сторонними библиотеками. При декодировании обратите внимание на список доступных категорий. Если там присутствует только «Статистика», токен гарантированно будет отдавать 401 ошибку на запросы остатков.
Вторая частая ошибка кроется в формировании заголовков HTTP-запроса. Согласно официальной спецификации Wildberries API, токен авторизации должен передаваться в заголовке Authorization с обязательным префиксом Bearer. Если передать токен «в чистом виде», некоторые шлюзы безопасности Wildberries могут отклонить запрос с кодом 401.
Рассмотрим, как правильно сформировать заголовки в коде 1С:
мЗаголовки = Новый Соответствие;
// Обязательно добавляем префикс "Bearer " перед телом токена
мЗаголовки.Вставить("Authorization", "Bearer " + СокрЛП(Токен));
мЗаголовки.Вставить("Content-Type", "application/json");
Использование метода СокрЛП() критически важно, чтобы случайно не передать невидимые символы переноса строк или пробелы, которые клиент мог скопировать вместе с токеном из личного кабинета.
Wildberries разделяет свои сервисы на разные физические серверы в зависимости от назначения методов. Это означает, что отправлять запросы аналитики на сервер статистики нельзя. Проанализируем правильное распределение хостов:
statistics-api.wildberries.ru/api/v1/warehouse_remains) запросы должны отправляться на хост: seller-analytics-api.wildberries.ruЕсли в коде вашей интеграции жестко зашит адрес сервера статистики для всех запросов, обращение к методам остатков вызовет сбой авторизации или ошибку отсутствия ресурса (HTTP 404/401).
Даже когда вы решите проблему с авторизацией (код 401 исчезнет), стандартный линейный код 1С столкнется с новой проблемой. Метод /api/v1/warehouse_remains является асинхронным. Это сделано для снижения нагрузки на серверы Wildberries, так как моментальный расчет остатков по всем складам для крупных продавцов требует больших вычислительных ресурсов.
Вы не можете получить таблицу остатков в одно действие. Процесс работы с асинхронным методом строится по следующему алгоритму:
/api/v1/warehouse_remains с необходимыми параметрами группировки. В ответ сервер возвращает HTTP-статус 200 и JSON, содержащий уникальный идентификатор задачи taskId./api/v1/warehouse_remains/tasks/{taskId}/status, подставляя полученный ранее ID. Ждем, пока в структуре ответа значение поля status не изменится на "done" (выполнено)./api/v1/warehouse_remains/tasks/{taskId}/download для получения фактических данных по остаткам.Если проигнорировать этот алгоритм и попытаться прочитать ответ первого запроса как готовую таблицу остатков, ваша программа упадет с ошибкой разбора JSON, так как вместо таблицы придет простой технический идентификатор задачи.
Недавно Wildberries обновил логику работы метода скачивания отчетов. Ранее, если остатков по заданным фильтрам не обнаруживалось, сервер возвращал статус HTTP 200 и пустой массив данных [] в теле ответа. Теперь же, при отсутствии данных для скачивания, сервер возвращает статус HTTP 204 No Content с пустым телом.
Если в вашем коде 1С прописана жесткая проверка на успешность только по коду 200:
Если Результат.КодСостояния = 200 Тогда
То при получении кода 204 ваша программа посчитает это ошибкой выполнения и вызовет аварийное исключение. Нам необходимо предусмотреть обработку кода 204 как успешного пустого результата.
Объединим все вышеперечисленные правила в единый отказоустойчивый модуль. Разберем по шагам функцию, которая корректно авторизуется с префиксом Bearer, отправляет асинхронный запрос на сервер аналитики, ожидает выполнения задачи в цикле и корректно обрабатывает пустые результаты со статусом 204.
&НаСервере
Функция ПолучитьОстаткиСкладов_WB(Токен, ПараметрыГруппировки = "") Экспорт
// Шаг 1. Настройка подключения к правильному серверу аналитики
АдресСервераАналитики = "seller-analytics-api.wildberries.ru";
мHTTPСоединение = Новый HTTPСоединение(АдресСервераАналитики,,,,,, Новый ЗащищенноеСоединениеOpenSSL());
// Формируем заголовки по стандарту Bearer-авторизации
мЗаголовки = Новый Соответствие;
мЗаголовки.Вставить("Authorization", "Bearer " + СокрЛП(Токен));
мЗаголовки.Вставить("Content-Type", "application/json");
// Шаг 2. Инициализация задачи на формирование отчета остатков
МетодИнициализации = "/api/v1/warehouse_remains";
СтрокаПараметров = ?(ЗначениеЗаполнено(ПараметрыГруппировки), ПараметрыГруппировки,
"?groupByBrand=true&groupBySubject=true&groupBySa=true&groupByNm=true&groupByBarcode=true&groupBySize=true");
мHTTPЗапрос = Новый HTTPЗапрос(МетодИнициализации + СтрокаПараметров, мЗаголовки);
мРезультат = мHTTPСоединение.Получить(мHTTPЗапрос);
Если мРезультат.КодСостояния <> 200 Тогда
ВызватьИсключение "Ошибка инициализации задачи остатков WB. Код состояния: " + мРезультат.КодСостояния
+ ". Текст ответа: " + мРезультат.ПолучитьТелоКакСтроку();
КонецЕсли;
// Читаем ID созданной сервером задачи
мОтветJSON = мРезультат.ПолучитьТелоКакСтроку();
мЧтениеJSON = Новый ЧтениеJSON;
мЧтениеJSON.УстановитьСтроку(мОтветJSON);
ДанныеЗадачи = ПрочитатьJSON(мЧтениеJSON);
мЧтениеJSON.Закрыть();
Попытка
TaskId = ДанныеЗадачи.data.taskId;
Исключение
ВызватьИсключение "Не удалось получить taskId из ответа сервера WB. Ответ: " + мОтветJSON;
КонецПопытки;
// Шаг 3. Цикл ожидания готовности отчета (опрос статуса задачи)
МаксимальноеВремяОжиданияСекунд = 120; // 2 минуты лимит
ИнтервалОпросаСекунд = 5;
ПрошлоСекунд = 0;
ОтчетГотов = Ложь;
Пока ПрошлоСекунд < МаксимальноеВремяОжиданияСекунд Цикл
МетодПроверкиСтатуса = "/api/v1/warehouse_remains/tasks/" + TaskId + "/status";
ЗапросСтатуса = Новый HTTPЗапрос(МетодПроверкиСтатуса, мЗаголовки);
РезультатСтатуса = мHTTPСоединение.Получить(ЗапросСтатуса);
Если РезультатСтатуса.КодСостояния = 200 Тогда
ЧтениеСтатуса = Новый ЧтениеJSON;
ЧтениеСтатуса.УстановитьСтроку(РезультатСтатуса.ПолучитьТелоКакСтроку());
ОтветСтатуса = ПрочитатьJSON(ChтениеСтатуса);
ЧтениеСтатуса.Закрыть();
ТекущийСтатус = ОтветСтатуса.data.status;
Если ТекущийСтатус = "done" Тогда
ОтчетГотов = Истина;
Прервать;
ИначеЕсли ТекущийСтатус = "error" Тогда
ВызватьИсключение "Сервер Wildberries вернул ошибку при формировании отчета по задаче: " + TaskId;
КонецЕсли;
КонецЕсли;
// Приостанавливаем выполнение потока на сервере 1С (имитация паузы)
#Если Клиент Тогда
Сигнал(); // Для тонкого клиента
#КонецЕсли
// Простейшая задержка на сервере через заблокированное фоновое задание или ping
// В реальной практике лучше использовать ПодключитьОбработчикОжидания на клиенте
// Для демонстрации используем простой замер времени:
ТекущаяДатаЗамера = ТекущаяДата();
Пока ТекущаяДата() < ТекущаяДатаЗамера + ИнтервалОпросаСекунд Цикл
// Пустой цикл ожидания интервала
КонецЦикла;
ПрошлоСекунд = ПрошлоСекунд + ИнтервалОпросаСекунд;
КонецЦикла;
Если Не ОтчетГотов Тогда
ВызватьИсключение "Превышено время ожидания формирования отчета остатков на стороне WB.";
КонецЕсли;
// Шаг 4. Скачивание готового отчета
МетодСкачивания = "/api/v1/warehouse_remains/tasks/" + TaskId + "/download";
ЗапросСкачивания = Новый HTTPЗапрос(МетодСкачивания, мЗаголовки);
РезультатСкачивания = мHTTPСоединение.Получить(ЗапросСкачивания);
// Обрабатываем успешный пустой ответ (HTTP 204 No Content)
Если РезультатСкачивания.КодСостояния = 204 Тогда
Возврат Новый Массив; // Возвращаем пустую таблицу остатков
КонецЕсли;
// Обрабатываем успешное получение данных (HTTP 200)
Если РезультатСкачивания.КодСостояния = 200 Тогда
ЧтениеДанных = Новый ЧтениеJSON;
ЧтениеДанных.УстановитьСтроку(РезультатСкачивания.ПолучитьТелоКакСтроку());
ТаблицаОстатков = ПрочитатьJSON(ЧтениеДанных, Истина); // считываем как Соответствие/Массив
ЧтениеДанных.Закрыть();
Возврат ТаблицаОстатков;
Иначе
ВызватьИсключение "Ошибка при скачивании отчета остатков. Код состояния: " + РезультатСкачивания.КодСостояния;
EndIf;
КонецФункции
Если ваша обработка 1С продолжает возвращать ошибку 401 при работе с Wildberries API, последовательно проверьте следующие пункты:
/api/v1/warehouse_remains.Bearer с последующим пробелом перед токеном в заголовке запроса.seller-analytics-api.wildberries.ru, а не на statistics-api.wildberries.ru.Используя предложенный нами асинхронный алгоритм и настроив корректную авторизацию, вы сможете построить стабильный и надежный обмен данными между 1С и Wildberries, который продолжит корректно работать даже при обновлении требований безопасности маркетплейса.