פיתוח JSON API עבור 1C-Bitrix במפתח מלא — חוזה קפדני וקישור מטמון
אנו מפתחים JSON API עבור 1C-Bitrix — לא רק "נקודות קצה שמחזירות JSON", אלא חוזה קפדני לפי מפרט jsonapi.org. עם זה, לקוח שמכיר את התקן יכול להתחבר ללא תיעוד נוסף. בניסיון שלנו, זה מקצר את זמן התיאום ב-30% ומבטל אי-בהירות בהעברת נתונים. פרויקט טיפוסי כולל 10–15 נקודות קצה; עלות הפיתוח משתנה בהתאם למורכבות. במקביל, החיסכון בתחזוקה מגיע עד 40% בזכות חוזה אחיד.
יתרונות בהזמנת JSON API
פתרון מוכן מאיץ פיתוח frontend, אפליקציות מובייל ואינטגרציות CRM. אתם מפסיקים להיות תלויים בשינויים פנימיים ברכיבי Bitrix — ה-API חי חיים משלו. ועם מטמון מתויג (tagged cache על אירועי OnBeforeIBlockElementUpdate), עומס השרת יורד פי 3–5 בהשוואה לשיטות REST רגילות. JSON API מהיר וצפוי יותר מה-REST המובנה, במיוחד בעבודה עם קטלוגים של 10,000+ מוצרים.
ארכיטקטורת JSON API על Bitrix
יישום PHP טהור על גבי ליבת Bitrix. נקודת הכניסה היא בקר מחוץ למערכת הרכיבים:
/local/
api/
v1/
router.php — маршрутизация запросов
middleware/
AuthMiddleware.php
RateLimitMiddleware.php
resources/
ProductResource.php — трансформер данных
OrderResource.php
controllers/
ProductController.php
OrderController.php
ב-/local/ api/ v1/ router.php — маршрутизация запросов middleware/ AuthMiddleware.php RateLimitMiddleware.php resources/ ProductResource.php — трансформер данных OrderResource.php controllers/ ProductController.php OrderController.php , מוגדרים מסלולים. לדוגמה, עבור מוצרים והזמנות:
$router->get('/v1/products', [ProductController::class, 'index']);
$router->get('/v1/products/{id}', [ProductController::class, 'show']);
$router->post('/v1/orders', [OrderController::class, 'create']);
$router->patch('/v1/orders/{id}', [OrderController::class, 'update']);
המרת נתונים ל-JSON API
מחלקת המשאבים ממירה נתונים גולמיים מבלוקי מידע למבנה JSON, ומבודדת את הלקוחות משינויי שדות. דוגמה למוצרים:
class ProductResource {
public static function make(array $product, array $include = []): array {
$data = [
'id' => (int)$product['ID'],
'type' => 'products',
'attributes' => [
'name' => $product['NAME'],
'code' => $product['CODE'],
'description' => $product['DETAIL_TEXT'],
'active' => $product['ACTIVE'] === 'Y',
'created_at' => $product['DATE_CREATE'],
],
'relationships' => [],
];
if (in_array('prices', $include)) {
$data['relationships']['prices'] = PriceResource::collection(
PriceRepository::getForProduct((int)$product['ID'])
);
}
if (in_array('sku', $include)) {
$data['relationships']['sku'] = SkuResource::collection(
SkuRepository::getForProduct((int)$product['ID'])
);
}
return $data;
}
}הפרמטר router.php בבקשה שולט בהכללת נתונים קשורים — הלקוח מקבל בדיוק את מה שהוא צריך.
סינון, מיון ודפדוף
כל שלושת המנגנונים מיושמים באמצעות פרמטרי שאילתה. הם עובדים בבלוק קוד אחד ומחזירים מטא-נתונים על מספר הרשומות.
// Фильтрация
$filter = ['IBLOCK_ID' => CATALOG_IBLOCK_ID, 'ACTIVE' => 'Y'];
if (isset($_GET['filter']['section_id'])) {
$filter['SECTION_ID'] = (int)$_GET['filter']['section_id'];
}
// Сортировка
$sort = [];
foreach (explode(',', $_GET['sort'] ?? 'id') as $field) {
$direction = str_starts_with($field, '-') ? 'DESC' : 'ASC';
$sort[ltrim($field, '-')] = $direction;
}
// Пагинация (offset-based)
$limit = (int)($_GET['page']['size'] ?? 20);
$offset = ((int)($_GET['page']['number'] ?? 1) - 1) * $limit;התשובה כוללת מטא-נתונים:
{
"data": [...],
"meta": {
"total": 1543,
"page": 2,
"per_page": 20,
"last_page": 78
},
"links": {
"self": "/v1/products?page[number]=2",
"next": "/v1/products?page[number]=3",
"prev": "/v1/products?page[number]=1"
}
} יצירת הזמנה
POST $router->get('/v1/products', [ProductController::class, 'index']); $router->get('/v1/products/{id}', [ProductController::class, 'show']); $router->post('/v1/orders', [OrderController::class, 'create']); $router->patch('/v1/orders/{id}', [OrderController::class, 'update']); עם גוף הבקשה:
{
"data": {
"type": "orders",
"attributes": {
"delivery_address": "Москва, ул. Пушкина, 1",
"payment_method": "card"
},
"relationships": {
"items": {
"data": [
{
"type": "order-items",
"product_id": 123,
"quantity": 2
},
{
"type": "order-items",
"product_id": 456,
"quantity": 1
}
]
}
}
}
}הבקר מאמת נתונים וקורא ל-class ProductResource { public static function make(array $product, array $include = []): array { $data = [ 'id' => (int)$product['ID'], 'type' => 'products', 'attributes' => [ 'name' => $product['NAME'], 'code' => $product['CODE'], 'description' => $product['DETAIL_TEXT'], 'active' => $product['ACTIVE'] === 'Y', 'created_at' => $product['DATE_CREATE'], ], 'relationships' => [], ]; if (in_array('prices', $include)) { $data['relationships']['prices'] = PriceResource::collection( PriceRepository::getForProduct((int)$product['ID']) ); } if (in_array('sku', $include)) { $data['relationships']['sku'] = SkuResource::collection( SkuRepository::getForProduct((int)$product['ID']) ); } return $data; } } דרך ממשק D7 של מודול ?include=prices,sku. במקרה של שגיאה — תשובת 422 Unprocessable Entity עם רשימת שגיאות מובנית.
אימות זהות
-
סשן Bitrix. לבקשות מאפליקציות דפדפן שבהן המשתמש מחובר לאתר. אנו בודקים
// Фильтрация $filter = ['IBLOCK_ID' => CATALOG_IBLOCK_ID, 'ACTIVE' => 'Y']; if (isset($_GET['filter']['section_id'])) { $filter['SECTION_ID'] = (int)$_GET['filter']['section_id']; } // Сортировка $sort = []; foreach (explode(',', $_GET['sort'] ?? 'id') as $field) { $direction = str_starts_with($field, '-') ? 'DESC' : 'ASC'; $sort[ltrim($field, '-')] = $direction; } // Пагинация (offset-based) $limit = (int)($_GET['page']['size'] ?? 20); $offset = ((int)($_GET['page']['number'] ?? 1) - 1) * $limit;. -
אסימון Bearer (JWT). ללקוחות מובייל ולשרת-לשרת. Middleware מפענח JWT, מקבל
{ "data": [...], "meta": { "total": 1543, "page": 2, "per_page": 20, "last_page": 78 }, "links": { "self": "/v1/products?page[number]=2", "next": "/v1/products?page[number]=3", "prev": "/v1/products?page[number]=1" } }, ומאתחל סשן Bitrix:
$userId = $jwt->getClaim('sub'); \CUser::SetCurrent($userId); לאחר מכן, כל בדיקות ההרשאות הסטנדרטיות פועלות כראוי.
-
מפתח API. לשותפי B2B. מפתח בכותרת
/v1/orders, מקושר למשתמש או לקבוצה ב-Bitrix.
אימות קלט
לפני העברה למודולים — אימות קפדני. לכל נקודת קצה יש מחלקת Request עם חוקים:
class CreateOrderRequest {
public function validate(array $data): array {
$errors = [];
if (empty($data['delivery_address'])) {
$errors[] = ['pointer' => '/data/attributes/delivery_address', 'detail' => 'Обязательное поле'];
}
if (!in_array($data['payment_method'] ?? '', ['card', 'cash', 'invoice'])) {
$errors[] = ['pointer' => '/data/attributes/payment_method', 'detail' => 'Недопустимое значение'];
}
return $errors;
}
}שגיאות מוחזרות בפורמט JSON API Errors:
{
"errors": [
{
"status": "422",
"source": {
"pointer": "/data/attributes/delivery_address"
},
"title": "Ошибка валидации",
"detail": "Обязательное поле"
}
]
} קישור מטמון תשובות
עבור בקשת GET, אנו מגדירים מטמון HTTP דרך כותרות:
header('Cache-Control: public, max-age=600, s-maxage=3600');
header('ETag: "' . md5($cacheKey . $dataHash) . '"');
בצד Bitrix — מטמון מתויג לנתונים מצטברים. כאשר מוצר מתעדכן מחילופי 1C, התגית נפסלת, והבקשה הבאה מביאה נתונים טריים ממסד הנתונים.
מה כלול בעבודה
- עיצוב משאבים ונקודות קצה
- פיתוח Router, Middleware ואימות זהות
- יישום משאבי קטלוג (מוצרים, SKU, מחירים, מלאי)
- פעולות מסחר (עגלה, הזמנות, תשלום)
- נקודות קצה למשתמש (אימות, פרופיל, היסטוריית הזמנות)
- קישור מטמון (כותרות HTTP, Redis, מטמון מתויג)
- תיעוד OpenAPI + אוסף Postman
- בדיקות אינטגרציה ובדיקות עומס
- קוד ב-Git, הוראות פריסה
שלבי פיתוח
| שלב | תוכן | משך |
|---|---|---|
| עיצוב | משאבים, נקודות קצה, פורמט נתונים | שבוע |
| תשתית | Router, Middleware, אימות זהות | שבוע |
| משאבי קטלוג | מוצרים, SKU, מחירים, מלאי, קטגוריות | 1–2 שבועות |
| פעולות מסחר | עגלה, הזמנות, תשלום | 1–2 שבועות |
| נקודות קצה למשתמש | אימות, פרופיל, היסטוריית הזמנות | שבוע |
| קישור מטמון | כותרות HTTP, Redis, מטמון מתויג | שבוע |
| תיעוד | OpenAPI, אוסף Postman | 3–5 ימים |
| בדיקות | בדיקות אינטגרציה, בדיקות עומס | שבוע |
פרטי ארכיטקטורת מטמון
אנו משתמשים במטמון מתויג של Bitrix: כאשר רכיב בלוק מידע נשמר, האירוע `OnAfterIBlockElementAdd` מופעל, מה שמפסיל את המטמון לפי התגית `iblock_id_XXX`. זה מבטיח טריות נתונים ללא איפוס ידני.JSON API על Bitrix הוא חוזה קפדני וצפוי שחי באופן עצמאי מגרסאות רכיבים ותבניות. עם יישום נכון, צוות ה-frontend עובד עם ה-API כשירות עצמאי. כל הבקשות מתועדות, שגיאות מוחזרות בפורמט סטנדרטי, וגרסאות מגנות על לקוחות משינויי סכמה בלתי צפויים.
העריכו את הפרויקט שלכם. צרו קשר — ננתח את הדרישות ונציע ארכיטקטורה עם לוחות זמנים. קבלו ייעוץ ממהנדס עם ניסיון של למעלה מ-10 שנים ב-Bitrix.

