Skip to content

Руководство по началу работы с самовывозом ​

Это руководство охватывает всё, что нужно знать для работы с заказами на самовывоз (click-and-collect) в TypeScript SDK Wildberries.

Содержание ​

Что такое самовывоз? ​

Самовывоз (click-and-collect) — это модель выполнения заказов, при которой:

  1. Покупатель заказывает онлайн: Покупатель оформляет заказ через Wildberries
  2. Продавец готовит заказ: Продавец собирает и подготавливает товар в своей физической точке
  3. Покупатель забирает лично: Покупатель приходит в точку продавца и забирает заказ

Ключевые особенности ​

ОсобенностьОписание
Физическая точкаУ продавца есть магазин или пункт выдачи
Верификация покупателяПроверка личности по коду перед выдачей
Процесс сборкиСтруктурированный жизненный цикл: новый, подтвердить, подготовить, выдать/отклонить
Отслеживание метаданныхКоды маркировки товаров (IMEI, SGTIN, UIN, GTIN) для соответствия требованиям
Штраф за 409Ответы 409 Conflict засчитываются как 10 запросов к лимиту

Быстрый старт ​

Установка ​

bash
npm install daytona-wildberries-typescript-sdk

Базовая настройка ​

typescript
import { WildberriesSDK } from 'daytona-wildberries-typescript-sdk';

const sdk = new WildberriesSDK({
  apiKey: process.env.WB_API_KEY!
});

// Шаг 1: Получить новые заказы на самовывоз
const { orders } = await sdk.inStorePickup.getOrdersNew();
console.log(`Найдено ${orders?.length ?? 0} новых заказов на самовывоз`);

// Шаг 2: Подтвердить заказ для сборки
const orderId = orders?.[0]?.id;
if (orderId) {
  await sdk.inStorePickup.updateOrdersConfirm(orderId);
  console.log(`Заказ ${orderId} подтверждён для сборки`);

  // Шаг 3: Отметить как подготовленный к выдаче
  await sdk.inStorePickup.updateOrdersPrepare(orderId);
  console.log(`Заказ ${orderId} готов к выдаче`);

  // Шаг 4: Верифицировать личность покупателя
  const identity = await sdk.inStorePickup.createClientIdentity({
    orderCode: '170046918-0011',
    passcode: '4567'
  });
  console.log(`Личность подтверждена: ${identity.isIdentified}`);

  // Шаг 5: Завершить выдачу
  await sdk.inStorePickup.updateOrdersReceive(orderId);
  console.log(`Заказ ${orderId} выдан покупателю`);
}

Настройка окружения ​

Создайте файл .env:

bash
WB_API_KEY=your_api_key_here

Доступные методы ​

Задачи сборки (6 методов) ​

МетодОписаниеУровень лимита
getOrdersNew()Получить новые заказы на самовывозT1 (300 в мин)
updateOrdersConfirm(orderId)Подтвердить заказ для сборкиT2 (100 в мин)
updateOrdersPrepare(orderId)Отметить заказ как подготовленныйT2 (100 в мин)
updateOrdersReceive(orderId)Отметить как выданный покупателюT2 (100 в мин)
updateOrdersReject(orderId)Отклонить заказ (покупатель отказался)T2 (100 в мин)
updateOrdersCancel(orderId)Отменить заказ (по инициативе продавца)T2 (100 в мин)

Запросы заказов (2 метода) ​

МетодОписаниеУровень лимита
getClickCollectOrders(params)Список выполненных заказов с пагинациейT1 (300 в мин)
createOrdersStatus(data)Получить статусы заказов по IDT1 (300 в мин)

Взаимодействие с покупателем (2 метода) ​

МетодОписаниеУровень лимита
createOrdersClient(data)Получить информацию о покупателе для заказовT1 (300 в мин)
createClientIdentity(data)Верифицировать личность покупателя по кодуT3 (30 в мин)

Операции с метаданными (6 методов) ​

МетодОписаниеУровень лимита
getOrdersMeta(orderId)Получить метаданные заказаT1 (300 в мин)
deleteOrdersMeta(orderId, options)Удалить метаданные заказа по ключуT1 (300 в мин)
updateMetaSgtin(orderId, data)Установить коды маркировки SGTINT4 (1000 в мин)
updateMetaUin(orderId, data)Установить код UINT4 (1000 в мин)
updateMetaImei(orderId, data)Установить код IMEIT4 (1000 в мин)
updateMetaGtin(orderId, data)Установить код GTINT4 (1000 в мин)

Жизненный цикл заказа ​

Заказы следуют строгой модели состояний с определёнными переходами:

                    +----------+
                    |   new    |
                    +----+-----+
                         |
                    confirm()
                         |
                    +----v-----+
                    | confirm  |
                    +----+-----+
                         |
                    prepare()
                         |
                    +----v-----+
              +---->| prepare  |<----+
              |     +----+-----+     |
              |          |           |
         reject()   receive()   (верификация
              |          |       перед выдачей)
              v          v
        +---------+ +---------+
        | reject  | | receive |
        +---------+ +---------+

        Любое состояние ----cancel()----> [ cancel ]

Допустимые переходы состояний:

  • new --> confirm (начало сборки)
  • confirm --> prepare (готов к выдаче)
  • prepare --> receive (покупатель забрал) -- конечное состояние
  • prepare --> reject (покупатель отказался) -- конечное состояние
  • Любое состояние --> cancel (отмена продавцом) -- конечное состояние

Пошаговая обработка заказов ​

typescript
const { orders } = await sdk.inStorePickup.getOrdersNew();

for (const order of orders ?? []) {
  console.log(`Заказ ${order.id}: ${order.article}`);

  // Проверить необходимые метаданные
  if (order.requiredMeta?.length) {
    console.log(`  Требуемые метаданные: ${order.requiredMeta.join(', ')}`);
  }

  // Подтвердить заказ
  await sdk.inStorePickup.updateOrdersConfirm(order.id!);

  // Установить требуемые метаданные (необходимо в статусе confirm)
  if (order.requiredMeta?.includes('imei')) {
    await sdk.inStorePickup.updateMetaImei(order.id!, {
      imei: '123456789012345' // из вашей системы учёта
    });
  }

  // Отметить как подготовленный
  await sdk.inStorePickup.updateOrdersPrepare(order.id!);
}

Верификация личности покупателя ​

Перед выдачей подготовленного заказа необходимо проверить личность покупателя с помощью кода из приложения Wildberries.

Как это работает ​

  1. Покупатель получает код в приложении Wildberries для своего заказа
  2. Когда покупатель приходит к вам, он сообщает код заказа и пароль
  3. Вы вызываете createClientIdentity() для проверки совпадения кода
  4. Если проверка пройдена (isIdentified: true), можно выдать заказ

Процесс верификации ​

typescript
// Покупатель предоставляет код заказа и пароль
const result = await sdk.inStorePickup.createClientIdentity({
  orderCode: '170046918-0011',  // Код заказа покупателя
  passcode: '4567'              // Пароль из приложения WB
});

if (result.isIdentified) {
  console.log('Личность покупателя подтверждена');
  // Можно выдать заказ
  await sdk.inStorePickup.updateOrdersReceive(orderId);
} else {
  console.log('Верификация не пройдена — попросите покупателя проверить приложение');
}

Получение информации о покупателе ​

Также можно получить контактные данные покупателя для заказов в статусе confirm или prepare:

typescript
const clientInfo = await sdk.inStorePickup.createOrdersClient({
  orders: [12345, 67890]
});

for (const client of clientInfo.orders ?? []) {
  console.log(`Заказ ${client.orderID}:`);
  console.log(`  Телефон: ${client.phone}`);
  console.log(`  ФИО: ${client.fio}`);
}

Операции с метаданными ​

Товары, требующие отслеживания для соответствия требованиям, должны иметь коды маркировки перед выдачей. Поле requiredMeta в новых заказах указывает, какие коды необходимы.

Типы метаданных ​

ТипОписаниеФормат
sgtinКоды маркировки (Честный Знак)16-135 символов, макс. 24 кода
imeiИдентификатор мобильного устройстваРовно 15 цифр
uinУникальный идентификационный номерРовно 16 символов
gtinГлобальный номер товара (Беларусь)Ровно 13 символов

Установка метаданных ​

Метаданные можно устанавливать только когда заказ находится в статусе confirm:

typescript
// Установить IMEI для мобильного устройства
await sdk.inStorePickup.updateMetaImei(orderId, {
  imei: '123456789012345'
});

// Установить коды маркировки SGTIN
await sdk.inStorePickup.updateMetaSgtin(orderId, {
  sgtins: ['01046012345678900421abc123']
});

// Установить UIN
await sdk.inStorePickup.updateMetaUin(orderId, {
  uin: '1234567890123456'
});

// Установить GTIN
await sdk.inStorePickup.updateMetaGtin(orderId, {
  gtin: '1234567890123'
});

Проверка метаданных ​

typescript
const meta = await sdk.inStorePickup.getOrdersMeta(orderId);

if (meta.imei) {
  console.log(`IMEI: ${meta.imei}`);
}
if (meta.sgtins?.length) {
  console.log(`Кодов SGTIN: ${meta.sgtins.length}`);
}

Удаление метаданных ​

Если необходимо исправить метаданные, сначала удалите их, а затем установите новое значение. Параметр options с ключом key обязателен:

typescript
// Удалить метаданные IMEI (параметр options обязателен)
await sdk.inStorePickup.deleteOrdersMeta(orderId, { key: 'imei' });

// Установить исправленное значение
await sdk.inStorePickup.updateMetaImei(orderId, {
  imei: '543210987654321'
});

Лимиты запросов ​

API самовывоза использует 4-уровневую систему лимитов запросов. SDK применяет эти лимиты автоматически, но их понимание помогает проектировать эффективные интеграции.

Уровни лимитов ​

УровеньНазваниеЗапросов/минИнтервалПрименяется к
T1Чтение сборки300200 мсgetOrdersNew, getClickCollectOrders, createOrdersStatus, createOrdersClient, getOrdersMeta, deleteOrdersMeta
T2Переходы состояний100600 мсupdateOrdersConfirm, updateOrdersPrepare, updateOrdersReceive, updateOrdersReject, updateOrdersCancel
T3Проверка личности302 сcreateClientIdentity
T4Установка метаданных100060 мсupdateMetaSgtin, updateMetaUin, updateMetaImei, updateMetaGtin

Штрафной множитель за 409 (ВАЖНО) ​

Все эндпоинты модуля самовывоза применяют штрафной множитель 10x для ответов 409 Conflict. Это означает:

  • Один ответ 409 засчитывается как 10 запросов к лимиту
  • Для T2 (переходы состояний) при 100 запросов/мин, всего 10 конфликтов исчерпают всю квоту
  • Для T3 (проверка личности) при 30 запросов/мин, всего 3 неудачные проверки исчерпают квоту
typescript
// ВНИМАНИЕ: Если вызов вернёт 409, это засчитается как 10 запросов
try {
  await sdk.inStorePickup.updateOrdersConfirm(orderId);
} catch (error) {
  // Этот 409 использовал 10 из 100 запросов T2 в минуту
  console.error('Конфликт состояний — рассмотрите предварительную проверку статуса');
}

Советы по лимитам запросов ​

  • Проверяйте статус заказа перед сменой состояния, чтобы избежать ошибок 409
  • T3 (проверка личности) — самый строгий лимит: 30 запросов в минуту. Не повторяйте неудачные верификации в цикле
  • SDK обрабатывает лимиты автоматически. При достижении лимита запрос ставится в очередь и повторяется после необходимого интервала

Обработка ошибок ​

Специализированные классы ошибок ​

SDK предоставляет четыре специализированных класса ошибок для модуля самовывоза:

typescript
import {
  WildberriesSDK,
  PickupOrderNotFoundError,
  InvalidOrderStateError,
  CustomerVerificationError,
  MetadataValidationError,
  RateLimitError,
  WBAPIError
} from 'daytona-wildberries-typescript-sdk';

PickupOrderNotFoundError (404) ​

Выбрасывается, когда заказ с указанным ID не существует:

typescript
try {
  await sdk.inStorePickup.updateOrdersConfirm(999999);
} catch (error) {
  if (error instanceof PickupOrderNotFoundError) {
    console.error(`Заказ ${error.orderId} не найден`);
    // Проверьте ID заказа и попробуйте снова
  }
}

InvalidOrderStateError (409) ​

Выбрасывается при недопустимом переходе состояния заказа (например, подготовка неподтверждённого заказа):

typescript
try {
  await sdk.inStorePickup.updateOrdersPrepare(orderId);
} catch (error) {
  if (error instanceof InvalidOrderStateError) {
    console.error(`Невозможно выполнить ${error.attemptedAction} для заказа ${error.orderId}`);
    console.error(`Текущее состояние: ${error.currentState}`);

    // Проверить текущий статус и повторить с правильным действием
    const statuses = await sdk.inStorePickup.createOrdersStatus({
      orders: [error.orderId]
    });
    console.log('Фактический статус:', statuses.orders?.[0]?.supplierStatus);
  }
}

CustomerVerificationError (409) ​

Выбрасывается при неудачной проверке пароля:

typescript
try {
  const result = await sdk.inStorePickup.createClientIdentity({
    orderCode: '170046918-0011',
    passcode: '1234'
  });
} catch (error) {
  if (error instanceof CustomerVerificationError) {
    console.error(`Верификация не пройдена для заказа ${error.orderCode}`);
    // Попросите покупателя проверить пароль в приложении Wildberries
    // ВНИМАНИЕ: Каждая неудачная попытка засчитывается как 10 запросов (T3: 30 в мин)
  }
}

MetadataValidationError (409) ​

Выбрасывается при неудачной установке метаданных (неверный формат, неверное состояние заказа или ненужный тип метаданных):

typescript
try {
  await sdk.inStorePickup.updateMetaImei(orderId, {
    imei: '123456789012345'
  });
} catch (error) {
  if (error instanceof MetadataValidationError) {
    console.error(`Невозможно установить ${error.codeType} для заказа ${error.orderId}`);
    // Убедитесь: 1) Заказ в статусе "confirm"
    //            2) Тип кода есть в requiredMeta заказа
    //            3) Формат кода корректен
  }
}

Комплексная обработка ошибок ​

typescript
async function processPickupOrder(orderId: number) {
  try {
    await sdk.inStorePickup.updateOrdersConfirm(orderId);
    await sdk.inStorePickup.updateOrdersPrepare(orderId);
  } catch (error) {
    if (error instanceof PickupOrderNotFoundError) {
      console.error(`Заказ ${error.orderId} не найден`);
    } else if (error instanceof InvalidOrderStateError) {
      console.error(`Недопустимый переход состояния: ${error.message}`);
    } else if (error instanceof RateLimitError) {
      console.error(`Превышен лимит запросов. Повторить через: ${error.retryAfter} мс`);
    } else if (error instanceof WBAPIError) {
      console.error(`Ошибка API ${error.statusCode}: ${error.message}`);
    }
  }
}

Лучшие практики ​

1. Обрабатывайте заказы оперативно ​

Новые заказы на самовывоз следует подтверждать и подготавливать быстро. Покупатели ожидают своевременную обработку:

typescript
// Регулярно проверяйте новые заказы
const { orders } = await sdk.inStorePickup.getOrdersNew();

for (const order of orders ?? []) {
  await sdk.inStorePickup.updateOrdersConfirm(order.id!);
  // Установите метаданные, затем подготовьте
}

2. Обрабатывайте 409 осторожно (штраф 10x) ​

Каждый ответ 409 Conflict стоит 10 запросов к лимиту. Всегда проверяйте статус перед попыткой перехода:

typescript
// ПРАВИЛЬНО: Сначала проверить статус
const statuses = await sdk.inStorePickup.createOrdersStatus({
  orders: [orderId]
});
const status = statuses.orders?.[0]?.supplierStatus;

if (status === 'new') {
  await sdk.inStorePickup.updateOrdersConfirm(orderId);
} else if (status === 'confirm') {
  await sdk.inStorePickup.updateOrdersPrepare(orderId);
}

// НЕПРАВИЛЬНО: Слепая попытка перехода (риск 409 + штраф 10x)
// await sdk.inStorePickup.updateOrdersPrepare(orderId);

3. Верифицируйте личность перед выдачей ​

Всегда проверяйте личность покупателя перед выдачей заказа:

typescript
const result = await sdk.inStorePickup.createClientIdentity({
  orderCode: customerOrderCode,
  passcode: customerPasscode
});

if (!result.isIdentified) {
  // НЕ выдавайте заказ
  console.error('Личность не подтверждена — запросите правильный пароль');
  return;
}

// Можно безопасно выдать заказ
await sdk.inStorePickup.updateOrdersReceive(orderId);

4. Устанавливайте метаданные до подготовки ​

Обязательные метаданные необходимо установить, пока заказ находится в статусе confirm, до вызова updateOrdersPrepare():

typescript
const { orders } = await sdk.inStorePickup.getOrdersNew();

for (const order of orders ?? []) {
  // Сначала подтвердить
  await sdk.inStorePickup.updateOrdersConfirm(order.id!);

  // Установить обязательные метаданные в статусе confirm
  if (order.requiredMeta?.includes('imei')) {
    await sdk.inStorePickup.updateMetaImei(order.id!, {
      imei: getImeiFromInventory(order.article!)
    });
  }
  if (order.requiredMeta?.includes('sgtin')) {
    await sdk.inStorePickup.updateMetaSgtin(order.id!, {
      sgtins: getSgtinsFromInventory(order.article!)
    });
  }

  // Проверить, что метаданные установлены корректно
  const meta = await sdk.inStorePickup.getOrdersMeta(order.id!);
  console.log('Метаданные:', meta);

  // Затем подготовить к выдаче
  await sdk.inStorePickup.updateOrdersPrepare(order.id!);
}

5. Используйте пагинацию для исторических заказов ​

typescript
const now = Math.floor(Date.now() / 1000);
const sevenDaysAgo = now - 7 * 24 * 60 * 60;

let allOrders = [];
let next = 0;

do {
  const result = await sdk.inStorePickup.getClickCollectOrders({
    limit: 1000,
    next,
    dateFrom: sevenDaysAgo,
    dateTo: now
  });

  allOrders.push(...(result.orders ?? []));
  next = result.next ?? 0;
} while (next > 0);

console.log(`Всего выполненных заказов на самовывоз: ${allOrders.length}`);

Связанные ресурсы ​

Made with ❤️ for the Wildberries developer community