נקודות איסוף
מחזיר את נקודות האיסוף של חברת השילוח הזמינות לרישיון. הנקודות שייכות לחברת השילוח של רישיון הקורא: רישיון HFD מחזיר נקודות HFD, רישיון Cargo מחזיר נקודות Cargo, וכן הלאה.
המקבילה ב-v2:
GET /pickup-points.
ב-v2 יש כאן הרבה יותר
ל-v1 אין סינון, אין הגבלה ואין מיון — הוא מחזיר את רשימת הנקודות המלאה של חברת השילוח, בכל פעם, בסדר של חברת השילוח. GET /pickup-points מוסיף סינון city ללא תלות ברישיות, limit, ודירוג מהקרוב לרחוק עם distance_km לכל נקודה, בהינתן lat/lng מפורשים או address בטקסט חופשי שהוא מבצע עליו geocoding בשבילכם. הוא גם מחזיר רשימה שטוחה שאינה תלויה בחברת השילוח, במקום עוטף ה-spots.spot_detail המקונן של v1. אם אתם בוחרים נקודה שממנה הלקוח יאסוף, v2 היא נקודת הקצה שאתם רוצים.
POST /shipping/pickup_locations
החזרת נקודות האיסוף של חברת השילוח של הרישיון שנקבע.
פרמטרים
Body
ה-handler אינו מקבל פרמטרים משלו — חתימת המתודה שלו אפילו אינה מקבלת את הבקשה. השדות היחידים שהוא קורא הם פרטי ההזדהות שה-middleware של הרישיון דורש:
| שדה | סוג | חובה | תיאור |
|---|---|---|---|
license_key | string | כן | ה-key של הרישיון. חברת השילוח, פרטי ההזדהות שלה וכתובת האיסוף נקבעים כולם ממנו. |
domain | string | כן | הדומיין של החנות הקוראת. נדרש על ידי ה-middleware. |
token | string | לא | ה-handler אינו קורא אותו. ה-middleware של הרישיון קורא אותו, כשהוא קיים, כדי לקבוע את המשתמש הפועל עבור בדיקת הרישיון. |
אין מה לשלוח לצורך סינון, עימוד או מיון, וה-handler מתעלם מכל דבר אחר בגוף הבקשה — קריאה שהוסיפה city, limit, lat, lng, show_all, display_points ו-bogus_param החזירה תשובה זהה בייט-בייט. ה-middleware של הרישיון הוא היוצא מן הכלל: מלבד license_key ו-domain הוא קורא גם את token.
מה שהרשימה מכילה נקבע במקום זאת על ידי הגדרות הספק של הרישיון עצמו — ובראשן display_points: כשהוא מוגדר ל-indoor, האינטגרציות של Cargo ושל Done משמיטות מהרשימה נקודות חיצוניות. האינטגרציה של Done מכבדת בנוסף הפעלה ברמת הרישיון, ולכן נקודה שמפעיל השבית בממשק הניהול של ShipOS אינה מופיעה.
בקשה לדוגמה
curl --location 'https://app.shipos.co.il/api/shipping/pickup_locations' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data '{
"license_key": "{license_key}",
"domain": "your-store.example.com"
}'// Node.js 18+ / דפדפנים — בלי תלויות
const response = await fetch('https://app.shipos.co.il/api/shipping/pickup_locations', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
},
body: JSON.stringify({
license_key: process.env.SHIPOS_LICENSE_KEY,
domain: process.env.SHIPOS_DOMAIN,
}),
})
const body = await response.json()
if (!response.ok || !body.success) {
// 500 "Error Retrieving Locations" כאשר לחברת השילוח אין רשת נקודות איסוף
throw new Error(`ShipOS v1 pickup locations: ${body.message}`)
}
const points = body.data.locations.spots.spot_detail
for (const point of points) {
console.log(point.n_code, point.name, point.city)
}<?php
use Illuminate\Support\Facades\Http;
$body = Http::acceptJson()
->post('https://app.shipos.co.il/api/shipping/pickup_locations', [
'license_key' => config('services.shipos.license_key'),
'domain' => config('services.shipos.domain'),
])
->json();
if (! ($body['success'] ?? false)) {
throw new RuntimeException('ShipOS v1 pickup locations: '.$body['message']);
}
$points = $body['data']['locations']['spots']['spot_detail'];
foreach ($points as $point) {
logger()->info($point['n_code'].' '.$point['name'].' '.$point['city']);
}תשובה לדוגמה
תשובה 200:
{
"data": {
"locations": {
"spots": {
"spot_detail": [
{
"city": "תל אביב",
"name": "סופר פארם דיזנגוף",
"house": "50",
"n_code": "12345",
"street": "דיזנגוף",
"remarks": "",
"latitude": "32.0791",
"longitude": "34.7742",
"street_code": "50"
}
]
}
}
},
"message": "",
"success": true,
"warning": ""
}הרשימה אינה נמצאת במקום המצופה
הנקודות נמצאות ב-data.locations.spots.spot_detail — ולא ב-data.locations. כל אינטגרציה של חברת שילוח מנרמלת את המבנה שלה לתוך עוטף ה-spots.spot_detail הזה לפני ההחזרה, ולכן המבנה נראה כמו ה-XML של חברת השילוח שלפיה הוא עוצב במקור.
שדות נקודת איסוף
כל חברת שילוח ממפה את המבנה שלה על תשעת המפתחות האלה. ערך שחברת השילוח אינה מספקת חוזר כמחרוזת ריקה, ולא כ-null — וזה מדויק כפשוטו: בתשובת Cargo חיה לא היה אף ערך null בשום מקום בכל 276 הנקודות, כאשר house היה ריק בכל 276 ו-remarks ריק ב-3.
| שדה | סוג | תיאור |
|---|---|---|
n_code | string | המזהה של הנקודה אצל חברת השילוח. זה הערך שמזהה את הנקודה הנבחרת כשנוצר משלוח — נתיב היצירה קורא אותו כ-pickup.n_code. |
name | string | שם התצוגה של הנקודה. |
city | string | עיר. |
street | string | רחוב. כמה חברות שילוח מכניסות לכאן את כל שורת הכתובת. |
house | string | מספר בית / רחוב. ריק אצל כמה חברות שילוח, שאין להן שדה נפרד לכך. |
street_code | string | קוד הרחוב של חברת השילוח כאשר קיים כזה; כמה חברות שילוח משתמשות בו מחדש עבור מספר הבית. |
remarks | string | טקסט חופשי מחברת השילוח — שעות פתיחה, כתובת באנגלית, או הערה, תלוי בחברת השילוח. |
latitude | string | קו רוחב כפי שחברת השילוח דיווחה עליו. |
longitude | string | קו אורך כפי שחברת השילוח דיווחה עליו. |
כמה חברות שילוח מוסיפות מפתחות נוספים מעל התשעה האלה. הם אינם חלק מחוזה משותף — אל תסתמכו על נוכחותם:
| שדה | סוג | חברות שילוח | תיאור |
|---|---|---|---|
is_outdoor | bool | string | ZigZag, Cargo, Done, Baldar | האם הנקודה היא לוקר חיצוני. הסוג באמת משתנה בין חברות השילוח: ברישיון Cargo חי הוא חזר כמחרוזת ריקה בכל 276 הנקודות, ולא כ-boolean. |
is_active | bool | Done | האם הנקודה מופעלת עבור הרישיון הזה. |
storageSackId, routeName, routeAreaCode | string | Done, Baldar | מטא-נתוני ניתוב של חברת השילוח. |
הערות על ההתנהגות
- התשובות גדולות. רשימת חברת השילוח המלאה מוחזרת בלי תקרה. קריאת Cargo חיה החזירה 276 נקודות / 127,789 בייטים (בערך 125 KB). שלפו אותה פעם אחת ושמרו אותה במטמון בצד שלכם, במקום בכל תשלום בקופה. שימו לב גם שה-handler חותך את העותק שהוא כותב ל-
api_request_logsב-65,500 תווים, ולכן התשובה שנרשמת ביומן עבור רשימה בסדר גודל כזה תמיד חסרה. - המטמון של 60 דקות לכל רישיון אינו חל על כל חברות השילוח. במקומות שבהם המטמון בשימוש, המפתח שלו כולל את הגדרות הספק של הרישיון, ולכן שינוי של פרטי ההזדהות או של כתובת האיסוף נכנס לתוקף מיד במקום להמתין לתום ה-TTL. חמש חברות שילוח (Cargo, Done, HFD, Orian, Run Software) אינן נוגעות במטמון הזה כלל: הן שומרות את הרשימה שלהן בטבלה
pickup_locationsשל ShipOS ומגישות אותה משם, והפקודהpickup-locations:refreshהיא זו שמרעננת את השורות האלה. השורה השמורה אינה הרשימה המנורמלת — היא מחזיקה את המבנה הגולמי של חברת השילוח (אצל Cargo, המפתחות ברמה העליונהResult,errorCode,error_msgו-PointsDetails), ו-transformLocations()מנרמל מחדש את כל 276 הנקודות לתוךspots.spot_detailבכל בקשה. זו הסיבה שקריאה שהיא קריאת מסד נתונים טהורה עדיין עולה בערך 2.1 שניות ואינה מראה הבדל בין קר לחם: שלוש קריאות Cargo חיות רצופות נמדדו ב-2.19 שניות, 2.09 שניות ו-2.16 שניות. - חברת שילוח בלי רשת נקודות איסוף היא שגיאה, לא רשימה ריקה. אושר בשרת החי על שני רישיונות פעילים: גם LionWheel וגם Self Pickup מחזירים
HTTP 500עם{"data":[],"message":"Error Retrieving Locations","success":false,"warning":""}. שימו לב שהכישלון הזה שומר על מעטפת ארבעת המפתחות, כוללwarning— הוא עובר דרך helper ההצלחה הרגילapiResponse, ולא דרך מבנה שלושת המפתחותfailResponse— ולכןdataהוא[]ולא נעדר, ואיןdata.locationsבכלל.
שגיאות
| סטטוס | message | מתי |
|---|---|---|
| 403 | Invalid License Key / License key has been deactivated | בדיקת הרישיון נכשלה ב-middleware. |
| 422 | — | license_key או domain חסר. מבנה הולידציה של Laravel ({"message": …, "errors": {…}}), ולא מעטפת v1. |
| 500 | Error Retrieving Locations | האינטגרציה של חברת השילוח לא החזירה דבר — הקריאה לחברת השילוח נכשלה, פרטי ההזדהות שגויים, או שלחברת השילוח אין רשת נקודות איסוף בכלל (אומת בשרת החי על LionWheel ועל Self Pickup). data הוא [] ומעטפת ארבעת המפתחות נשמרת, ולכן warning קיים וריק. |