Skip to content

נקודות איסוף ​

מחזיר את נקודות האיסוף של חברת השילוח הזמינות לרישיון. הנקודות שייכות לחברת השילוח של רישיון הקורא: רישיון 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_keystringכןה-key של הרישיון. חברת השילוח, פרטי ההזדהות שלה וכתובת האיסוף נקבעים כולם ממנו.
domainstringכןהדומיין של החנות הקוראת. נדרש על ידי ה-middleware.
tokenstringלאה-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 אינה מופיעה.

בקשה לדוגמה ​

bash
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"
}'
js
// 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
<?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:

json
{
  "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_codestringהמזהה של הנקודה אצל חברת השילוח. זה הערך שמזהה את הנקודה הנבחרת כשנוצר משלוח — נתיב היצירה קורא אותו כ-pickup.n_code.
namestringשם התצוגה של הנקודה.
citystringעיר.
streetstringרחוב. כמה חברות שילוח מכניסות לכאן את כל שורת הכתובת.
housestringמספר בית / רחוב. ריק אצל כמה חברות שילוח, שאין להן שדה נפרד לכך.
street_codestringקוד הרחוב של חברת השילוח כאשר קיים כזה; כמה חברות שילוח משתמשות בו מחדש עבור מספר הבית.
remarksstringטקסט חופשי מחברת השילוח — שעות פתיחה, כתובת באנגלית, או הערה, תלוי בחברת השילוח.
latitudestringקו רוחב כפי שחברת השילוח דיווחה עליו.
longitudestringקו אורך כפי שחברת השילוח דיווחה עליו.

כמה חברות שילוח מוסיפות מפתחות נוספים מעל התשעה האלה. הם אינם חלק מחוזה משותף — אל תסתמכו על נוכחותם:

שדהסוגחברות שילוחתיאור
is_outdoorbool | stringZigZag, Cargo, Done, Baldarהאם הנקודה היא לוקר חיצוני. הסוג באמת משתנה בין חברות השילוח: ברישיון Cargo חי הוא חזר כמחרוזת ריקה בכל 276 הנקודות, ולא כ-boolean.
is_activeboolDoneהאם הנקודה מופעלת עבור הרישיון הזה.
storageSackId, routeName, routeAreaCodestringDone, 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מתי
403Invalid License Key / License key has been deactivatedבדיקת הרישיון נכשלה ב-middleware.
422—license_key או domain חסר. מבנה הולידציה של Laravel ({"message": …, "errors": {…}}), ולא מעטפת v1.
500Error Retrieving Locationsהאינטגרציה של חברת השילוח לא החזירה דבר — הקריאה לחברת השילוח נכשלה, פרטי ההזדהות שגויים, או שלחברת השילוח אין רשת נקודות איסוף בכלל (אומת בשרת החי על LionWheel ועל Self Pickup). data הוא [] ומעטפת ארבעת המפתחות נשמרת, ולכן warning קיים וריק.