phpsoftbox / wildberries
Wildberries API client component for the PhpSoftBox framework
Requires
- php: ^8.5
- phpsoftbox/collection: dev-master
- psr/http-client: ^1.0
- psr/http-factory: ^1.0
- psr/http-message: ^2.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.93
- phpsoftbox/cli-app: dev-master
- phpsoftbox/code-generator: dev-master
- phpsoftbox/cs-fixer: ^1.1.0
- phpsoftbox/http-message: dev-master
- phpunit/phpunit: ^11.2
- symfony/yaml: ^7.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-08-31 12:24:42 UTC
README
About
phpsoftbox/wildberries — API-клиент Wildberries на базе PSR-18.
Компонент включает:
WildberriesApiClientс поддержкой нескольких API-хостов;- универсальные HTTP-методы
get/post/put/patch/delete/request; - секции API, сгенерированные из OpenAPI (
general,products,ordersFbs,ordersDbw,ordersDbs,inStorePickup,ordersFbw,promotion,communications,tariffs,analytics,reports,finances); - ответы в
WildberriesApiResponse, совместимом сPhpSoftBox\Collection\Collection; WildberriesApiResponse::makeDto()для явного преобразования ответа в DTO;- централизованные повторы безопасных запросов после HTTP 429;
WildberriesExceptionсо статусом и payload.
Quick Start
use PhpSoftBox\Http\Message\RequestFactory; use PhpSoftBox\Http\Message\StreamFactory; use PhpSoftBox\Wildberries\WildberriesApiClient; $client = new WildberriesApiClient( token: $_ENV['WILDBERRIES_API_TOKEN'], httpClient: $psr18Client, requestFactory: new RequestFactory(), streamFactory: new StreamFactory(), authorizationScheme: 'Bearer', ); // Низкоуровневый вызов $stocks = $client->marketplace()->get('/api/v3/orders/new'); // Вызов через секцию API $parents = $client->products()->objectParentAll();
Повтор запросов после HTTP 429
Клиент автоматически обрабатывает 429 Too Many Requests для всех HTTP-методов.
Это относится как к читающим GET, HEAD и POST, так и к изменяющим POST,
PUT, PATCH и DELETE. Повтор выполняется только после фактически полученного
ответа 429 от WB: сетевые ошибки, timeout и другие HTTP-статусы этот механизм не
перехватывает.
По умолчанию клиент делает не более четырёх попыток, включая первоначальный запрос.
Перед повтором он читает X-RateLimit-Retry как число секунд. Если заголовок
отсутствует или некорректен, используются задержки 1, 2 и 4 секунды. На каждом
следующем 429 фактическая задержка выбирается как максимальная из нового значения
заголовка и fallback-задержки текущей попытки.
Чтобы синхронный worker не блокировался на длительный cooldown, по умолчанию также действуют два бюджета:
- одна задержка — не более 30 секунд;
- сумма задержек одного вызова клиента — не более 60 секунд.
Клиент не обрезает задержку до лимита: более ранний повтор противоречил бы значению
X-RateLimit-Retry. Вместо ожидания выбрасывается WildberriesRateLimitException,
содержащий требуемое время в retryAfterSeconds(), HTTP-статус 429 и payload ответа.
Это же исключение выбрасывается, если исчерпано число попыток или policy запретила
повтор. Оно наследует WildberriesException, поэтому существующий общий catch
продолжает работать.
Тело запроса сохраняется до первого вызова PSR-18 клиента. Для каждой попытки создаётся новый stream, поэтому запрос повторяется с полным исходным JSON, даже если предыдущий HTTP-вызов прочитал stream до конца.
Настройка retry
Все параметры собраны в RateLimitRetryOptions:
use PhpSoftBox\Wildberries\Retry\RateLimitRetryOptions; use PhpSoftBox\Wildberries\Retry\WildberriesRetryEvent; use PhpSoftBox\Wildberries\WildberriesApiClient; $client = new WildberriesApiClient( token: $token, httpClient: $psr18Client, requestFactory: $requestFactory, streamFactory: $streamFactory, rateLimitRetry: new RateLimitRetryOptions( maxAttempts: 4, maxDelaySeconds: 30, maxTotalDelaySeconds: 60, onRetry: static function (WildberriesRetryEvent $event): void { // $event->attempt — номер предстоящей попытки: 2 для первого повтора. // Также доступны delaySeconds, method, endpoint и statusCode. }, ), );
maxAttempts: 1 полностью отключает фактические повторы, сохраняя обычную обработку
ответа 429 через WildberriesRateLimitException. null вместо одного из бюджетов
отключает соответствующее ограничение. Отрицательные и бесконечные значения считаются
ошибкой конфигурации.
Длительный cooldown удобно передать планировщику без блокировки worker-а:
use PhpSoftBox\Wildberries\WildberriesRateLimitException; try { $result = $client->products()->tags(); } catch (WildberriesRateLimitException $exception) { $job->releaseAfter($exception->retryAfterSeconds()); }
Для тестов или интеграции с собственным механизмом ожидания можно передать реализацию
SleeperInterface. Она получает рассчитанную задержку в секундах, поэтому unit-тестам
не требуется ждать в реальном времени.
Исключение запросов из retry
По умолчанию DefaultRetryableRequestPolicy разрешает повтор любого запроса после
429. Если отдельную операцию повторять нельзя, её можно исключить через callback:
use PhpSoftBox\Wildberries\Retry\CallbackRetryableRequestPolicy; use PhpSoftBox\Wildberries\Retry\RateLimitRetryOptions; use Psr\Http\Message\RequestInterface; $retry = new RateLimitRetryOptions( requestPolicy: new CallbackRetryableRequestPolicy( static fn (RequestInterface $request): bool => $request->getUri()->getPath() !== '/custom/non-retryable', ), );
Для более сложных правил можно реализовать RetryableRequestPolicyInterface.
Метод allows() получает PSR-7 request целиком, поэтому решение может учитывать
HTTP-метод, host, path и другие признаки запроса. Policy определяет только допустимость
повтора: сам retry всё равно выполняется исключительно после HTTP 429.
DTO ответы
Wrapper-методы остаются совместимыми с Collection. Если для endpoint-а есть сгенерированный DTO, его можно получить явно:
$parents = $client->products()->objectParentAll()->makeDto();
Для низкоуровневых вызовов работает та же карта DTO:
$response = $client->marketplace() ->put('/api/v3/orders/123/meta/gtin', ['gtin' => '04601234567890']) ->makeDto();
Генерация DTO
DTO генерируются из локальных OpenAPI YAML файлов в docs/:
vendor/bin/psb wildberries:openapi:generate-dto
Команда обновляет src/Dto и src/Dto/WildberriesResponseDtoMap.php. Wrapper-классы не меняются: основной контракт остается WildberriesApiResponse/Collection, а DTO создаются явно через makeDto().
Тестовый контур
Официальная песочница WB требует отдельный токен типа Тестовый контур.
Production-токен и sandbox-токен не взаимозаменяемы. Компонент не читает переменные
окружения и не переключает окружение автоматически: нужные адреса передаёт приложение.
use PhpSoftBox\Wildberries\WildberriesApiBasesEnum; $client = new WildberriesApiClient( token: $testToken, httpClient: $psr18Client, requestFactory: new RequestFactory(), streamFactory: new StreamFactory(), authorizationScheme: 'Bearer', apiBases: WildberriesApiBasesEnum::sandbox(), ); $client->sandbox()->fbsOrdersMake([ 'orders' => [ ['sku' => 'BarcodeTest123', 'amount' => 1], ], ]);
WildberriesApiBasesEnum::sandbox() содержит официальные адреса доступных sandbox-хостов.
При необходимости отдельные адреса по-прежнему можно переопределить через apiBases.
Секция sandbox() использует логический хост marketplace. Специальные FBS-методы
песочницы позволяют создать тестовые сборочные задания и эмулировать отмену, доставку,
получение, отказ, брак и закрытие поставки.
Актуальные ограничения и требования описаны в официальной документации тестового контура WB.