ПЭК в Битрикс: расчёт, создание заказов, трекинг
ПЭК (Первая Экспедиционная Компания) — одна из ключевых транспортных компаний для грузовой и сборной доставки в России. Основная специфика интеграции: ПЭК работает с грузами от 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 день — свяжитесь, чтобы обсудить детали.







