Context menu (context_menu)
Версия: 14_04_2026
- Ознакомление с проектом `v2/context_menu`: приложение для Маркетплейс Битрикс24 — пункт контекстного меню сообщения «Создать сделку» (placement `IM_CONTEXT_MENU`), создание сделки из текста сообщения и уведомление в чат со ссылкой на CRM.
- Зафиксировано соглашение по changelog: имя файла — дата в формате `d_m_Y` (как в PHP: день и месяц с ведущими нулями, год из четырёх цифр, разделитель `_`).
- Предыдущая зафиксированная версия: `23_3_2026` (изменения по `install.php`, `context_menu.php`: регистрация placement, unbind/bind, «тихое» окно 1×1, CRM без жёсткого `CATEGORY_ID`, обработка ошибок и контекста `dialogId`/`messageId`).
Текущее состояние кода (на дату файла):
- `install.php` — серверный обработчик `ONAPPINSTALL` / `OnAppSettingsInstall` с `placement.unbind` → `placement.bind` для `IM_CONTEXT_MENU`, параметры `GROUP_NAME`, `LANG_ALL`, `OPTIONS`; клиентская ветка BX24 с тем же сценарием; логи `placement_unbind_result` / `placement_bind_result`.
- `context_menu.php` — для `POST`/`IM_CONTEXT_MENU`: серверная загрузка текста (`im.dialog.messages.get`), проверка CRM (`crm.deal.fields`), `crm.deal.add` без фиксированной воронки, `im.message.add`; для `GET` — страница-описание приложения; мини-скрипт закрытия iframe после POST.
- `index.php` — краткая пользовательская страница приложения «Сделка из чата: одним кликом» (для открытия из списка установленных приложений).
- `marketing.md` — описание продукта, маркетинговые тексты и архитектура для Маркета (в репозитории; при необходимости синхронизировать с актуальным названием в карточке Маркета).
Доработки от 14_04_2026 (проверка 5 требований):
- `context_menu.php` переведен на серверный сценарий обработки `POST` от `IM_CONTEXT_MENU`: создание сделки и отправка ответа в чат выполняются на PHP без ожидания фронтенда; в iframe остается только мини-скрипт автозакрытия `BX24.closeApplication()`.
- Для запуска из списка установленных приложений (без `PLACEMENT_OPTIONS`) добавлена полноценная пользовательская страница-описание, чтобы не было падений и белого экрана.
- Усилена универсальность обработки прав: явная проверка `crm.deal.fields`, создание сделки без фиксированного `CATEGORY_ID`, отдельное сообщение в чат при недостатке прав на CRM/воронку.
- Унифицировано название приложения в пользовательских экранах: `Сделка из чата: одним кликом`.
- `index.php` заменен на краткую страницу назначения приложения в пользовательском стиле (под открытие из раздела установленных приложений).
Полный отчёт о работе в рамках текущего чата (сессия)
Ниже зафиксирована вся последовательность действий и решений по проекту `v2/context_menu` в ходе диалога.
1. Организация changelog и версионирование по дате
- Проверена папка `v2/context_menu/changelogs/`: при отсутствии каталог создавался бы автоматически; в репозитории каталог уже был.
- Соглашение по именам файлов: формат `d_m_Y` (день и месяц с ведущими нулями, четырёхзначный год, разделитель `_`), например `14_04_2026`.
- Удалён дублирующий файл с нестандартным именем `14_4_2026` (пустой, месяц без ведущего нуля), чтобы не плодить две «версии» на один день.
- Самая «молодая» по дате запись в `changelogs` соответствует текущей итерации разработки; зафиксирована связь с предыдущим файлом `23_3_2026`.
2. Первичное ознакомление с проектом
- Проект: приложение для Маркетплейс Битрикс24 — действие в контекстном меню сообщения чата (`IM_CONTEXT_MENU`): создание сделки CRM из текста сообщения и уведомление в чат со ссылкой на сделку.
- Просмотрены ключевые файлы: `install.php` (регистрация placement, `placement.unbind` / `placement.bind`), `context_menu.php` (логика сделки и чата), `index.php`, `marketing.md`.
3. Открытие из списка установленных приложений: ошибка 405 и консоль
- Проблема: при переходе по ссылке на приложение из списка установленных открывался тот же обработчик, что и для меню сообщения, без `dialogId`/`messageId`, из-за чего возникали белый экран и ошибка в консоли.
- Решение (первая итерация): в `context_menu.php` добавлена ветка «обычного» открытия приложения — показ краткой пользовательской страницы-описания без выполнения сценария создания сделки; фоновый сценарий с минимальным UI оставлен только при наличии контекста `IM_CONTEXT_MENU`.
4. Расширенная доработка по пяти требованиям
Запрошено:
1. Доступность действия создания сделки из сообщения также в мобильном приложении Битрикс24 (под пунктом «Создать»), после установки.
2. На десктопе убрать заметное промежуточное окно: только фоновое создание сделки и сообщение в чате.
3. Корректное поведение при недостаточных правах (нет CRM, нет прав на воронку и т.п.), универсальность для облака и коробки.
4. Стабильная страница при открытии приложения из списка установленных (без 405 и с понятным текстом).
5. Единое пользовательское название приложения: «Сделка из чата: одним кликом».
Реализовано в коде:
- `context_menu.php`
- Основная бизнес-логика перенесена на серверный обработчик `POST` при `PLACEMENT=IM_CONTEXT_MENU`: чтение `DOMAIN`, `AUTH_ID`, `PROTOCOL`, разбор `PLACEMENT_OPTIONS` (`dialogId`, `messageId`), вызовы REST через `curl` к порталу (`im.dialog.messages.get`, `crm.deal.fields`, `crm.deal.add`, `im.message.add`).
- Создание сделки без фиксированного `CATEGORY_ID` — портал подбирает доступную пользователю воронку.
- Перед созданием сделки выполняется проверка доступа к CRM через `crm.deal.fields`; при ошибках — системное сообщение в чат с понятной формулировкой о правах, где уместно.
- После успеха — сообщение в чат со ссылкой на карточку сделки; превью текста обрезается с учётом UTF-8 (вспомогательные функции при отсутствии `mbstring` — fallback на однобайтовые функции).
- Ответ обработчика для placement: минимальная HTML-страница с `BX24.resizeWindow(1,1)` и `BX24.closeApplication()` — только закрытие контейнера виджета, без отдельного «интерфейса» сценария.
- Для GET (открытие без контекста меню) — статическая страница с названием «Сделка из чата: одним кликом» и краткой инструкцией для пользователя.
- `install.php`
- Обновлены заголовки и подписи установки под официальное название приложения; логика `placement.bind` / `IM_CONTEXT_MENU` и `OPTIONS` сохранена (в т.ч. `context: ALL` для всех типов чатов в рамках документации API).
- `index.php`
- Заменён прежний промо-блок «Консалт Инфо» на краткую страницу назначения того же приложения с тем же названием — для сценария, когда в настройках Маркета указан URL на `index.php` как страница приложения.
- Название
- В пользовательских заголовках и текстах зафиксировано: «Сделка из чата: одним кликом» (константа `APP_NAME` в `context_menu.php`, заголовки в `index.php` и блок установки в `install.php`).
5. Ограничения и примечания по мобильному клиенту
- Регистрация пункта выполняется через официальный placement `IM_CONTEXT_MENU`; в документации Bitrix24 для этого placement описаны параметры `OPTIONS` (`context`, `role`, `extranet`), отдельного флага «только мобильный» в `placement.bind` для него нет.
- Отображение пункта в мобильном приложении зависит от клиента Битрикс24; серверная реализация снижает зависимость от JS в iframe и одинаково обрабатывает вызов, если контекст `PLACEMENT_OPTIONS` передан.
6. Затронутые файлы (итог)
| Файл | Суть изменений |
|------|----------------|
| `v2/context_menu/context_menu.php` | Серверный POST для `IM_CONTEXT_MENU`, GET-страница приложения, название, права, UTF-8 helpers |
| `v2/context_menu/install.php` | Тексты и заголовки под название приложения |
| `v2/context_menu/index.php` | Страница описания приложения для списка установленных |
| `v2/context_menu/changelogs/14_04_2026` | Настоящий файл: история и полный отчёт по чату |
7. Ссылки на документацию (справочно)
- [IM_CONTEXT_MENU](https://apidocs.bitrix24.com/api-reference/widgets/im/context-menu.html)
- [placement.bind](https://apidocs.bitrix24.com/api-reference/widgets/placement-bind.html)
- [Контекстное меню сообщений (MENU в im.message)](https://apidocs.bitrix24.com/api-reference/chats/messages/menu.html) — для понимания отличий от виджетов placement
*Конец отчёта по сессии чата для версии `14_04_2026`.*
Версия: 23_3_2026
- Добавлена обновленная регистрация `IM_CONTEXT_MENU` в `install.php`: единые параметры `OPTIONS`, локализация и `GROUP_NAME=Создать`.
- Добавлена отвязка старого обработчика через `placement.unbind` при установке/переустановке, чтобы избежать дублей пункта меню.
- Обновлен обработчик `context_menu.php`: работа в «тихом» минимальном окне (прозрачный 1x1 интерфейс) и автозакрытие после выполнения.
- Создание сделки теперь выполняется без фиксированного `CATEGORY_ID`, чтобы повышать совместимость с разными правами на воронки.
- Добавлена унифицированная обработка REST-ошибок и уведомление в чат при недостатке прав на CRM/воронку.
- Добавлена более гибкая обработка `dialogId/messageId` из контекста для совместимости разных клиентов.
Полное описание работ по проекту в рамках текущего чата:
1) Организация changelog в проекте
- Проверена корневая папка проекта `context_menu` на наличие каталога `changelogs`.
- При отсутствии каталог был создан.
- Создан файл версии/даты `changelogs/23_3_2026` по формату `d_m_Y`.
- Для подробной фиксации также был создан файл `changelogs/23_3_2026.md` с расширенным отчётом.
2) Доработки регистрации действия «Создать сделку» в `install.php`
- Добавлена функция `mpBuildPlacementBindParams($handlerUrl)` для централизованной сборки параметров `placement.bind`.
- В регистрацию `IM_CONTEXT_MENU` добавлены:
- `GROUP_NAME = "Создать"` (группировка под пунктом «Создать»),
- `LANG_ALL` для `ru/en` с локализацией `TITLE` и `GROUP_NAME`,
- `OPTIONS` с параметрами:
- `context = "ALL"`
- `role = "USER"`
- `extranet = "N"`.
- Добавлен `placement.unbind` перед `placement.bind` (и в install event, и в JS-ветке), чтобы не накапливались дубли пункта после переустановок.
- Добавлены дополнительные логи:
- `placement_unbind_result`
- `placement_bind_result`.
3) Доработки фонового сценария создания сделки в `context_menu.php`
- Убрана видимая промежуточная UI-часть (мигающее окно):
- пустой заголовок страницы,
- прозрачный минимальный интерфейс `1x1`,
- `BX24.resizeWindow(1, 1)`.
- Добавлено гарантированное закрытие приложения:
- `closeApp()` + вызов в `finally`.
- Введён единый REST-wrapper `callRest()` для унифицированной обработки ошибок API.
4) Улучшение универсальности и обработки прав
- Добавлена ранняя проверка доступности CRM:
- `ensureCrmAccessible()` через `crm.deal.fields`.
- Из `crm.deal.add` убран фиксированный `CATEGORY_ID: 0`:
- теперь воронка не зашита жестко,
- сценарий лучше работает у пользователей с ограничениями по воронкам.
- Добавлена классификация ошибок прав:
- `ACCESS_DENIED`
- `INVALID_CREDENTIALS`
- `insufficient_scope`
- текстовые признаки недостатка прав/доступа.
- При неуспехе создания сделки добавлено системное уведомление в чат:
- `postErrorToChat()` сообщает пользователю причину.
5) Совместимость контекста запуска из разных клиентов
- Добавлен helper `getPlacementOption()` для чтения `dialogId/messageId` в разных регистрах ключей.
- Улучшен сценарий чтения текста исходного сообщения:
- попытка точного поиска по `messageId`,
- при неуспехе безопасный fallback, чтобы не срывать весь процесс.
6) Проверки после изменений
- Проверены линтер-диагностики по измененным файлам: ошибок не найдено.
- Попытка `php -l` не выполнена из-за отсутствия `php` в окружении терминала.
7) Файлы, затронутые в ходе работ
- `install.php`
- `context_menu.php`
- `changelogs/23_3_2026`
- `changelogs/23_3_2026.md`