Переклад дзвінка за допомогою скрипта в Asterisk



Не так давно в одного з наших клієнтів виникла необхідність переводити дзвінки (вхідні та вихідні) по кліку з браузера. Логіка така: група операторів колл-центру приймає і здійснює дзвінки, і після розмови та з'ясування потреб їм потрібно з'єднати клієнта з одним із замовників або іншим фахівцем організації.

Здавалося б, оператор може перевести дзвінок класичним способом — «сліпим» переведенням на потрібний номер зі свого телефонного апарату або софтфона, але на ділі виявилося, що номери, на які потрібно здійснювати переклад, більше п'яти сотень і вони постійно додаються і змінюються, так що навіть централізоване автоматичне заповнення телефонної книги софтфона не дає можливості комфортної та швидкої роботи операторів: спочатку потрібно з'ясувати потребу клієнта, потім знайти в CRM номер, з яким його потрібно з'єднати, потім або вручну ввести номер, або знайти той же номер в телефонній книзі софтфона. Це призводить до нераціонального використання робочого часу операторів, високої ймовірності помилки при перекладі та зниження якості обслуговування клієнтів в цілому.

У деяких випадках подібну задачу вирішують наступним чином: за події в CRM в якусь базу даних заноситься номер оператора, і номер, з яким потрібно з'єднати його співрозмовника. Після цього оператор здійснює переведення дзвінка на службовий номер, в контексті перекладу здійснюється запит до бази даних і дзвінок нарешті перекладається на потрібний номер. Диалплан для вихідних в такому випадку виглядає приблизно так:

[operator-out]
 
розширеннями => _X.,1,Noop(Outgoing call from ${CALLERID(num)} до ${РОЗШИРЕННЯМИ})
 
розширеннями => _X.,n,Set(__TRANSFER_CONTEXT=transfer)
 
розширеннями => _X.,n,Dial(SIP/provider/${РОЗШИРЕННЯМИ},30,T)
 

 
[transfer]
 
розширеннями => 800,1,Set(num=ODBC_GETXFERNUM(${CALLERID(num)}
 
розширеннями => 800,n,Noop(Transfer to ${num})
 
розширеннями => 800,n,Goto(some-context,${num},1)


При вихідному дзвінку встановлюється змінна каналу TRANSFER_CONTEXT, яка перекриває контекст для перекладу дзвінків, і якщо дзвінок буде переведений на номер 800, використовуючи ODBC, ми отримуємо номер, на який потрібно насправді здійснити переклад. Однак, до самого переведення у відповідні поля таблиці повинно бути занесено однозначна відповідність внутрішнього номера оператора, та номери, на який саме зараз потрібно переводити дзвінок, що вимагає як мінімум одного зайвого дії з боку працівника (CRM йому потрібно вибрати номер, куди він хоче перевести дзвінок, а потім на телефоні або софтфоне виконати сам переклад), та ще й потрібно стежити за тим, щоб дані в таблиці були вірні: видаляти запис відразу після переведення, перевіряти та обробляти в диалплане порожні записи.

При всіх недоліках подібний метод можна застосовувати в тому випадку, якщо заздалегідь відомо, на який номер може знадобитися перевести дзвінок. Припустимо, колл-центр працює на вихідні дзвінки по клієнтам декількох замовників. Дзвінок формується автоматично з CRM(з використанням callfile або через originate в AMI), де оператор натискає кнопку «наступний дзвінок» і бачить скрипт розмови з клієнтом. Тоді можна просто додати наслідувану змінну з номером, і переводити дзвінок на нього:

У callfile додати наслідувану змінну __num:

Channel: Local/101@from-internal
 
Callerid: 74950000000
 
MaxRetries: 2
 
RetryTime: 600
 
WaitTime: 30
 
Context: from-internal
 
Extension: 74950000000
 
Priority: 1
 
<b>Set: __num=79991112233</b>


А контекст перекладу буде виглядати ще простіше:

розширеннями => 800,1,Noop(Transfer to ${num})
 
розширеннями => 800,n,Goto(some-context,${num},1)


Однак, у нашому випадку, як було сказано вище, такий метод застосовувати небажано.

На щастя, розробники asterisk подбали про нас, і через cli можна здійснити переклад певного каналу в заданий контекст:

<code>channel redirect <[[context,]розширеннями,]priority>
 

 
Аналогічний функціонал є і у AMI:
 

 
Action: Redirect
 
[ActionID:] value
 
Channel: value
 
[ExtraChannel:] value
 
Розширеннями: value
 
[ExtraExten:] value
 
Context: value
 
[ExtraContext:] value
 
Priority: value
 
[ExtraPriority:] value>
 


Залишився тільки одне питання: як визначити канал, який нам потрібно перекласти, адже ми знаємо лише номер оператора.

Потрібно розуміти, що звичайна розмова є з'єднання двох каналів. В консолі ми можемо виконати bridge show all і побачити всі ідентифікатори сполук.

> bridge show all 
 
Bridge-ID Chans Type Technology
 
14418b64-0635-46e7-bd48-f4b820461eaa 2 basic simple_bridge


А командою bridge show <bridge-id> подивитися інформацію про те, які саме канали беруть участь в з'єднанні.

Зрозуміло, що перебирати всі bridge-id в пошуках потрібного каналу незручно, й простіше отримати детальну інформацію про канали і знайти у видачі bridge-id, на підставі якого можна буде ідентифікувати потрібний нам канал:

> core show channels concise 
 
SIP/RT-00000453!incoming!!1!Up!AppDial!(Outgoing Line)!89063448810!!!3!134!14418b64-0635-46e7-bd48-f4b820461eaa!1479984681.1659
 
SIP/67-00000452!macro-dialout-trunk!s!23!Up!Dial!SIP/RT/89063448810,300,TtL(7200000)!67!!!3!134!14418b64-0635-46e7-bd48-f4b820461eaa!1479984681.1658


Ми бачимо, що на поточний момент у нас є 2 каналу з однаковим bridge-id(14418b64-0635-46e7-bd48-f4b820461eaa), і ми знаємо внутрішній номер оператора. Залишається тільки отримати ім'я другого каналу і здійснити переказ. Розглянемо приклад bash-скрипта, який реалізує потрібний функціонал (протестовано на FreePBX 13):

#!/bin/bash
context="from-internal" # задаємо контекст, в який будемо переводити виклик
розширеннями=$1 # отримуємо номер оператора
num=$2 # отримуємо зовнішній або внутрішній номер, на який здійснимо переклад
bridge=$(asterisk -rx 'core show channels concise' | grep SIP/$розширеннями- | cut -d '!' -f13 ) # отримуємо bridge-id для каналу назва якого має вигляд SIP/xx-aaaaa
channel=$(asterisk -rx 'core show channels concise' | grep $bridge | grep -v SIP/$розширеннями- | cut -d '!' -f1) # отримуємо channel сполученого з ним каналу виду SIP/provider-000000
result=$(asterisk -rx "channel redirect $channel $context,$num,1") # переводимо отриманий канал в потрібний контекст
echo $result
exit 0


Скрипт викликається з двома параметрами — номер оператора та номер, на який потрібно перевести дзвінок. Залишається тільки «навчити» CRM його коректно викликати.

Що ж ми отримали в результаті? Можливість переведення дзвінка оператора по одному кліку без необхідності використання баз даних та додаткових дій з боку працівника, не використовуючи готові CRM і модулі для роботи з asterisk для них. При цьому, скрипт однаково працює як з вхідними, так і з зовнішніми викликами.

Подібна реалізація буде корисна для аутсорс-колл-центрів, довідкових та інших служб, де потрібно швидко переводити дзвінки на велике число номерів, а також може застосовуватися для полегшення праці секретаря у великій організації.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.