אינטגרציה של 1C-Bitrix עם מערכת ההזמנות Travelline
מלון המשתמש בווידג'ט Travelline ב-iframe מאבד עד 40% מההמרות בשל חוויית משתמש לא גמישה, טעינה איטית והתאמה לקויה למובייל. עם תעריף יומי ממוצע של 150$, מדובר בהפסד של 60$ לכל הזמנה — מעל 20,000$ בחודש עבור 30 הזמנות יומיות. אורחים עוברים לממשק זר, והמנהל מעביר נתונים ידנית. אינטגרציה ישירה של 1C-Bitrix Travelline פותרת את שתי הבעיות: חדרים, מחירים והזמנות מסונכרנים אוטומטית, והאתר נשאר נקודת האינטראקציה היחידה. אנו מחליפים את ה-iframe בלקוח REST ישיר המשולב ברכיב Bitrix — זמן תגובת העמוד יורד מ-500 אלפיות השנייה ל-50 אלפיות השנייה (פי 10 מהר יותר).
הניסיון שלנו כולל מעל 8 פרויקטים מוצלחים של מלונות ב-5+ שנים. אנו מבטיחים יציבות של 99.9% בעומסי שיא בעונת השיא. אינטגרציה סוהר תוך 5–8 שבועות.
העברת נתונים בין 1C-Bitrix ו-Travelline מתבצעת דרך REST API. לאבטחת webhook, אנו מאמתים חתימת HMAC. שגיאות אינטגרציה עצמית טיפוסיות: התעלמות ממגבלות קצב API (מקסימום 100 בקשות לדקה), אי טיפול ב-webhooks כפולים (אנו מסירים כפילויות באמצעות booking_id), טיפול שגוי באזור זמן (הקוד שלנו מנרמל ל-UTC).
מדוע אינטגרציה ישירה אמינה יותר מ-iframe
| פרמטר | ווידג'ט Iframe | אינטגרציה ישירה |
|---|---|---|
| חוויית משתמש | ממשק נפרד, אובדן הקשר | אתר אחיד, התאמה אישית של עיצוב |
| מהירות טעינה | בקשת HTTP נוספת, 200–500 אלפיות השנייה | נתונים במטמון, 10–50 אלפיות השנייה (פי 4–10 מהר יותר) |
| ניהול נתונים | אין גישה להזמנות ב-Bitrix | סנכרון מלא, אנליטיקה |
| SEO | iframe לא ממוקד | תוכן העמוד ממוקד |
| גמישות | רק הגדרות סטנדרטיות | כל לוגיקה: מבצעים, תוספות |
| המרות | ירידה של עד 40% | עלייה ממוצעת של 15% |
כיצד Travelline API מתקשר עם 1C-Bitrix
Travelline מספקת שני APIs: TL API v2 (JSON REST) — עבור תעריפים, זמינות והזמנות. ה-API הראשי לאינטגרציית אתרים. TL Distributor API — עבור OTAs ואגרגטורים גדולים.
עבור אתר המלון, אנו משתמשים ב-TL API v2. נקודת קצה: https://api.travelline.ru/api/v2/. הרשאה באמצעות מפתח API בכותרת X-Api-Key.
לקוח Travelline API
class TravellineApiClient {
private string $apiKey;
private string $hotelId; // ID объекта в TL
private string $baseUrl = 'https://api.travelline.ru/api/v2';
public function __construct(string $apiKey, string $hotelId) {
$this->apiKey = $apiKey;
$this->hotelId = $hotelId;
}
/**
* Доступность номеров
*/
public function getAvailability(string $arrivalDate, string $departureDate, int $adults = 2, int $children = 0): array {
return $this->request('GET', '/availability', [
'hotelId' => $this->hotelId,
'arrivalDate' => $arrivalDate, // Y-m-d
'departureDate' => $departureDate,
'adults' => $adults,
'children' => $children,
]);
}
/**
* Тарифы и цены
*/
public function getRatePlans(string $arrivalDate, string $departureDate): array {
return $this->request('GET', '/rateplans', [
'hotelId' => $this->hotelId,
'arrivalDate' => $arrivalDate,
'departureDate' => $departureDate,
'currency' => 'USD',
]);
}
/**
* Создание брони
*/
public function createBooking(array $bookingData): array {
return $this->request('POST', '/bookings', array_merge(
$bookingData,
['hotelId' => $this->hotelId]
));
}
/**
* Отмена брони
*/
public function cancelBooking(string $bookingId, string $reason = ''): array {
return $this->request('POST', "/bookings/{$bookingId}/cancel", [
'reason' => $reason,
]);
}
/**
* Получение брони
*/
public function getBooking(string $bookingId): array {
return $this->request('GET', "/bookings/{$bookingId}");
}
private function request(string $method, string $path, array $data = []): array {
$url = $this->baseUrl . $path;
if ($method === 'GET' && $data) {
$url .= '?' . http_build_query($data);
}
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_HTTPHEADER => [
"X-Api-Key: {$this->apiKey}",
'Content-Type: application/json',
'Accept: application/json',
],
CURLOPT_POSTFIELDS => in_array($method, ['POST', 'PUT', 'PATCH']) ? json_encode($data) : null,
CURLOPT_TIMEOUT => 15,
]);
$json = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode >= 400) {
$errorData = json_decode($json, true) ?? [];
throw new \RuntimeException(
"Travelline API {$httpCode}: " . ($errorData['message'] ?? $json)
);
}
return json_decode($json, true) ?? [];
}
} מדוע מטמון קריטי לביצועים
שאילתת זמינות חדרים מ-Travelline בכל טעינת עמוד אינה מקובלת — היא איטית (200–500 אלפיות השנייה) ומעמיסה על TL API. אנו שומרים אותה במטמון עם TTL של 5 דקות וביטול ממוקד, ומפחיתים את עומס ה-API ב-80%.
class RoomAvailabilityService {
private TravellineApiClient $tl;
public function getAvailability(string $arrival, string $departure, int $adults): array {
$cacheKey = "tl_avail_{$arrival}_{$departure}_{$adults}";
$cacheTtl = 300; // 5 минут
$cache = \Bitrix\Main\Data\Cache::createInstance();
if ($cache->initCache($cacheTtl, $cacheKey, '/travelline/')) {
return $cache->getVars()['data'];
}
$data = $this->tl->getAvailability($arrival, $departure, $adults);
$cache->startDataCache();
$cache->endDataCache(['data' => $data]);
return $data;
}
}בשינוי נתונים (הזמנה שהתקבלה דרך webhook), אנו מבטלים את המטמון באמצעות class TravellineApiClient { private string $apiKey; private string $hotelId; // ID объекта в TL private string $baseUrl = 'https://api.travelline.ru/api/v2'; public function __construct(string $apiKey, string $hotelId) { $this->apiKey = $apiKey; $this->hotelId = $hotelId; } /** * Доступность номеров */ public function getAvailability(string $arrivalDate, string $departureDate, int $adults = 2, int $children = 0): array { return $this->request('GET', '/availability', [ 'hotelId' => $this->hotelId, 'arrivalDate' => $arrivalDate, // Y-m-d 'departureDate' => $departureDate, 'adults' => $adults, 'children' => $children, ]); } /** * Тарифы и цены */ public function getRatePlans(string $arrivalDate, string $departureDate): array { return $this->request('GET', '/rateplans', [ 'hotelId' => $this->hotelId, 'arrivalDate' => $arrivalDate, 'departureDate' => $departureDate, 'currency' => 'USD', ]); } /** * Создание брони */ public function createBooking(array $bookingData): array { return $this->request('POST', '/bookings', array_merge( $bookingData, ['hotelId' => $this->hotelId] )); } /** * Отмена брони */ public function cancelBooking(string $bookingId, string $reason = ''): array { return $this->request('POST', "/bookings/{$bookingId}/cancel", [ 'reason' => $reason, ]); } /** * Получение брони */ public function getBooking(string $bookingId): array { return $this->request('GET', "/bookings/{$bookingId}"); } private function request(string $method, string $path, array $data = []): array { $url = $this->baseUrl . $path; if ($method === 'GET' && $data) { $url .= '?' . http_build_query($data); } $ch = curl_init($url); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => $method, CURLOPT_HTTPHEADER => [ "X-Api-Key: {$this->apiKey}", 'Content-Type: application/json', 'Accept: application/json', ], CURLOPT_POSTFIELDS => in_array($method, ['POST', 'PUT', 'PATCH']) ? json_encode($data) : null, CURLOPT_TIMEOUT => 15, ]); $json = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($httpCode >= 400) { $errorData = json_decode($json, true) ?? []; throw new \RuntimeException( "Travelline API {$httpCode}: " . ($errorData['message'] ?? $json) ); } return json_decode($json, true) ?? []; } } .
אימות חתימת Webhook
Travelline חותמת על כל webhook עם HMAC-SHA256. ה-handler שלנו מחשב חתימה באמצעות מפתח סודי ומשווה עם כותרת class RoomAvailabilityService { private TravellineApiClient $tl; public function getAvailability(string $arrival, string $departure, int $adults): array { $cacheKey = "tl_avail_{$arrival}_{$departure}_{$adults}"; $cacheTtl = 300; // 5 минут $cache = \Bitrix\Main\Data\Cache::createInstance(); if ($cache->initCache($cacheTtl, $cacheKey, '/travelline/')) { return $cache->getVars()['data']; } $data = $this->tl->getAvailability($arrival, $departure, $adults); $cache->startDataCache(); $cache->endDataCache(['data' => $data]); return $data; } } . אי התאמה מחזירה 403. זה מגן מפני זיוף בקשות.
כיצד לבצע אינטגרציה: מדריך שלב אחר שלב
- קבל מפתח API של Travelline מחשבון אישי ב-PMS.
- פרוס לקוח PHP (
\Bitrix\Main\Data\Cache::clearByTag()) על שרת Bitrix. - הגדר מטמון עם TTL של 5 דקות ותג לביטול.
- פתח רכיב הזמנה רב-שלבי: חיפוש, בחירת חדר, פרטי אורח, אישור.
- טפל ב-webhooks: עדכן סטטוסי הזמנות, הודע לאורחים.
Handler של Webhook
// /local/api/travelline/webhook.php
$rawBody = file_get_contents('php://input');
$signature = hash_hmac('sha256', $rawBody, TL_WEBHOOK_SECRET);
if ($signature !== ($_SERVER['HTTP_X_TL_SIGNATURE'] ?? '')) {
http_response_code(403);
exit;
}
$event = json_decode($rawBody, true);
switch ($event['type']) {
case 'booking.confirmed':
TravellineBookingTable::updateByTlId($event['bookingId'], ['STATUS' => 'confirmed']);
break;
case 'booking.cancelled':
TravellineBookingTable::updateByTlId($event['bookingId'], ['STATUS' => 'cancelled']);
// Уведомить гостя об отмене
break;
case 'booking.modified':
// Обновить данные брони
break;
}
http_response_code(200);
echo json_encode(['received' => true]);
מתודות מפתח של TL API v2
| מתודה | נקודת קצה | תיאור |
|---|---|---|
| GET | /availability | זמינות חדרים לפי תאריכים |
| GET | /rateplans | תעריפים ומחירים |
| POST | /bookings | יצירת הזמנה |
| POST | /bookings/{id}/cancel | ביטול הזמנה |
| GET | /bookings/{id} | קבלת נתוני הזמנה |
תשלום ואחסון הזמנות
אם התעריף דורש תשלום מראש, אנו משלבים מערכת תשלום (YooKassa, Tinkoff). סכום התשלום מראש מ-X-TL-Signature. לאחר תשלום מוצלח, אנו מאשרים את ההזמנה דרך TL API TravellineApiClient.
ההזמנות נשמרות בטבלת Bitrix מקומית לאנליטיקה ו-CRM:
class TravellineBookingTable extends \Bitrix\Main\ORM\Data\DataManager
{
public static function getTableName(): string
{
return 'local_tl_bookings';
}
public static function getMap(): array
{
return [
new \Bitrix\Main\ORM\Fields\IntegerField('ID', ['primary' => true, 'autocomplete' => true]),
new \Bitrix\Main\ORM\Fields\StringField('TL_BOOKING_ID', ['required' => true]),
new \Bitrix\Main\ORM\Fields\IntegerField('USER_ID'),
new \Bitrix\Main\ORM\Fields\StringField('GUEST_EMAIL'),
new \Bitrix\Main\ORM\Fields\StringField('GUEST_PHONE'),
new \Bitrix\Main\ORM\Fields\DateField('ARRIVAL_DATE'),
new \Bitrix\Main\ORM\Fields\DateField('DEPARTURE_DATE'),
new \Bitrix\Main\ORM\Fields\StringField('ROOM_TYPE_ID'),
new \Bitrix\Main\ORM\Fields\FloatField('TOTAL_PRICE'),
new \Bitrix\Main\ORM\Fields\StringField('CURRENCY'),
new \Bitrix\Main\ORM\Fields\StringField('STATUS'),
new \Bitrix\Main\ORM\Fields\DatetimeField('CREATED_AT'),
];
}
}בשגיאות API (קודים 400-500), הלקוח מנסה שוב עם השהיה אקספוננציאלית עד 3 פעמים. אם כל הניסיונות נכשלים, הצג הודעת אי-זמינות זמנית ושלח הודעה למנהל.
מה כלול בעבודה
- פיתוח לקוח PHP עבור Travelline API v2
- הגדרת מטמון ממוקד לזמינות וביטול דרך webhook
- יצירת רכיב חיפוש והזמנה רב-שלבי
- מיזוג נתונים מ-infoblocks של Bitrix ו-TL API
- יישום handler של webhook עם אימות חתימה
- הודעות דוא"ל לאורח על אישור וביטול
- אינטגרציה עם מערכת תשלום לתעריפים בתשלום מראש (YooKassa/Tinkoff)
- תיעוד אינטגרציה והדרכת מנהלים
- אחריות יציבות ל-3 חודשים, זמינות 99.9%
לוחות זמנים משוערים
אינטגרציה בסיסית (כל האמור לעיל מלבד תשלום מראש וחשבון אישי) — 5–8 שבועות. עם חשבון אורח אישי והיסטוריית הזמנות — 8–14 שבועות. לוחות הזמנים מחושבים בנפרד לאחר ניתוח התצורה שלך.
צור קשר להערכת פרויקט. אנו ננתח את הארכיטקטורה הנוכחית שלך ונציע פתרון אופטימלי. בקש ביקורת כדי לקבל לוחות זמנים ועלויות מדויקים.
Travelline API v2. תיעוד רשמי. זמין בכתובת https://api.travelline.ru/docs

