При интеграции 1С с маркетплейсами, в частности с Wildberries, разработчики часто сталкиваются с ошибками при работе с API. Одна из самых распространенных — это ошибка формата даты при отправке запросов на получение данных за определенный период. Давайте вместе разберем реальный случай, когда при попытке получить заказы с Wildberries сервер возвращает ответ: {"error":"Некорректный формат переданной даты."}. Проанализируем исходный код, выясним причины проблемы и найдем правильное решение.
Исходная ситуация выглядит так: программист формирует GET-запрос к API Wildberries для получения заказов, передавая в параметрах дату начала и конца периода. Вот фрагмент кода, который приводит к ошибке:
Токен = "xxxxxx";
Заголовки = новый Соответствие();
Заголовки.Вставить("X-Auth-Token", Токен);
Заголовки.Вставить("Content-Type", "application/json");
SSL_Соединение = Новый ЗащищенноеСоединениеOpenSSL();
HttpСоединение = новый HttpСоединение("suppliers-orders.wildberries.ru", 443, , , , SSL_Соединение);
// Даты формируются в формате ISO 8601 со смещением часового пояса
Сервис = "/api/v1/orders?date_start=2020-12-20T00:00:00+03:00&date_end=2021-01-12T00:00:00+03:00";
HTTPЗапрос = новый HttpЗапрос(сервис, заголовки);
HttpОтвет = HTTPСоединение.Получить(HTTPЗапрос);
Результат = HttpОтвет.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
// В переменной Результат получаем: {"error":"Некорректный формат переданной даты."}
На первый взгляд, формат даты 2020-12-20T00:00:00+03:00 соответствует стандарту, и даже в старой документации Wildberries можно было встретить подобные примеры. Однако, как это часто бывает, дьявол кроется в деталях. Разберем по шагам, что здесь может быть не так.
Давайте внимательно посмотрим на строку запроса, а именно на параметр даты: ...T00:00:00<strong>+</strong>03:00. Символ + является специальным символом в URL. При передаче в строке запроса он по стандарту интерпретируется как пробел. Это означает, что сервер Wildberries вместо ожидаемого +03:00 получает 03:00 (с пробелом). Естественно, такая строка не может быть распознана как корректное смещение часового пояса, что и приводит к ошибке формата даты.
Решение: Все параметры, которые вставляются в URL, необходимо кодировать с помощью специального механизма URL-encoding. В 1С для этого есть функция КодироватьСтроку().
Неправильно кодировать всю строку целиком. Кодировать нужно значение каждого параметра по отдельности, а затем уже собирать итоговую строку запроса. Посмотрим на исправленный вариант формирования строки:
// Формируем даты как строки в нужном формате
ДатаНачалоСтрокой = Формат(ДатаНачала, "ДФ='yyyy-MM-ddTHH:mm:ss+03:00'");
ДатаОкончанияСтрокой = Формат(ДатаОкончания, "ДФ='yyyy-MM-ddTHH:mm:ss+03:00'");
// Кодируем ТОЛЬКО значения параметров
ЗакодированнаяДатаНачало = КодироватьСтроку(ДатаНачалоСтрокой, СпособКодированияСтроки.КодировкаURL);
ЗакодированнаяДатаОкончания = КодироватьСтроку(ДатаОкончанияСтрокой, СпособКодированияСтроки.КодировкаURL);
// Собираем итоговую строку сервиса
Сервис = "/api/v1/orders?date_start=" + ЗакодированнаяДатаНачало + "&date_end=" + ЗакодированнаяДатаОкончания;
После такого преобразования символ + будет заменен на его код %2B, и сервер получит корректную строку: ...T00:00:00%2B03:00. В большинстве случаев уже одно это действие решает проблему.
Даже после кодирования ошибка может сохраняться. Часто это связано с тем, что API-серверы настроены на прием даты и времени в универсальном координированном времени (UTC). Передача смещения часового пояса (например, +03:00) может быть не поддержана или работать нестабильно.
Решение: Лучшей практикой при работе с API является передача времени в формате UTC. По стандарту ISO 8601 это обозначается буквой Z в конце строки времени. Это однозначно указывает серверу, что время передано по Гринвичу (нулевой часовой пояс).
Давайте изменим код, чтобы он формировал дату в UTC:
Получаем универсальную дату. В 1С для этого можно использовать функцию ТекущаяУниверсальнаяДата() или преобразовать локальную дату в UTC.
Форматируем строку. При форматировании нужно добавить в конце символ Z.
Пример формирования правильной строки даты в UTC:
// Предположим, у нас есть ДатаНачала (локальное время)
// Преобразуем ее в UTC. Простой способ - вычесть разницу с UTC.
// РазницаЧасовыхПоясов = (ТекущаяДата() - ТекущаяУниверсальнаяДата()) / 3600; // в часах
// ДатаНачалаUTC = ДатаНачала - РазницаЧасовыхПоясов * 3600;
// Более надежный способ получить текущее время UTC и отформатировать его
ДатаНачалаUTC = ТекущаяУниверсальнаяДата();
ДатаОкончанияUTC = ТекущаяУниверсальнаяДата() + 3600; // например, +1 час
// Форматируем строку в соответствии со стандартом, добавляя 'Z' вручную
ДатаНачалоСтрокой = Формат(ДатаНачалаUTC, "ДФ='yyyy-MM-ddTHH:mm:ss'") + "Z";
ДатаОкончанияСтрокой = Формат(ДатаОкончанияUTC, "ДФ='yyyy-MM-ddTHH:mm:ss'") + "Z";
// Кодировать значения уже не нужно, так как в них нет спецсимволов, но оставим это как хорошую практику
ЗакодированнаяДатаНачало = КодироватьСтроку(ДатаНачалоСтрокой, СпособКодированияСтроки.КодировкаURL);
ЗакодированнаяДатаОкончания = КодироватьСтроку(ДатаОкончанияСтрокой, СпособКодированияСтроки.КодировкаURL);
Сервис = "/api/v1/orders?date_start=" + ЗакодированнаяДатаНачало + "&date_end=" + ЗакодированнаяДатаОкончания;
Использование формата с Z — наиболее надежный и кроссплатформенный способ передачи времени, который понимают практически все современные API.
В процессе решения проблемы выяснился еще один важный аспект: версия API. В исходном коде используется эндпоинт /api/<strong>v1</strong>/orders. Wildberries, как и многие другие крупные платформы, постоянно развивает свой API. Старые версии (v1, v2) могут быть объявлены устаревшими (deprecated), работать нестабильно или вовсе отключаться.
Решение: Всегда сверяйтесь с актуальной официальной документацией для разработчиков на портале Wildberries. На сегодняшний день для работы с заказами используются более новые версии API (например, `v3`), которые имеют другие требования:
/api/v3/orders.X-Auth-Token используется стандартный заголовок Authorization с токеном типа Bearer. Выглядит это так: Authorization: Bearer <Ваш_API_ключ>.Таким образом, если вы столкнулись с подобной ошибкой, первым делом убедитесь, что вы используете актуальную и поддерживаемую версию API.
Соберем все рекомендации воедино и напишем итоговый, современный вариант кода для подключения к API Wildberries. Будем использовать актуальный метод авторизации и формат даты UTC.
// Используйте API-ключ нового формата!
Токен = "eyJhbGciOiJFUzI1NiIsImtpZCI6IjIwMjMtMDYtMj...";
Заголовки = Новый Соответствие();
// Актуальный заголовок авторизации
Заголовки.Вставить("Authorization", "Bearer " + Токен);
Заголовки.Вставить("Content-Type", "application/json");
Заголовки.Вставить("Accept", "application/json"); // Рекомендуемый заголовок
// Используем актуальный хост для API поставщиков
HttpСоединение = Новый HttpСоединение("suppliers-api.wildberries.ru", 443, , , , Новый ЗащищенноеСоединениеOpenSSL());
// Даты в UTC и формате YYYY-MM-DDTHH:MM:SSZ
ДатаНачалаUTC = ТекущаяУниверсальнаяДата() - 86400; // Сутки назад
ДатаОкончанияUTC = ТекущаяУниверсальнаяДата();
ДатаНачалоСтрокой = Формат(ДатаНачалаUTC, "ДФ='yyyy-MM-ddTHH:mm:ss'") + "Z";
ДатаОкончанияСтрокой = Формат(ДатаОкончанияUTC, "ДФ='yyyy-MM-ddTHH:mm:ss'") + "Z";
// Кодируем значения параметров на случай наличия спецсимволов
ЗакодированнаяДатаНачало = КодироватьСтроку(ДатаНачалоСтрокой, СпособКодированияСтроки.КодировкаURL);
ЗакодированнаяДатаОкончания = КодироватьСтроку(ДатаОкончанияСтрокой, СпособКодированияСтроки.КодировкаURL);
// Используем актуальный эндпоинт (пример, уточняйте в документации!)
Сервис = "/api/v3/orders?limit=100&next=0&dateFrom=" + ЗакодированнаяДатаНачало + "&dateTo=" + ЗакодированнаяДатаОкончания;
HTTPЗапрос = Новый HttpЗапрос(Сервис, Заголовки);
Попытка
HttpОтвет = HttpСоединение.Получить(HTTPЗапрос);
Если HttpОтвет.КодСостояния >= 200 И HttpОтвет.КодСостояния < 300 Тогда
Результат = HttpОтвет.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
Сообщить("Успешный ответ от сервера!");
// Дальнейшая обработка JSON...
Иначе
ТекстОшибки = HttpОтвет.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
Сообщить("Ошибка при запросе. Код: " + HttpОтвет.КодСостояния + ". Ответ: " + ТекстОшибки);
КонецЕсли;
Исключение
Сообщить("Исключение при выполнении HTTP-запроса: " + ОписаниеОшибки());
КонецПопытки;
Для отладки всегда выводите в лог итоговую строку Сервис, которую вы отправляете, а также полный ответ сервера, включая код состояния и тело ответа. Это поможет быстро локализовать проблему, если она возникнет снова.