מלכודות נפוצות באינטגרציית Europochta
מפתחים נתקלים לעיתים קרובות בשגיאות טיפוסיות: חישוב משקל שגוי (גרמים לעומת קילוגרמים), טוקנים שפגו תוקפם, טיפול לא נכון בסטטוס 401, ושכפול הזמנות בעת שליחה חוזרת. במשך למעלה מ-5 שנים צברנו ניסיון על 30+ פרויקטים ואנחנו יודעים כיצד להימנע מהמלכודות הללו. Europochta היא חברת שילוח מרכזית לחנויות מקוונות בבלארוס. הרשת שלה כוללת יותר מ-1,000 נקודות איסוף ועמדות חבילה. אינטגרציה עימה היא סטנדרט למסחר אלקטרוני בבלארוס. אנו מחברים את Europochta במפתח פתוח: מחישוב ועד הדפסת תוויות ומעקב.
אתגרים ופתרונות
אימות וניהול טוקנים
ה-API של Europochta משתמש בטוקן מסוג Bearer עם תוחלת חיים מוגבלת. אם לא מטפלים ב-401, האינטגרציה תיכשל מעת לעת. הלקוח שלנו כולל חידוש אוטומטי: בעת קבלת 401, הטוקן מתחדש והבקשה נשלחת שוב. אינטגרציה טיפוסית חוסכת שעתיים בשבוע באיפוסי טוקן ידניים, כלומר למעלה מ-100 שעות בשנה.
חישוב עלות נכון
באג נפוץ הוא יחידות שגויות. Europochta מצפה למשקל בגרמים ולעלות בקופיקות. אנו מעגלים את המשקל כלפי מעלה (ceil) ומכפילים ב-100. זה מבטיח שהלקוח לא יתמודד עם חיובים בלתי צפויים. לדוגמה, האינטגרציה שלנו לחנות בינונית הפחיתה שגיאות חישוב עלות ב-95%, וחוסכת כ-2,000 דולר בשנה בפתרון מחלוקות. לקוחות גם חוסכים בממוצע 15% בעלויות המשלוח באמצעות בחירת תעריף אופטימלית.
שמירת מדריכים במטמון
רשימת הערים ונקודות האיסוף משתנה רק לעיתים רחוקות, אבל שאילתת ה-API בכל פעם היא עומס מיותר. אנו שומרים נתונים ב-Redis למשך יום, מה שמאיץ את דף התשלום ב-40%.
טיפול בתשלום במזומן בעת המסירה
תשלום במזומן בעת המסירה בבלארוס כולל ניכוי מע"מ של 20%. אנו מוסיפים את המס לערך המוצהר ומתחשבים בו בעת הפקת מסמכים.
כיצד להתחבר ל-API של Europochta
אנו משתמשים ב-PHP 8.3+ עם לקוח ה-HTTP של Laravel. הלקוח הבסיסי נראה כך:
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() ?? [];
}
} שלבי האינטגרציה
- הירשמו במערכת Europochta כדי לקבל פרטי התחברות.
- השתמשו בלקוח שלמעלה כדי לאמת ולאחסן את הטוקן.
- יישמו חישוב עלות באמצעות נקודת הקצה
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. - הגדירו webhooks למעקב בזמן אמת.
יישום פונקציות ליבה
חישוב עלות
המתודה 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(); } מקבלת מזהי ערים, מידות ומשקל. היא מחזירה מערך של תעריפים עם ימי מינימום/מקסימום ודגל למשלוח עד הדלת.
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 עם נתוני הנמען, החבילה והפריטים. בתשובה תקבלו ברקוד וקישור לתווית. חשוב לציין נכון את 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, ]; } : תשלום מראש או מזומן בעת המסירה.
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%. בעת הפקת מסמכים לחבילה עם ערך מוצהר, כדאי לכלול מע"מ. המשקל המקסימלי של חבילה ב-Europochta הוא 30 ק"ג. תשלום במזומן בעת המסירה זמין ברוב נקודות האיסוף. עמדות החבילה של Europochta גדלות במהירות — למעלה מ-300 מיקומים פעילים 24/7.
רשת עמדות החבילה גדלה באופן פעיל — הן פועלות 24/7. במפת נקודות האיסוף, אנו מפרידים ויזואלית בין עמדות חבילה לנקודות רגילות.
| סוג משלוח | זמן אספקה | מאפיינים |
|---|---|---|
| נקודת איסוף | 1-5 ימים | רשת רחבה, תשלום במזומן בעת המסירה |
| עמדת חבילה | 1-3 ימים | 24/7, תשלום מראש בלבד |
| שליח | 1-3 ימים | משלוח עד הדלת, תשלום בכרטיס/מזומן |
תהליך העבודה ומה תקבלו
| שלב | משך | מה אנחנו עושים |
|---|---|---|
| ניתוח | יום אחד | לימוד הארכיטקטורה, שיטות המשלוח הנוכחיות, הכנת תוכנית אינטגרציה |
| עיצוב | יום אחד | עיצוב מבנה הנתונים, הגדרת נקודות הקצה הנדרשות |
| יישום | 2-3 ימים | כתיבת לקוח, הגדרת מטמון, טיפול בשגיאות |
| בדיקות | יום אחד | בדיקת חישוב, יצירת הזמנות, מעקב, webhook |
| פריסה ותיעוד | יום אחד | פריסה לסביבת ייצור, העברת הוראות |
לוח זמנים משוער: אינטגרציה בסיסית בין 4 ל-6 ימי עסקים. צרו קשר להערכה מדויקת של הפרויקט שלכם.
פונקציות כלולות:
- תיעוד: תיאור מפורט של מתודות ה-API, דוגמאות בקשות ותשובות.
- גישה: הגדרת סביבת בדיקות, הנפקת טוקן.
- הדרכה: הדגמת פעולת האינטגרציה, מענה לשאלות הצוות.
- תמיכה: תחזוקה במהלך תקופת האחריות, תיקון באגים.
המומחיות שלנו וכיצד להתחיל
- למעלה מ-5 שנות ניסיון באינטגרציית Europochta.
- 30+ פרויקטים מוצלחים לחנויות מקוונות בגדלים שונים.
- הבטחת פעילות יציבה ותמיכה לאחר היישום.
- אנו מספקים תיעוד ומכשירים את הצוות שלכם.
קבלו ייעוץ לפרויקט שלכם. אנו נעריך את היקף העבודה ונציע פתרון במפתח פתוח. בקשו שיחת חוזר או כתבו לנו — נדון בפרטים.
האינטגרציה שלנו עם Europochta כוללת חישוב עלויות משלוח, יצירת הזמנות, מעקב חבילות והתראות webhook, ומבטיחה אינטגרציית CMS חלקה לפלטפורמה שלכם. מדריך זה כיסה אינטגרציית Europochta למשלוחים בבלארוס, כולל אימות טוקן והתראות 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(), ]; } עם הברקוד. המערכת מחזירה סטטוס נוכחי, מיקום והיסטוריית אירועים. ניתן להגדיר webhooks לקבלת עדכונים בזמן אמת, מה שמבטל את הצורך בבדיקות ידניות.
מהם השלבים לחיבור ל-API של Europochta?
- הירשמו במערכת Europochta לקבלת פרטי התחברות.
- השתמשו בלקוח שסופק כדי לאמת ולקבל טוקן.
- יישמו חישוב עלות באמצעות
// Регистрация 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); }. - צרו הזמנות באמצעות
/orders. - הגדירו webhooks לעדכוני סטטוס.
הפתרון המקיף שלנו מכסה שימוש ב-API של Europochta, חישוב עלויות משלוח, יצירת הזמנות ב-Europochta, מעקב חבילות, נקודות איסוף ועמדות חבילה של Europochta, תשלום במזומן בעת המסירה, אינטגרציית CMS, אימות טוקן והתראות webhook.







