Интеграция службы доставки Европочты на сайт
Почему интеграция Европочты ломается без правильного клиента?
Разработчики часто сталкиваются с типичными ошибками: неверный расчёт веса (граммы vs килограммы), просроченные токены, необработанные 401-статусы, дублирование заказов при повторных отправках. За 5 лет мы накопили опыт на 30+ проектах и знаем, как обойти эти грабли. Европочта — ключевой перевозчик для белорусских интернет-магазинов. Её сеть насчитывает более 1000 пунктов выдачи и постаматов. Интеграция с ней — стандарт для e-commerce в РБ. Мы подключаем Европочту под ключ: от расчёта до печати этикеток и трекинга.
Какие проблемы решаем
Аутентификация и управление токенами. API Европочты использует Bearer-токен с ограниченным сроком жизни. Если не обрабатывать 401, интеграция будет периодически падать. В нашем клиенте автоматический refresh: при получении 401 токен обновляется, запрос повторяется.
Корректный расчёт стоимости. Ошибка в единицах измерения — частый баг. Европочта ожидает вес в граммах, стоимость — в копейках. Мы округляем вес вверх (ceil) и умножаем на 100. Это гарантирует, что клиент не получит неожиданных доплат.
Кеширование справочников. Список городов и ПВЗ редко меняется, но запрос к API каждый раз — лишняя нагрузка. Мы кешируем данные в Redis на сутки, что ускоряет страницу оформления заказа.
Работа с наложенным платежом. Наложенный платёж в Беларуси предполагает удержание НДС 20%. Мы добавляем налог в объявленную стоимость и учитываем его при формировании документов.
Как подключиться к API Европочты
Мы используем PHP 8.3+ с Laravel HTTP-клиентом. Базовый клиент выглядит так:
class EvropochtaClient { private string $baseUrl = 'https://api.europost.by/api/v1'; private ?string $token = null; public function authenticate(): string { if ($this->token) { return $this->token; } $response = Http::post($this->baseUrl . '/auth/login', [ 'login' => config('services.europost.login'), 'password' => config('services.europost.password'), ]); if ($response->failed()) { throw new EuropochtaAuthException('Authentication failed: ' . $response->body()); } $this->token = $response->json('token'); return $this->token; } public function request(string $method, string $path, array $data = []): array { $token = $this->authenticate(); $response = Http::withToken($token) ->withHeaders(['Content-Type' => 'application/json']) ->{strtolower($method)}($this->baseUrl . $path, $data); if ($response->status() === 401) { // Токен протух — получаем новый $this->token = null; return $this->request($method, $path, $data); } if ($response->failed()) { throw new EuropochtaApiException( "Europost API error: " . $response->body(), $response->status() ); } return $response->json() ?? []; } } Расчёт стоимости и создание заказа
Расчёт стоимости. Метод /calc принимает ID городов, габариты и вес. Возвращает массив тарифов с указанием min/max дней и признаком доставки до двери.
public function calculateDelivery( string $fromCityId, string $toCityId, float $weightKg, int $width, int $height, int $depth ): array { $response = $this->request('POST', '/calc', [ 'from_city_id' => $fromCityId, 'to_city_id' => $toCityId, 'weight' => (int)ceil($weightKg * 1000), // граммы, округляем вверх 'width' => $width, 'height' => $height, 'depth' => $depth, ]); return collect($response['services'] ?? []) ->map(fn($s) => [ 'service_id' => $s['id'], 'service_name' => $s['name'], 'cost' => (float)$s['cost'], 'currency' => 'BYN', 'min_days' => (int)($s['min_days'] ?? 1), 'max_days' => (int)($s['max_days'] ?? 7), 'to_door' => (bool)($s['to_door'] ?? false), ]) ->toArray(); } Создание заказа. Отправляем POST на /orders с данными получателя, посылки и вложений. В ответ получаем штрих-код и ссылку на этикетку. Важно правильно указать payment_type: prepaid или cod (наложенный).
public function createOrder(Order $order): array { $payload = [ 'order_id' => (string)$order->id, 'service_id' => $order->europost_service_id, 'from_city_id' => config('services.europost.default_city_id'), 'to_city_id' => $order->shipping_city_id, 'pickup_point_id' => $order->pickup_point_id ?? null, // Данные получателя 'recipient' => [ 'name' => $order->recipient_name, 'phone' => preg_replace('/[^0-9+]/', '', $order->recipient_phone), 'email' => $order->recipient_email, ], // Данные для доставки до двери 'address' => $order->pickup_point_id ? null : [ 'street' => $order->shipping_street, 'house' => $order->shipping_house, 'flat' => $order->shipping_flat ?? '', 'comment' => $order->shipping_comment ?? '', ], // Параметры посылки 'parcel' => [ 'weight' => (int)ceil($order->total_weight_kg * 1000), 'width' => $order->package_width, 'height' => $order->package_height, 'depth' => $order->package_length, 'declared_cost' => (int)($order->total * 100), // копейки 'payment_type' => $order->is_prepaid ? 'prepaid' : 'cod', 'cod_amount' => $order->is_prepaid ? 0 : (int)($order->total * 100), ], // Описание вложений 'items' => $order->items->map(fn($item) => [ 'name' => $item->product->name, 'quantity' => $item->quantity, 'price' => (int)($item->price * 100), ])->toArray(), ]; $response = $this->request('POST', '/orders', $payload); if (empty($response['barcode'])) { throw new EuropochtaOrderException( 'Order creation failed: ' . json_encode($response) ); } return [ 'barcode' => $response['barcode'], 'europost_id' => $response['id'], 'label_url' => $response['label_url'] ?? null, ]; } Как обрабатывать ошибки и восстанавливаться после сбоев
Клиент автоматически перезапрашивает токен при 401. Если ошибка повторяется — проблема в учётных данных. Мы также логируем все запросы к API для быстрой диагностики. В качестве альтернативы, можно использовать готовый SDK для Laravel, который работает в 3 раза быстрее стандартной реализации.
Отслеживание посылок и webhook
Трекинг. Получаем статусы и события по штрих-коду. Метод возвращает текущий статус, местоположение и историю событий.
public function trackParcel(string $barcode): array { $response = $this->request('GET', '/tracking/' . $barcode); return [ 'status' => $response['current_status'] ?? '', 'location' => $response['current_location'] ?? '', 'events' => collect($response['events'] ?? [])->map(fn($e) => [ 'date' => $e['date'], 'time' => $e['time'], 'status' => $e['status'], 'place' => $e['place'], 'comment' => $e['comment'] ?? '', ])->toArray(), ]; } Webhook уведомления. Регистрируем URL для получения событий (изменение статуса, доставка, возврат). Обработчик проверяет HMAC-подпись и обновляет статус заказа.
// Регистрация webhook $this->request('POST', '/webhooks', [ 'url' => 'https://yoursite.by/api/europost/webhook', 'events' => ['order.status_changed', 'order.delivered', 'order.returned'], ]); // Обработчик public function handleWebhook(Request $request): Response { // Проверка подписи $signature = hash_hmac('sha256', $request->getContent(), config('services.europost.webhook_secret')); if ($signature !== $request->header('X-Europost-Signature')) { return response('Forbidden', 403); } $data = $request->json()->all(); $order = Order::where('europost_barcode', $data['barcode'])->first(); if ($order) { $order->update(['shipping_status' => $data['status']]); if ($data['status'] === 'delivered') { dispatch(new MarkOrderDelivered($order)); } } return response('ok', 200); } Особенности белорусского рынка
НДС в Беларуси — 20%. При формировании документов для посылки с объявленной ценностью стоит указывать стоимость с НДС. Максимальный вес посылки Европочты — 30 кг. Наложенный платёж доступен для большинства точек выдачи.
Сеть постаматов активно растёт — они работают 24/7. На карте ПВЗ мы визуально разделяем постаматы и обычные точки.
Сравнение типов доставки Европочты
| Тип | Сроки | Особенности |
|---|---|---|
| ПВЗ | 1-5 дней | Широкая сеть, наложенный платёж |
| Постамат | 1-3 дня | 24/7, только предоплата |
| Курьер | 1-3 дня | Доставка до двери, оплата картой/наличными |
Процесс работы и сроки
| Этап | Длительность | Что делаем |
|---|---|---|
| Аналитика | 1 день | Изучаем архитектуру, текущие методы доставки, готовим план интеграции |
| Проектирование | 1 день | Проектируем структуру данных, определяем необходимые эндпойнты |
| Реализация | 2-3 дня | Пишем клиент, настраиваем кеш, обработку ошибок |
| Тестирование | 1 день | Проверяем расчёт, создание заказов, трекинг, webhook |
| Деплой и документация | 1 день | Размещаем на продакшене, передаём инструкцию |
Ориентировочные сроки: базовая интеграция — от 4 до 6 рабочих дней. Свяжитесь с нами для точной оценки вашего проекта.
Что входит в работу
- Документация: подробное описание API-методов, примеры запросов и ответов.
- Доступы: настройка тестовой среды, выдача токенов.
- Обучение: демонстрация работы интеграции, ответы на вопросы команды.
- Поддержка: сопровождение в течение гарантийного периода, исправление ошибок.
Почему стоит выбрать нас
- Более 5 лет опыта интеграции Европочты.
- 30+ успешных проектов для интернет-магазинов разного масштаба.
- Гарантия стабильной работы и сопровождение после внедрения.
- Предоставляем документацию и обучаем вашу команду.
Как заказать интеграцию
Получите консультацию по вашему проекту. Мы оценим объём работ и предложим решение под ключ. Закажите обратный звонок или напишите нам — обсудим детали.







