Розробка інтеграції Bitrix24 через вебхуки
Найпоширеніша скарга на вебхук-інтеграції з Bitrix24: «все працювало, а потім перестало». Причина майже завжди одна — обробник став відповідати повільніше 5 секунд, Bitrix24 перестав його викликати, і ніхто цього не помітив, бо логів не було. Побудова надійної інтеграції на вебхуках вимагає розуміння того, як Bitrix24 доставляє події та що відбувається при збоях.
Архітектура вебхук-інтеграції
Вебхуки в Bitrix24 працюють у двох напрямках:
Вихідний вебхук — Bitrix24 викликає ваш URL при події. Підписка налаштовується в «Розробникам → Вихідний вебхук» або через event.bind у REST API. Bitrix24 робить POST-запит із Content-Type: application/x-www-form-urlencoded.
Вхідний вебхук — ваша система викликає Bitrix24 через фіксований URL із токеном. Зручно для простих односторонніх інтеграцій без OAuth.
Для двосторонньої інтеграції зазвичай використовують обидва типи: вхідний — для відправки даних у Bitrix24, вихідний — для отримання подій.
Підписка на події через API
Програмна підписка надійніша за ручне налаштування в інтерфейсі — не залежить від дій адміністратора:
// Підписка через REST API (від імені OAuth-програми)
$b24->call('event.bind', [
'event' => 'ONCRMDEALUPDATE',
'handler' => 'https://your-system.com/webhooks/bitrix24',
'auth_type' => 0, // 0 = поточний користувач
]);
// Отримати список активних підписок
$bindings = $b24->call('event.get');
// Відписатися
$b24->call('event.unbind', [
'event' => 'ONCRMDEALUPDATE',
'handler' => 'https://your-system.com/webhooks/bitrix24',
]);
Структура вхідного запиту
Тіло POST-запиту від Bitrix24:
event=ONCRMDEALUPDATE
&event_handler_id=42
&auth[access_token]=abc123
&auth[expires]=1700000000
&auth[member_id]=a1b2c3
&auth[domain]=company.bitrix24.ru
&auth[application_token]=xyz789
&data[FIELDS][ID]=456
&data[FIELDS][STAGE_ID]=EXECUTING
&data[FIELDS][OPPORTUNITY]=150000
Важливо: data[FIELDS] містить лише змінені поля, а не повний об'єкт. Для отримання актуального стану угоди потрібен окремий виклик crm.deal.get.
auth[application_token] — токен для верифікації джерела запиту. Для коробкового Bitrix24 перевіряємо його збіг із токеном програми.
Обов'язковий паттерн: негайна відповідь + черга
Ключова вимога: обробник повинен повернути HTTP 200 протягом 5 секунд. Усе, що довше — таймаут, подія вважається недоставленою.
// routes/api.php (Laravel)
Route::post('/webhooks/bitrix24', function (Request $request) {
// Валідація токена — швидко
if (!validateBitrixToken($request->input('auth.application_token'))) {
return response('Forbidden', 403);
}
// Кладемо в чергу — швидко
ProcessBitrixEvent::dispatch($request->all());
// Негайно відповідаємо
return response('OK', 200);
});
// app/Jobs/ProcessBitrixEvent.php
class ProcessBitrixEvent implements ShouldQueue
{
public $tries = 3;
public $backoff = [60, 300, 900]; // 1 хв, 5 хв, 15 хв
public function handle(): void
{
$event = $this->payload['event'];
$dealId = $this->payload['data']['FIELDS']['ID'];
// Тепер отримуємо повний об'єкт
$deal = $this->b24->call('crm.deal.get', ['id' => $dealId]);
// ... обробка
}
}
Ідемпотентність обробника
Одна подія може прийти двічі: Bitrix24 повторює виклик при мережевих проблемах, а масові операції генерують ONCRMDEALUPDATE на кожне поле. Обробник повинен бути ідемпотентним:
// Дедуплікація через event_handler_id + часова мітка
$eventKey = md5($event . $dealId . $request->input('ts'));
if ($redis->set("processed:{$eventKey}", 1, ['NX', 'EX' => 3600])) {
ProcessBitrixEvent::dispatch($payload);
// Якщо ключ вже є — дубль, ігноруємо
}
Ланцюжки подій і петлі синхронізації
Класична проблема: зовнішня система отримує подію ONCRMDEALUPDATE, оновлює дані у своїй БД, потім відправляє оновлення назад у Bitrix24 — це знову генерує ONCRMDEALUPDATE, і цикл повторюється нескінченно.
Рішення:
- Прапорець в угоді: встановлюємо кастомне поле
UF_CRM_SYNC_LOCK=Yперед записом із зовнішньої системи, перевіряємо його в обробнику — якщоY, пропускаємо та скидаємо прапорець - Хеш даних: порівнюємо хеш вхідних даних із останнім обробленим — якщо збігається, пропускаємо
- Часова мітка: якщо подія про наше ж оновлення (час ≤ 2 сек із моменту нашого запису) — ігноруємо
Моніторинг доставки
Bitrix24 не веде журнал доставки вебхуків для зовнішніх отримувачів. Потрібно вести його самостійно:
CREATE TABLE webhook_events (
id SERIAL PRIMARY KEY,
event_type VARCHAR(64),
entity_id INTEGER,
received_at TIMESTAMP DEFAULT NOW(),
processed_at TIMESTAMP,
status VARCHAR(16) DEFAULT 'pending', -- pending/done/error
error_message TEXT
);
Алерт: якщо за 10 хвилин немає жодної події ONCRMDEALUPDATE у робочий час — швидше за все, Bitrix24 перестав викликати обробник.
Обмеження за подіями
| Подія | Особливості |
|---|---|
ONCRMDEALUPDATE |
Викликається при кожній зміні будь-якого поля |
ONCRMDEALADD |
Не спрацьовує при імпорті через API з DISABLE_PORTAL_ACTIVITY=Y |
ONVOXIMPLANTCALLEND |
Дані запису дзвінка доступні із затримкою 5–30 сек |
ONTASKUPDATE |
Не включає зміни чеклістів |
ONIMBOTMESSAGEADD |
Лише для ботів, зареєстрованих через imbot.register |
Коробковий Bitrix24: розширення подій
На коробці доступні події PHP-рівня, яких немає в REST API:
// Подія до збереження угоди — можна змінити дані
\Bitrix\Main\EventManager::getInstance()->addEventHandler(
'crm', 'OnBeforeCrmDealAdd',
[MyHandler::class, 'onBeforeDealAdd']
);
// Власна подія з модуля
$event = new \Bitrix\Main\Event('my_module', 'OnSomethingHappened', ['data' => $data]);
$event->send();
Етапи розробки
| Етап | Зміст | Термін |
|---|---|---|
| Проєктування | Список подій, схема даних, архітектура обробника | 2–3 дні |
| Endpoint і черга | HTTP-обробник, Job, дедуплікація | 3–5 днів |
| Бізнес-логіка | Обробка кожного типу події, виклик зовнішніх систем | 1–3 тижні |
| Захист від петель | Прапорці синхронізації, idempotency | 2–3 дні |
| Моніторинг | Журнал подій, алерти, дашборд | 2–3 дні |
| Тестування | Емуляція подій, навантажувальні тести | 3–5 днів |
Загалом: 3–7 тижнів залежно від кількості подій і складності бізнес-логіки.







