Интеграция PBX Asterisk и Битрикс24 с помощью Asterisk Manager Interface (AMI)

Я хотел бы поделиться своим опытом интеграции бизнес-системы Битрикс24 и телефонной АТС Asterisk через AMI.

Эта интеграция позволяет автоматизировать обработку входящих и исходящих звонков, управлять клиентской базой и контролировать активности сотрудников.

AMI (Asterisk Manager Interface) - это интерфейс управления, который позволяет управлять Asterisk через программный интерфейс. В нашем случае, мы используем AMI для получения событий звонков, например, входящие и исходящие звонки, статусы звонков, и т.д.

Одно из главных преимуществ интеграции через AMI - это возможность получения информации о звонках в реальном времени. Например, когда звонит клиент, наша система получает информацию о его номере и имени, и мы можем автоматически идентифицировать его в Битрикс24 и связать звонок с этим контактом.

Еще одно преимущество интеграции через AMI - это возможность управления звонками непосредственно из Битрикс24. Мы можем перенаправлять звонки на нужного сотрудника, записывать разговоры и прослушивать их в Битрикс24, а также создавать звонки прямо из системы CRM.

Для интеграции через AMI будем использовать библиотеку panoramisk на Python, которая облегчает работу с AMI. Эта библиотека позволяет подключаться к AMI и получать события в реальном времени без вмешательства в диалплан.

В примере рассмотрим процесс подключения к AMI и получения событий с помощью panoramisk и дальнейшую оптправку данных о входящем звонке в Битрикс24:

1. Первое, что нужно сделать - это подключиться к AMI интерфейсу, используя учетные данные из файла manager.cof (Asterisk) 

import asyncio 
import requests, json 
from panoramisk import Manager 

# Подключение AMI 
manager = Manager(loop=asyncio.get_event_loop(), 
                  host='ip', port=5038, ssl=False, 
                  encoding='utf8', 
                  username='username', 
                  secret='secret')

 

2.  Для хранения данных о звонках будем использвоать ассоциативный массив

# Ассоциативный массив 
calls_data = {}
# Ассоциативный массив 
calls_data = {}

3. Следующий блок кода регистрирует обработчик события "Newchannel" с помощью manager.register_event(). Если входящий вызов был успешно установлен, обработчик получит событие и проверит, что вызов не является внутренним (Exten не равен 's') и что его контекст равен 'from-trunk'. Затем обработчик сохраняет информацию о вызове в словарь calls_data с использованием уникального идентификатора Linkedid в качестве ключа. Кроме того, он выводит информацию о вызове в консоль. 

 

# Подписка на события Новый вызов 
@manager.register_event('Newchannel') 
def NewchannelEvent(manager, message): 
    # Обработка событий входящего вызова 
    if message.Context == 'from-trunk' and message.Exten != 's': 
        call_id = message.Linkedid 
        calls_data[call_id] = {"phone_number": message.CallerIDNum, 'bitrix_user_id': None} 
        print('Входящий: ', call_id, calls_data[call_id])

 

Так выглядит само событие "Newchannel" данные из которого мы получаем:

 

Event: Newchannel 
Privilege: call,all 
Channel: SIP/trunk Tele2-700XXXXXXXX 
ChannelState: 0 
ChannelStateDesc: Down 
CallerIDNum: +77058645543 (Номер мой) 
CallerIDName: +77058645543 
ConnectedLineNum: <unknown> 
ConnectedLineName: <unknown> 
Language: en 
AccountCode: 
Context: from-trunk 
Exten: +700XXXXXXXX 
Priority: 1 
Uniqueid: 1677040396.2789 
Linkedid: 1677040396.2789

 

4. Следующий код отвечает за обработку события BridgeEnter, которое происходит, когда оператор ответил на звонок.

В функции BridgeEnter происходит проверка, является ли вызов входящим (если это исходящий звонок, то функция не будет выполнять никаких действий).

Затем функция обновляет информацию о звонке в словаре calls_data, добавляя в него информацию об внутреннем номере оператора, ищет в Битрикс24 id пользователя по этому номеру, регистрирует звонок в Битрикс24 и сохраняет id звонка в словаре calls_data.

Наконец, функция выводит сообщение в консоль о том, что оператор ответил на звонок и печатает информацию о звонке из словаря calls_data.

 

@manager.register_event('BridgeEnter') 
def BridgeEnter(manager, message): 
    # Для входящих вызовов 
    call_id = message.Linkedid 
    if message.ChannelStateDesc == 'Up' and message.Context == 'macro-dial-one': 
        calls_data[call_id]["internal_number"] = message.CallerIDNum 
        calls_data[call_id]["bitrix_user_id"] = find_user_id(message.CallerIDNum) 
        calls_data[call_id]["bitrix_call_id"] = register_call(calls_data[call_id]["bitrix_user_id"], calls_data[call_id]["phone_number"], 2) 
        print('Оператор ответил: ', call_id, calls_data[call_id])

 

Получаем продолжительность звонка:

manager.register_event('Cdr') 
def CdrEvent(manager, message): 
    call_id = message.UniqueID
    calls_data[call_id]["duration"] = message.Duration

 

6. Этот код отправляет POST-запрос на указанный адрес bitrix_url + finish, чтобы завершить звонок в Битрикс24. Для этого используются данные из словаря calls_data для конкретного call_id, в котором содержится информация о звонке, включая идентификатор вызова в Битрикс24 bitrix_call_id, идентификатор пользователя bitrix_user_id, продолжительность звонка duration и статус STATUS_CODE.

В качестве параметров для POST-запроса передаются ключ-значение в виде словаря finish_param. После отправки запроса на сервер Битрикс24, результат возвращается в виде ответа response_finish, который затем выводится на экран с помощью функции print().

 

# Завершение звонка звонка в битрикс 
finish_param = { 
    'CALL_ID': calls_data[call_id]["bitrix_call_id"], 
    'USER_ID': calls_data[call_id]["bitrix_user_id"], 
    'DURATION': calls_data[call_id]["duration"], 
    'STATUS_CODE': '200' 
    } 
response_finish = requests.post(bitrix_url + finish, finish_param) 
print(f"Response from finish: {response_finish.json()}")

 

В данной статье рассмотрен только один сценарий - "успешный" входящий звонок. Так же нет функции отправки записи разговора на сервер Битрикс24. Но это всё будет, если есть интерес :)

Comments 0

Login to leave a comment