ПЭК в Битрикс: расчёт, создание заказов, трекинг
ПЭК (Первая Экспедиционная Компания) — одна из ключевых транспортных компаний для грузовой и сборной доставки в России. Основная специфика интеграции: ПЭК работает с грузами от 1 кг и выше, API заточен под параметры грузоместа (длина, ширина, высота, вес каждого места отдельно), а не под стандартный розничный формат Битрикс. Если у вас интернет-магазин с крупногабаритом — диваны, строительные материалы, промышленное оборудование — ПЭК часто становится основным перевозчиком.
Из нашей практики: мы реализовали интеграцию для сети магазинов стройматериалов — расчёт стал точнее на 25%, а доначисления прекратились. Опыт 5+ лет в Битрикс и более 30 проектов по доставке гарантируют надёжное решение.
API ПЭК: особенности
ПЭК предоставляет REST API с авторизацией через Bearer-токен. Токен получается через POST /v2/sign-in с логином и паролем из личного кабинета. Токен не имеет жёстко ограниченного TTL (в практике живёт 24–48 часов), но рекомендуется кэшировать и обновлять при получении 401.
Ключевые эндпоинты:
-
POST /v2/calculator— расчёт стоимости и сроков -
POST /v2/orders— создание заказа -
GET /v2/orders/{id}— статус заказа -
GET /v2/departments— список терминалов ПЭК
Базовый URL: https://api.pek.ru. Документация доступна в личном кабинете партнёра.
Как настроить расчёт стоимости?
class PekDeliveryHandler extends \Bitrix\Sale\Delivery\Services\Base
{
protected function calculateConcrete(
\Bitrix\Sale\Shipment $shipment
): \Bitrix\Sale\Delivery\CalculationResult {
$result = new \Bitrix\Sale\Delivery\CalculationResult();
$token = $this->getApiToken();
$payload = $this->buildCalcPayload($shipment);
$response = $this->apiPost('/v2/calculator', $payload, $token);
if (empty($response['price'])) {
$result->addError(new \Bitrix\Main\Error('Расчёт недоступен'));
return $result;
}
$result->setDeliveryPrice((float)$response['price']);
$result->setPeriodDescription($response['period_min'] . '–' . $response['period_max'] . ' дней');
return $result;
}
private function buildCalcPayload(\Bitrix\Sale\Shipment $shipment): array
{
$order = $shipment->getOrder();
return [
'senderCityId' => (int)$this->getOption('SENDER_CITY_ID'),
'receiverCityId' => $this->getReceiverCityId($shipment),
'cargo' => $this->buildCargoPlaces($shipment),
'service' => $this->getOption('SERVICE_TYPE', 'door_door'),
'declaredValue' => round($order->getPrice(), 2),
];
}
private function buildCargoPlaces(\Bitrix\Sale\Shipment $shipment): array
{
// ПЭК требует параметры каждого грузоместа отдельно
$weight = max($shipment->getWeight() / 1000, 1); // г → кг, минимум 1 кг
return [
[
'weight' => $weight,
'length' => (int)$this->getOption('DEFAULT_LENGTH', 50),
'width' => (int)$this->getOption('DEFAULT_WIDTH', 50),
'height' => (int)$this->getOption('DEFAULT_HEIGHT', 50),
],
];
}
}
Важно: ПЭК рассчитывает по объёмному весу. Если фактический вес меньше объёмного (Д×Ш×В / 5000 для авиа, / 4000 для авто), считается объёмный. Для крупногабарита это критично — передавайте реальные габариты товаров. Документация ПЭК: объёмный вес = (Д×Ш×В)/5000 для авиа и /4000 для авто.
Как получить cityId и не ошибиться?
ПЭК использует собственные числовые идентификаторы городов. Поиск города:
public function findCityId(string $cityName): ?int
{
$response = $this->apiGet('/v2/city?name=' . urlencode($cityName), $this->getApiToken());
return $response[0]['id'] ?? null;
}
Альтернатива: выгрузить справочник городов ПЭК и хранить маппинг название_города → pek_city_id в инфоблоке или кастомной таблице. При старте рекомендуется именно этот подход — API поиска города возвращает неоднозначные результаты для населённых пунктов с одинаковым названием.
Создание заказа и терминалы
private function createPekOrder(\Bitrix\Sale\Shipment $shipment): string
{
$order = $shipment->getOrder();
$props = $order->getPropertyCollection();
$payload = [
'senderCityId' => (int)$this->getOption('SENDER_CITY_ID'),
'receiverCityId' => $this->getReceiverCityId($shipment),
'cargo' => $this->buildCargoPlaces($shipment),
'service' => $this->getOption('SERVICE_TYPE', 'door_door'),
'declaredValue' => round($order->getPrice(), 2),
'sender' => [
'company' => $this->getOption('SENDER_COMPANY'),
'contact' => $this->getOption('SENDER_CONTACT'),
'phone' => $this->getOption('SENDER_PHONE'),
'address' => $this->getOption('SENDER_ADDRESS'),
],
'receiver' => [
'contact' => $props->getItemByOrderPropertyCode('FIO')?->getValue(),
'phone' => $props->getItemByOrderPropertyCode('PHONE')?->getValue(),
'address' => $props->getItemByOrderPropertyCode('ADDRESS')?->getValue(),
],
];
$response = $this->apiPost('/v2/orders', $payload, $this->getApiToken());
return (string)($response['id'] ?? '');
}
При типе door_terminal или terminal_door нужно передавать идентификатор терминала ПЭК. Список терминалов: GET /v2/departments. Фильтрация по cityId. На сайте реализуется выпадающий список терминалов с картой — виджет или кастомная реализация на Leaflet/Yandex Maps.
Почему важно передавать реальные габариты?
Кейс из нашей практики: магазин стройматериалов, средний вес заказа 50–200 кг, много листового материала. Проблема при внедрении: Битрикс хранит вес отправления как одно число, а ПЭК при заказе с несколькими позициями разных размеров требует список грузомест с габаритами каждого. Пришлось реализовать логику разбивки: у каждого товара в инфоблоке заведены свойства DELIVERY_LENGTH, DELIVERY_WIDTH, DELIVERY_HEIGHT. При формировании отправки каждая единица товара превращается в отдельное грузоместо.
Это увеличило точность расчёта: расхождение с реальной стоимостью сократилось с ±30% до ±5%, экономия на доначислениях составила до 15% от стоимости доставки. Такая детализация — ключевое преимущество перед стандартным подходом, где используется усреднённый вес.
Трекинг статусов
| Статус ПЭК | Значение |
|---|---|
accepted |
Принят к перевозке |
in_transit |
В пути |
arrived |
Прибыл на терминал назначения |
out_for_delivery |
Передан курьеру |
delivered |
Доставлен |
returned |
Возврат |
Вебхуков у ПЭК нет — только polling. Агент Битрикс раз в 4 часа запрашивает статусы активных отправлений через GET /v2/orders/{id} и обновляет статус заказа в магазине. Наш опыт показывает, что polling проще и дешевле вебхуков для невысоких нагрузок (до 500 отправлений в день).
Типичные ошибки при интеграции
| Ошибка | Последствие | Решение |
|---|---|---|
| Передача усреднённых габаритов | Доначисление до 30% | Указать свойства товаров |
| Неверный cityId | Расчет неверный | Выгрузить полный справочник |
| Отсутствие кэширования токена | Лимиты API | Кэшировать с инвалидацией по 401 |
| Игнорирование объёмного веса | Завышение стоимости | Учитывать коэффициент |
Что входит в работу под ключ
- Разработка обработчика доставки на PHP 8.1+ с полным циклом: расчёт → создание → трекинг.
- Настройка соответствия городов ПЭК (выгрузка и маппинг).
- Генерация грузомест на основе свойств товаров (если требуется).
- Интеграция карты терминалов на витрине.
- Агент трекинга и уведомления клиентов о статусах.
- Документация и консультация по доработкам.
Получите консультацию по интеграции — наши инженеры сертифицированы по Битрикс и имеют 5+ лет коммерческого опыта. Свяжитесь для оценки вашего проекта.
Сроки
| Состав | Срок |
|---|---|
| Расчёт стоимости + создание заказа | 4–5 дней |
| + Список терминалов + карта | +2–3 дня |
| + Разбивка на грузоместа по товарам | +2 дня |
| + Polling статусов + уведомления | +2 дня |
Оценим ваш проект за 1 день — свяжитесь, чтобы обсудить детали.







