Передача контекста боту при открытии чата

Выберите инструмент для разработки с AI-агентом:

  • используйте Битрикс24 Вайбкод, чтобы создать приложение для Битрикс24 по описанию задачи без знания языков программирования. Агент напишет код и разместит приложение на сервере без ручной настройки хостинга
  • используйте MCP-сервер, чтобы разрабатывать интеграцию через REST API в своем проекте. Агент будет обращаться к официальной REST-документации

Механизм передачи стартового контекста боту при открытии чата. Пользователь переходит по специальной ссылке с внешнего сайта, по QR-коду или диплинку приложения, мессенджер открывает диалог с ботом, и бот немедленно получает произвольные JSON-данные — без дополнительных шагов.

По этим данным бот сразу понимает, зачем пришел пользователь: открывает нужную карточку, запускает сценарий адаптации, выдает купон или начинает процедуру авторизации.

Как работает механизм

  1. Пользователь переходит по ссылке ?IM_DIALOG={dialogId}&BOT_CONTEXT={json} или нативному bx-диплинку.
  2. Веб-интерфейс Битрикс24 открывает чат с ботом.
  3. После инициализации диалога клиент отправляет запрос im.v2.Chat.Bot.sendContext с {dialogId, context}.
  4. Платформа направляет контекст боту — через PHP-обработчик (модульные боты) и через событие ONIMBOTV2CONTEXTGET (REST-боты).
  5. Бот реагирует собственными вызовами методов: отправляет сообщение, показывает клавиатуру и так далее.

Параметр BOT_CONTEXT автоматически удаляется из адресной строки браузера через history.replaceState — после открытия чата контекстный токен в истории не остается.

Форматы ссылок

Контекст можно передать двумя способами: через браузер или через bx-диплинк для десктопного и мобильного приложений. Оба способа доставляют одинаковые данные, поэтому логика обработки в боте от выбранного способа не зависит.

Определить со стороны интеграции, установлено ли у пользователя приложение, нельзя. Рекомендуемые подходы в UI:

  • Две кнопки — «Открыть в приложении» (bx-ссылка) и «Открыть в браузере» (http-ссылка), пользователь выбирает сам.
  • Посадочная страница — автоматически пытается открыть bx-ссылку. Если приложение не перехватило переход за отведенное время — показывает запасную кнопку с http-ссылкой.

Веб: GET-параметры

Работает на любой странице Битрикс24:

https://{portal}/online/?IM_DIALOG={dialogId}&BOT_CONTEXT={urlEncodedJson}
        

Параметр

Описание

IM_DIALOG

dialogId — числовой ID пользователя-бота

BOT_CONTEXT

JSON произвольной структуры в URL-кодировке

Пример ссылки:

https://portal.bitrix24.ru/online/?IM_DIALOG=1459503&BOT_CONTEXT=%7B%22pairCode%22%3A%2213bd812901b295c50adbc%22%7D
        

Диплинк для десктопного и мобильного приложения Битрикс24. Открывает чат с ботом напрямую через обработчик протокола bx://:

bx://v2/{portal}/botContext/dialogId/{dialogId}/context/{urlEncodedJson}
        

Сегмент

Описание

v2

Версия протокола приложения, сейчас всегда v2

{portal}

Домен Битрикс24

botContext

Тип диплинка, фиксированное значение

{dialogId}

Числовой ID пользователя-бота

{urlEncodedJson}

encodeURIComponent(JSON.stringify(context))

Пример:

bx://v2/portal.bitrix24.ru/botContext/dialogId/1459503/context/%7B%22pairCode%22%3A%2213bd812901b295c50adbc%22%7D
        

JS API

Если чат открывается программно изнутри страницы Битрикс24, используйте JS API:

import { Messenger } from 'im.public';
        
        Messenger.openChatWithBotContext(dialogId, { pairCode: '13bd812901b295c50adbc' });
        

Параметр

Тип

Описание

dialogId

string

Идентификатор бота (числовой ID)

context

object

Произвольный JSON-объект

Метод создает внутренний сервис контекста, подписывается на onDialogInited и после инициализации диалога отправляет запрос im.v2.Chat.Bot.sendContext.

Событие ONIMBOTV2CONTEXTGET

Основная точка обработки контекста для бота. Событие доставляется в том же режиме, который выбран при регистрации бота через imbot.v2.Bot.register — отдельной подписки не требуется.

  • Fetch-режим (eventMode: "fetch", по умолчанию): событие забирается через imbot.v2.Event.get.
  • Webhook-режим (eventMode: "webhook"): событие приходит запросом на webhookUrl.

Полное описание всех полей, режимов доставки и примеры данных — в справочнике событий.

Поля события

Поле

Тип

Описание

bot

object

Бот-получатель. Формат зависит от режима: в fetch — полный объект бота, в webhook — {id, code, auth}

dialogId

string

Идентификатор диалога, например "chat5"

context

object

Произвольный JSON, переданный при открытии чата

chat

object

Объект чата

user

object

Пользователь, инициировавший открытие

language

string

Язык бота

user.id в событии приходит как number (не string) и в fetch-, и в webhook-режиме. Используйте user.id напрямую для сопоставления с хранимыми данными.

Ответ обработчика не влияет на сценарий: бот реагирует собственными вызовами методов, например imbot.v2.Chat.Message.send.

Пример: webhook-обработчик контекста

// webhook_handler.php
        $data = json_decode(file_get_contents('php://input'), true);
        
        if (($data['event'] ?? '') === 'ONIMBOTV2CONTEXTGET') {
            $eventData = $data['data'] ?? [];
            $context   = $eventData['context'] ?? [];
            $dialogId  = $eventData['chat']['dialogId'] ?? '';
            $botId     = (int)($eventData['bot']['id'] ?? 0);
        
            if (($context['action'] ?? null) === 'openTask') {
                $taskId = (int)($context['taskId'] ?? 0);
                CRest::call('imbot.v2.Chat.Message.send', [
                    'botId'    => $botId,
                    'dialogId' => $dialogId,
                    'fields'   => ['message' => "Открываю задачу #{$taskId}"],
                ]);
            }
        
            http_response_code(200);
            echo json_encode(['status' => 'ok']);
        }
        

Сценарии использования

Запуск по диплинку

Самый частый случай: ссылка несет короткий стартовый контекст, бот при открытии сразу «знает, зачем пришел пользователь», и запускает нужный сценарий. Привязка личности и подтверждение не требуются.

Сценарий

Пример context

Что делает бот

Диплинк к контенту

{"action":"openTask","taskId":456}

Открывает карточку, запускает сценарий

Реферал / приглашение

{"ref":"u12345"}

Привязывает нового пользователя к пригласившему

Адаптация

{"onboard":"teamX"}

Предзаполняет команду, роль или организацию

Активация / погашение

{"claim":"GIFT-7H2K"}

Выдает купон / подарок / заказ

Офлайн → чат (QR)

{"table":42}

Контекст поддержки или заказа из офлайна

Два способа передать данные:

  • Встроенные данные — прямо в ссылке. Подходит для небольших и неконфиденциальных данных.
  • Токен-ссылка — в BOT_CONTEXT кладется короткий токен, а реальные данные восстанавливаются по нему на вашем сервере. Подходит для объемных или конфиденциальных данных.

Привязка и авторизация

Тот же диплинк, но параметр — это токен авторизации или привязки, а результат — привязка проверенной личности: создание сессии или выдача персонального ключа. Поверх базового сценария добавляются серверный жизненный цикл pairCode и обязательное подтверждение в боте.

Типичный сценарий:

  1. Внешний сервер генерирует pairCode и возвращает браузеру ссылку на бота.
  2. Пользователь переходит по ссылке — бот получает ONIMBOTV2CONTEXTGET с проверенным user.id.
  3. Бот не выполняет привязку сразу, а показывает карточку подтверждения с информацией об инициаторе.
  4. Пользователь нажимает «Подтвердить» — приходит отдельное событие ONIMBOTV2COMMANDADD.
  5. Только после нажатия кнопки сервер выполняет привязку (создает сессию, выдает ключ).

Безопасность

Событие ONIMBOTV2CONTEXTGET не должно сразу выполнять действия с побочными эффектами: создавать сессию, привязывать аккаунт, выдавать ключ. Событие только инициирует сценарий — завершает его явное подтверждение пользователя в боте.

Почему обязательно подтверждение. Без него CONTEXTGET — это незаметная автоматическая привязка. Атакующий встраивает на свою страницу изображение с URL вида https://адрес-жертвы/online/?...BOT_CONTEXT={pairCode_атакующего} — браузер жертвы молча вызывает CONTEXTGET, и личность жертвы привязывается к коду атакующего. Явная карточка подтверждения в боте с именем или IP/временем инициатора позволяет пользователю увидеть чужой запрос и отклонить его.

Рекомендации при реализации привязки:

  • Два независимых секрета. pairCode передается через ссылку, а результат (сессия или ключ) браузер получает по отдельному httpOnly-cookie. Перехваченный pairCode не раскрывает результат привязки.
  • Атомарная смена состояния. При получении CONTEXTGET одной операцией переводите запись в состояние awaiting_confirm и сохраняйте в ней user.id. При нажатии кнопки меняйте состояние awaiting_confirm → consumed тоже одной атомарной операцией и только если user.id нажавшего совпадает с сохраненным.
  • Экранирование строк. Пользовательские данные (имя, email) экранируйте перед вставкой в BB-разметку сообщения бота.
  • Инициировавший запрос отображайте в карточке подтверждения: имя/email или IP/браузер/время.

Жизненный цикл pairCode

Параметр

Рекомендация

Формат

64 шестнадцатеричных символа (256 бит), криптографически случайный

Время жизни (TTL)

~10–15 минут

Состояния

pending → awaiting_confirm → confirmed \| declined \| expired

Одноразовость

Меняйте состояние одной атомарной операцией: SELECT … FOR UPDATE или UPDATE … WHERE status=… RETURNING

Защита от перебора

Неизвестный, просроченный или чужой код → 200 без утечки данных; просроченные записи удаляйте по расписанию

Примеры

Ссылка с внешнего сайта

<a href="https://portal.bitrix24.ru/online/?IM_DIALOG=1234&BOT_CONTEXT=%7B%22action%22%3A%22openTask%22%2C%22taskId%22%3A456%7D">
            Задать вопрос боту о задаче
        </a>
        

Бот получит в context: {"action": "openTask", "taskId": 456}.

Вызов из JS-кода приложения

import { Messenger } from 'im.public';
        
        Messenger.openChatWithBotContext('1234', {
            action: 'openTask',
            taskId: 456,
            source: 'taskCard',
        });
        

Событие ONIMBOTV2CONTEXTGET (fetch-режим)

{
            "type": "ONIMBOTV2CONTEXTGET",
            "data": {
                "bot": { "id": 456, "code": "my_bot", "eventMode": "fetch" },
                "dialogId": "chat5",
                "context": { "action": "openTask", "taskId": 456 },
                "chat": { "id": 5, "dialogId": "chat5", "type": "chat" },
                "user": { "id": 274, "name": "Евгений Шеленков" },
                "language": "ru"
            }
        }
        

Событие привязки с pairCode

{
            "type": "ONIMBOTV2CONTEXTGET",
            "data": {
                "chat": { "dialogId": "274" },
                "user": { "id": 274, "name": "Евгений Шеленков" },
                "context": { "pairCode": "e5142e4ad735..." }
            }
        }
        

user.id здесь 274 — это number, не строка. Используйте его для привязки после подтверждения.

Продолжите изучение