Интеграция службы доставки Европочты на сайт
Почему интеграция Европочты ломается без правильного клиента?
Разработчики часто сталкиваются с типичными ошибками: неверный расчёт веса (граммы 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+ успешных проектов для интернет-магазинов разного масштаба.
- Гарантия стабильной работы и сопровождение после внедрения.
- Предоставляем документацию и обучаем вашу команду.
Как заказать интеграцию
Получите консультацию по вашему проекту. Мы оценим объём работ и предложим решение под ключ. Закажите обратный звонок или напишите нам — обсудим детали.







