Разбираемся с FreePBX и интегрируем его с Битрикс24 и не только

Содержание

Битрикс24 — это огромный комбайн, который совмещает и CRM, и документооборот, и учет и еще много разных вещей, которые очень нравятся менеджерам и не очень нравятся IT персоналу. Портал используют очень много небольших и средних компаний, в том числе небольшие клиники, производственники и даже салоны красоты. Основной функцией, которую "любят" менеджеры является интеграция телефонии и CRM, когда любой звонок сразу фиксируется в CRM, создаются карточки клиента, при входящем отображается информация о клиенте и сразу видно кто он такой, что ему можно продать и сколько он должен. Но телефония от Битрикс24 и ее интеграция с CRM стоит денег, иногда немалых. В статье я расскажу опыт интеграции с открытыми инструментами и популярной IP АТС FreePBX, а также рассмотрю логику работы различных частей

Я работаю на аутсорсе в компании, которая занимается продажей и настройкой, интеграцией IP телефонии. Когда меня спросили, можем ли мы вон той вот и вот этой вот компании предложить что то для интеграции Битрикс24 с АТС, которые стоят у клиентов, а также с виртуальными АТС на различных VDS компании, я пошел в Гугл. И он мне конечно же выдал ссылку на статью в хабр, где есть и описание, и github, и вроде все работает. Но при попытке попользоваться этим решением вылезло, что Битрикс24 уже не тот, что ранее, и надо многое переделывать. Кроме того, FreePBX это вам не голый астериск, тут думать надо как совместить удобство использования и хардкорный диалплан в конфиг-файлах.

Изучаем логику работы

Итак для начала, как все это должно работать. При поступления звонка извне на АТС (событие SIP INVITE от провайдера) начинается обработка диалплана(плана набора, dialplan) — правил, что и в каком порядке делать со звонком. Из первого пакета можно получить много информации, которую потом можно использовать в правилах. Отличным инструментом для изучения внутренностей SIP является анализатор sngrep (ссылка) который просто ставится в популярных дистрибутивах через apt install/yum install и подобное, но можно и из исходников собрать. Посмотрим лог звонка в sngrep

В упрощенном виде диалплан занимается только первым пакетом, иногда также в процессе разговора совершается перевод звонков, нажатия кнопок (DTMF), разные интересности типа FollowMe, RingGroup, IVR и прочего.

Что внутри Invite пакета

Собственно большинство простых диалпланов работают с первыми двумя полями и вся логика крутится вокруг DID и CallerID. DID — куда звоним, CallerID — кто звонит.

Но ведь у нас фирма а не один телефон — и значит в АТС скорее всего есть группы вызова (одновременный/последовательный звонок нескольких аппаратов) на городских номерах (Ring Group), IVR (Здравствуйте, вы позвонили. Нажмите один для. ), Автоответчики (Phrases), Временные условия (Time Conditions), Переадресация на другие номера или на сотовый (FollowMe, Forward). Это значит, что однозначно определить кому на самом деле придет вызов и с кем будет разговор при поступлении вызова очень сложно. Вот пример начала прохождения типового вызова в АТС наших клиентов

После успешного входа звонка в АТС происходит путешествие его по диалплану в разных "контекстах". Контекст с точки зрения Asterisk — это нумерованный набор команд, каждая из которых содержит фильтр по набранному номеру (он называется exten, для наружного вызова на начальном этапе exten=DID). Командами в строке диалплана может быть все что угодно — внутренние функции (например позвонить внутреннему абоненту — Dial() , положить трубку — Hangup() ), условные операторы ( IF, ELSE, ExecIF и подобные), переходы к другим правилам этого контекста ( Goto, GotoIF ), переход другим контекстам в виде вызова функций (Gosub, Macro). Отдельно стоит директива include имя_контекста , которая добавляет команды другого контекста в конец текущего контекста. Команды, включенные через include всегда выполняются после команд текущего контекста.

Вся логика работы FreePBX построена на включении друг в друга разных контекстов через include и вызов через Gosub, Macro и обработчики Handler. Рассмотрим контекст входящих вызовов FreePBX

Вызов проходит по всем контекстам сверху вниз по очереди, в кажом контексте могут быть вызовы других контекстов как макросов (Macro), функций(Gosub) или просто переходы (Goto), поэтому реальное дерево того, что вызывается можно отследить только в логах.

Типовая схема настройки типичной офисной АТС показана ниже. При вызове во входящих маршрутах ищется DID, по нему проверяются временные условия, если все в порядке — запускается голосовое меню. Из него по кнопке 1 или таймауту выход на группу дозвона операторов. После окончания звонка вызывается макрос hangupcall, после которого ничего уже в диалплане выполнить не удастся, кроме специальных обработчиков (hangup handler).

Где в этом алгоритме звонка мы должны поставлять информацию о начале звонка в CRM, где начинать запись, где оканчивать запись и отсылать ее вместе с информацией о звонке на CRM?

Интеграция с внешними системами

Что такое интеграция АТС и CRM? Это настройки и программы, которые конвертируют данные и события между двумя этими платформами и пересылают друг другу. Самым распространенным способом взаимодействия независимых систем является API, а самым популярным способом доступа к API является HTTP REST. Но только не для asterisk.

Внутри Asterisk есть:

AGI — синхронный вызов внешних программ/компонентов, используется в основном в диалплане, есть библиотеки типа phpagi, PAGI

AMI — текстовый TCP сокет, работающий по принципу подписки на события и ввода текстовых команд, напоминает SMTP изнутри, умеет отслеживать события и управлять вызовами, ,есть библиотека PAMI — самая популярная для создания связи с Asterisk

Event: Newchannel Privilege: call,all Channel: PJSIP/VMS_pjsip-0000078b ChannelState: 4 ChannelStateDesc: Ring CallerIDNum: 111222 CallerIDName: 111222 ConnectedLineNum: ConnectedLineName: Language: en AccountCode: Context: from-pstn Exten: s Priority: 1 Uniqueid: 1599589046.5244 Linkedid: 1599589046.5244

ARI — смесь того, другого, все через REST, WebSocket, в формате JSON — но вот со свежими библиотеками и обертками не очень, на вскидку нашлись (phparia, phpari) которые становились в своем развитии года 3 назад.

Удобство или неудобство, возможность или невозможность работы с тем или иным API определяются задачами, которые необходимо решить. Задачи для интеграции с CRM следующие:

Отследить начало вызова, куда его перевели, вытащить CallerID, DID, времена начала и конца, может быть данные из директории (для поиска связи телефона и пользователя CRM)

Начать и окончить запись звонка, сохранить в нужном формате, сообщить по окончании записи где лежит файл

Инициировать звонок по внешнему событию (из программы), позвонить внутреннему номеру, внешнему и соединить их

Опционально: интегрировать с CRM, группами дозвона и FollowME для автоматического перевода звонков при отсутствии на месте(по информации CRM)

Все эти задачи можно решить через AMI или ARI, но ARI предоставляет гораздо меньше информации, нет многих событий, не отслеживаются многие переменные, которые в AMI все таки есть (например вызовы макросов, задание переменных внутри макросов, в том числе запись звонков). Поэтому, для правильного и точного отслеживания — выберем пока AMI (но не окончательно). Кроме того (ну а куда ж без этого, мы люди ленивые) — в исходной работе (статья в хабр) используют PAMI. *Потом надо попробовать переписать на ARI, но не факт что получится.

Придумываем интеграцию заново

Для того, чтоб наш FreePBX мог сообщать в AMI простыми способами о начале звонка, времени окончания, номерах, именах записанных файлов, рассчитывать длительность звонка проще всего воспользоваться тем же трюком, что и исходные авторы — ввести свои переменные и парсить вывод на их присутствие. PAMI предлагает это делать просто через функцию-фильтр.

Вот пример задания своей переменной для времени начала звонка (s — это специальный номер в диалплане, который выполняется ДО начала поиска по DID)


Источник: habr.com