Как создать коннектор открытых линий для чата на сайте
Выберите инструмент для разработки с AI-агентом:
- используйте Битрикс24 Вайбкод, чтобы создать приложение для Битрикс24 по описанию задачи без знания языков программирования. Агент напишет код и разместит приложение на сервере без ручной настройки хостинга
- используйте MCP-сервер, чтобы разрабатывать интеграцию через REST API в своем проекте. Агент будет обращаться к официальной REST-документации
Коннектор передает сообщения посетителей сайта в Открытую линию Битрикс24, а ответы операторов — обратно на сайт. Посетитель пишет в чат на сайте, оператор отвечает из Битрикс24.
Коннектор работает только в контексте приложения (OAuth). Входящий вебхук не подойдет: методам imconnector.* нужна авторизация приложения. SDK выполняют исходящие вызовы REST; входящие события (ONIMCONNECTORMESSAGEADD) и настройку коннектора (placement SETTING_CONNECTOR) принимает ваш веб-сервер. Инициализацию SDK по токену приложения смотрите в примере чат-бота.
Архитектура
Интеграция состоит из серверной части (приложение) и виджета чата на сайте:
| Файл | Назначение | Методы REST |
|---|---|---|
function.* |
Хелперы: идентификатор коннектора, хранение чатов и сообщений, номер линии | — |
install_connector.* |
Установка: регистрация коннектора и подписка на событие | imconnector.register, event.bind |
handler.* |
Настройка коннектора (placement) и приём сообщений из Битрикс24 | imconnector.activate, imconnector.connector.data.set, imconnector.send.status.delivery |
ajax.* |
Обмен данными между виджетом и Битрикс24 | imconnector.send.messages |
index.* |
Виджет чата на сайте (фронтенд) | — |
Идентификатор коннектора (getConnectorID), хранение истории чатов (saveMessage/getChat) и номера линии (setLine/getLine) — это платформозависимая логика хранения; в примерах ниже она вынесена в хелперы.
1. Установка: регистрация коннектора
При установке приложения регистрируем коннектор методом imconnector.register и подписываемся на событие OnImConnectorMessageAdd методом event.bind.
В imconnector.register передаем: ID — идентификатор коннектора, NAME — название, ICON/ICON_DISABLED — иконки (DATA-представление SVG), PLACEMENT_HANDLER — URL обработчика настроек.
const connectorId = 'example_site_chat'
const handlerUrl = 'https://your-domain.example/handler'
const icon = {
DATA_IMAGE: 'data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2070%2071%22%3E%3C/svg%3E',
COLOR: '#a6ffa3', SIZE: '100%', POSITION: 'center',
}
const reg = await $b24.actions.v2.call.make({
method: 'imconnector.register',
params: { ID: connectorId, NAME: 'ExampleSiteChat', ICON: icon, ICON_DISABLED: { ...icon, COLOR: '#ffb3a3' }, PLACEMENT_HANDLER: handlerUrl },
requestId: 'connector-register',
})
if (reg.getData().result) {
await $b24.actions.v2.call.make({
method: 'event.bind',
params: { event: 'OnImConnectorMessageAdd', handler: handlerUrl },
requestId: 'event-bind',
})
}
<?php
// $b24 построен на токене приложения (см. пример чат-бота)
$connectorId = 'example_site_chat';
$handlerUrl = 'https://your-domain.example/handler';
$icon = [
'DATA_IMAGE' => 'data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2070%2071%22%3E%3C/svg%3E',
'COLOR' => '#a6ffa3', 'SIZE' => '100%', 'POSITION' => 'center',
];
$reg = $b24->getIMOpenLinesScope()->connector()->register([
'ID' => $connectorId,
'NAME' => 'ExampleSiteChat',
'ICON' => $icon,
'ICON_DISABLED' => array_merge($icon, ['COLOR' => '#ffb3a3']),
'PLACEMENT_HANDLER' => $handlerUrl,
]);
if ($reg->isSuccess()) {
// event.bind не входит в типизированный коннектор-сервис — вызываем через ядро
$b24->core->call('event.bind', [
'event' => 'OnImConnectorMessageAdd',
'handler' => $handlerUrl,
]);
}
# client построен на токене приложения (см. пример чат-бота)
connector_id = "example_site_chat"
handler_url = "https://your-domain.example/handler"
icon = {
"DATA_IMAGE": "data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2070%2071%22%3E%3C/svg%3E",
"COLOR": "#a6ffa3", "SIZE": "100%", "POSITION": "center",
}
reg = client.imconnector.register(
bitrix_id=connector_id,
name="ExampleSiteChat",
icon=icon,
placement_handler=handler_url,
icon_disabled={**icon, "COLOR": "#ffb3a3"},
).response
if reg.result:
client.event.bind(event="OnImConnectorMessageAdd", handler=handler_url).response
2. Обработчик: активация и приём сообщений
Битрикс24 открывает обработчик в настройках Открытой линии (placement SETTING_CONNECTOR) и шлет туда событие ONIMCONNECTORMESSAGEADD при сообщении от оператора.
Активация коннектора для линии — методами imconnector.activate и imconnector.connector.data.set. LINE и ACTIVE_STATUS приходят в PLACEMENT_OPTIONS.
// В обработчике placement SETTING_CONNECTOR
const options = JSON.parse(req.body.PLACEMENT_OPTIONS)
const line = Number(options.LINE)
await $b24.actions.v2.call.make({
method: 'imconnector.activate',
params: { CONNECTOR: connectorId, LINE: line, ACTIVE: Number(options.ACTIVE_STATUS) },
requestId: 'connector-activate',
})
await $b24.actions.v2.call.make({
method: 'imconnector.connector.data.set',
params: { CONNECTOR: connectorId, LINE: line, DATA: { id: `${connectorId}line${line}`, url_im: widgetUri, name: widgetName } },
requestId: 'connector-data-set',
})
$options = json_decode($_REQUEST['PLACEMENT_OPTIONS'], true);
$line = (string)(int)$options['LINE'];
$b24->getIMOpenLinesScope()->connector()->activate($connectorId, $line, (int)$options['ACTIVE_STATUS']);
$b24->getIMOpenLinesScope()->connector()->setData($connectorId, $line, [
'id' => $connectorId . 'line' . $line,
'url_im' => $widgetUri,
'name' => $widgetName,
]);
import json
options = json.loads(request.form["PLACEMENT_OPTIONS"])
line = int(options["LINE"])
client.imconnector.activate(connector=connector_id, line=line, active=int(options["ACTIVE_STATUS"])).response
client.imconnector.connector.data.set(
connector=connector_id,
line=line,
data={"id": f"{connector_id}line{line}", "url_im": widget_uri, "name": widget_name},
).response
Приём сообщения от оператора. На событии ONIMCONNECTORMESSAGEADD сохраняем сообщение и подтверждаем доставку методом imconnector.send.status.delivery.
if (req.body.event === 'ONIMCONNECTORMESSAGEADD' && req.body.data.CONNECTOR === connectorId) {
for (const message of req.body.data.MESSAGES) {
const messageId = saveMessage(message.chat.id, message) // локальное хранение
await $b24.actions.v2.call.make({
method: 'imconnector.send.status.delivery',
params: {
CONNECTOR: connectorId,
LINE: getLine(),
MESSAGES: [{ im: message.im, message: { id: [messageId] }, chat: { id: message.chat.id } }],
},
requestId: 'status-delivery',
})
}
}
if (($_REQUEST['event'] ?? '') === 'ONIMCONNECTORMESSAGEADD'
&& ($_REQUEST['data']['CONNECTOR'] ?? '') === $connectorId) {
foreach ($_REQUEST['data']['MESSAGES'] as $message) {
$messageId = saveMessage($message['chat']['id'], $message); // локальное хранение
$b24->getIMOpenLinesScope()->connector()->sendStatusDelivery($connectorId, getLine(), [
['im' => $message['im'], 'message' => ['id' => [$messageId]], 'chat' => ['id' => $message['chat']['id']]],
]);
}
}
if request.form.get("event") == "ONIMCONNECTORMESSAGEADD":
for message in messages: # data[MESSAGES] из тела события
message_id = save_message(message["chat"]["id"], message) # локальное хранение
client.imconnector.send.status.delivery(
connector=connector_id,
line=get_line(),
messages=[{"im": message["im"], "message": {"id": [message_id]}, "chat": {"id": message["chat"]["id"]}}],
).response
3. AJAX: отправка сообщений посетителя в Битрикс24
Виджет на сайте шлет сообщения посетителя на ajax.*, откуда они уходят в Открытую линию методом imconnector.send.messages.
Структура сообщения MESSAGES[]: user (id, name), message (id, date, text), chat (id, url).
const arMessage = {
user: { id: chatId, name: visitorName },
message: { id: messageId, date: Math.floor(Date.now() / 1000), text: visitorText },
chat: { id: chatId, url: pageUrl },
}
await $b24.actions.v2.call.make({
method: 'imconnector.send.messages',
params: { CONNECTOR: connectorId, LINE: lineId, MESSAGES: [arMessage] },
requestId: 'send-messages',
})
$arMessage = [
'user' => ['id' => $chatID, 'name' => htmlspecialchars($_POST['name'])],
'message' => ['id' => $messageId, 'date' => time(), 'text' => htmlspecialchars($_POST['message'])],
'chat' => ['id' => $chatID, 'url' => htmlspecialchars($_SERVER['HTTP_REFERER'])],
];
$b24->getIMOpenLinesScope()->connector()->sendMessages($connectorId, $lineId, [$arMessage]);
import time
ar_message = {
"user": {"id": chat_id, "name": visitor_name},
"message": {"id": message_id, "date": int(time.time()), "text": visitor_text},
"chat": {"id": chat_id, "url": page_url},
}
client.imconnector.send.messages(connector=connector_id, line=line_id, messages=[ar_message]).response
4. Виджет чата на сайте
index.* отдает HTML-страницу с чатом: поле ввода, список сообщений и периодический опрос ajax.* для загрузки истории и ответов оператора. Это обычный фронтенд (HTML + JS + fetch к вашему ajax.*), без вызовов REST Битрикс24 напрямую — все обращения к Битрикс24 идут через серверную часть.
5. Запуск коннектора
- Разместите серверные файлы на публичном HTTPS-URL
- Создайте локальное приложение типа «Серверное» с правами
imopenlines,imconnector,im - Откройте
install_connector.*, чтобы зарегистрировать коннектор и подписаться на событие - В Контакт-центре откройте коннектор
ExampleSiteChat, выберите Открытую линию и активируйте — Битрикс24 вызоветhandler.*с placementSETTING_CONNECTOR - Разместите виджет (
index.*) на сайте и проверьте обмен сообщениями