В середньостатистичного ISP, функціонування колцентру/техпідтримки зводиться до двох простих речей:
Усе. Нічого більше глобально не відбувається. Все інше це вторинні штуки і розширення, призначені суто для підвищення зручності, отримання статистики, контролю якості та розуміння того, що відбувається у вищеописаних двох пунктах.
За звичай, в інтернетах ще прийнято ілюструвати це все якимись такими добрими картинками, на кшталт таких:
чи такими
або навіть такими, ну щоб “взагалі на серйозних щах”
Так-так, більше усміхнених і щасливих людей! Так! Ще більше! Йоу! Щасливий персонал, котрий контактує з клієнтами! Це ж так реалістично… ага..
Ну, ви ж розумієте, куди ви потрапили, де ви це читаєте і що далі подібної херні не буде? Так?
Для реалізації основного функціоналу колцентру вам знадобляться:
Тут усе зрозуміло. Для цього взагалі можна нічого особливо не робити. Воно “якось робиться” і “якось працює”. Фактично саме по-собі.
Але можливо вам захочеться наступних речей:
Власне всі вищевикладені речі, в тому чи іншому вигляді, цілком можна реалізувати за допомогою інтеграції вашої PBX з Ubilling.
Власне типовий і рандомно-масштабований кейс типового кол центру виглядає якось так:
(саппортів намальовано три штуки, щоб вони могли по черзі обійматися і плакати)
PBX ми будемо використовувати On-Premise Asterisk, оскільки боротись з тарганами в голові нікому невідомих SaaS ми не хочемо і в принципі не маємо здоров'я розбиратись з цим за вас. Також поряд там намальовано GSM-to-SIP gateway, в який можна натицяти SIM-карток та приймати виклики ними. Якщо вам дуже хочеться аби ми “порадили якийсь нормальний”, то нехай це буде, щось типу Yeastar TGХХХ. Якщо вам дуже цікаво знати, як це все налаштовується та інтегрується з Asterisk - дайте нам знати, скажімо отут @Ubilling.
В подальшому будуть використовуватись наступні дані, для прикладу:
Дані з прикладу | Що це? |
---|---|
192.168.0.162/24 | IP адреса нашого серверу з Asterisk |
em1 | Інтерфейс, через котрий ми будемо спілкуватись з PBX |
192.168.0.161/24 | IP адреса нашого біллінгового серверу з Ubilling |
172.16.42.0/24 та 192.168.0.0/24 | умовно “безпечні мережі” де знаходяться наше обладнання, телефони, працівники, тощо |
185.45.152.0/22 та 195.5.0.54/32 | Мережі та адреси ззовні нашої мережі, де знаходяться наші SIP-провайдери |
444444 | Номер отриманий від сервісу Zadarma. Він же логін. |
0800123456 | Вхідний багатоканальний 0800 номер від Укртелекому, насправді 0800 працюють як “аліаси” і дзвінки з них надходять на “справжній номер” |
0333333333 | Наш справжній номер Укртелекому, на який прилітатиме усе, що дзвонить на 0800123456 а також кудою ми будемо здійснювати вихидні дзвінки за замовчуванням. Він же логін. |
195.5.0.54 | IP адреса SIP транку Укртелекому |
sip.zadarma.com | Хост SIP транку сервісу Zadarma |
zadarmasecretpassword | Пароль сервісу Zadarma |
verysecretmysqlrootpassword | root-пароль на MySQL серверу телефонії |
asteriskmysqlpassword | пароль MySQL користувача asterisk - використовувається для з'єднання з БД як самим Aterisk для запису CDR, так і біллінгом для читання CDR |
UBxxxxxxxxxxxxxxxxxxxxx | Серійний номер вашого працюючого Ubilling |
http://192.168.0.161/billing/ | Повний URL веб інтерфейсу вашого Ubilling |
sharedsippassword | Загальний пароль наших SIP телефонів, це має сенс якщо всі їх налаштовує ваш адміністратор та стоять вони у вас десь в офісі |
bosspassword | Пароль на конкретний SIP телефон, який демонструє своїм виглядом, як використовувати конкретний пароль не наслідуючи “загальний” для якогось конкретного пристрою |
08:00-20:00 | Робочий час роботи техпідтримки |
20:00-08:00 | Час “нічного режиму” |
maryana,mariya,markiyan | Логіни та відповідно імена працівників служби техпідтримки, котрі приймають дзвінки |
121,122,123 | SIP номери працівників техпідтримки, котрі приймають дзвінки в рамках черги |
120 | SIP номер, котрий може телефонувати куди йому заманеться, але дзвінки від клієнтів не будуть до нього потрапляти |
У праву руку беремо чисту FreeBSD 13.2 та ставимо все необхідне нам ПЗ.
# pkg install -y asterisk18 # pkg install -y mysql80-server # pkg install -y lame # pkg install -y sox
Редагуємо наш /etc/rc.conf якось так
hostname="sip" ifconfig_em1="inet 192.168.0.162/24" defaultrouter="192.168.0.1" sshd_enable="YES" dumpdev="AUTO" #firewall firewall_enable="YES" firewall_nat_enable="YES" dummynet_enable="YES" firewall_script="/etc/firewall.conf" #fsck no bg fsck_y_enable="YES" background_fsck="NO" #asterisk and mysql mysql_enable="YES" asterisk_enable="YES" #nfs for calls archive export rpcbind_enable="YES" nfs_server_enable="YES" nfs_server_flags="-u -t -n 4" mountd_enable="YES" mountd_flags="-r"
Запихаємо все потрібне до /boot/loader.conf
kern.hz="1000" ipfw_load="YES" net.inet.ip.fw.default_to_accept="1" libalias_load="YES" ipfw_nat_load="YES" dummynet_load="YES"
І хоч якось намагаємося подбати про свою безпеку використовуючи якийсь такий /etc/firewall.conf
# touch /etc/firewall.conf # chmod a+x /etc/firewall.conf
#!/bin/sh # firewall command FwCMD="/sbin/ipfw -q" ${FwCMD} -f flush #safe networks define ${FwCMD} table 22 add 127.0.0.1 ${FwCMD} table 22 add 192.168.0.0/24 ${FwCMD} table 22 add 172.16.42.0/24 #peers ${FwCMD} table 22 add 185.45.152.0/22 ${FwCMD} table 22 add 195.5.0.54 #safe zones ${FwCMD} add 45 allow ip from table\(22\) to me ${FwCMD} add 45 allow ip from me to table\(22\) #ssh access ${FwCMD} add 46 deny ip from any to me dst-port 22 ${FwCMD} add 46 deny ip from me to any src-port 22 #snmp access ${FwCMD} add 47 deny ip from any to me dst-port 161 ${FwCMD} add 47 deny ip from me to any src-port 161 #SIP access ${FwCMD} add 48 deny ip from any to me dst-port 5060 ${FwCMD} add 48 deny ip from me to any src-port 5060 #mysql access ${FwCMD} add 49 deny ip from any to me dst-port 3306 ${FwCMD} add 49 deny ip from me to any src-port 3306 #Asterisk misc ${FwCMD} add 50 deny ip from any to me dst-port 28533 ${FwCMD} add 50 deny ip from me to any src-port 28533 ${FwCMD} add 50 deny ip from any to me dst-port 2727 ${FwCMD} add 50 deny ip from me to any src-port 2727 ${FwCMD} add 50 deny ip from any to me dst-port 4569 ${FwCMD} add 50 deny ip from me to any src-port 4569 ${FwCMD} add 50 deny ip from any to me dst-port 4520 ${FwCMD} add 50 deny ip from me to any src-port 4520 #NFS ${FwCMD} add 51 deny ip from any to me dst-port 111 ${FwCMD} add 51 deny ip from me to any src-port 111 ${FwCMD} add 51 deny ip from any to me dst-port 601 ${FwCMD} add 51 deny ip from me to any src-port 601 ${FwCMD} add 51 deny ip from any to me dst-port 602 ${FwCMD} add 51 deny ip from me to any src-port 602 ${FwCMD} add 51 deny ip from any to me dst-port 2049 ${FwCMD} add 51 deny ip from me to any src-port 2049 ${FwCMD} add 65535 allow all from any to any
Встановлюємо рутовий пароль на MySQL у випадку, якщо було згенеровано тимчасовий:
# service mysql-server start # cat /root/.mysql_secret # set OMP=`cat /root/.mysql_secret | tail -n 1` && mysqladmin -u root -p"${OMP}" password verysecretmysqlrootpassword
або ж просто змінуємо пароль на необхідний, якщо /root/.mysql_secret не існує:
# cat /root/.mysql_secret cat: /root/.mysql_secret: No such file or directory # mysqladmin -u root password verysecretmysqlrootpassword
Попередньо готуємо базу даних для зберігання наших CDR
# mysql -u root -pverysecretmysqlrootpassword
CREATE DATABASE asterisk; CREATE USER 'asterisk'@'%' IDENTIFIED BY 'asteriskmysqlpassword'; GRANT ALL PRIVILEGES ON *.* TO 'asterisk'@'%' WITH GRANT OPTION; USE asterisk; CREATE TABLE `cdr` ( `calldate` datetime NOT NULL DEFAULT '1970-01-01 00:00:01', `clid` varchar(80) NOT NULL DEFAULT '', `src` varchar(80) NOT NULL DEFAULT '', `dst` varchar(80) NOT NULL DEFAULT '', `dcontext` varchar(80) NOT NULL DEFAULT '', `channel` varchar(80) NOT NULL DEFAULT '', `dstchannel` varchar(80) NOT NULL DEFAULT '', `lastapp` varchar(80) NOT NULL DEFAULT '', `lastdata` varchar(80) NOT NULL DEFAULT '', `duration` int(11) NOT NULL DEFAULT '0', `billsec` int(11) NOT NULL DEFAULT '0', `disposition` varchar(45) NOT NULL DEFAULT '', `amaflags` int(11) NOT NULL DEFAULT '0', `accountcode` varchar(20) NOT NULL DEFAULT '', `userfield` varchar(255) NOT NULL DEFAULT '', `uniqueid` varchar(32) NOT NULL DEFAULT '' ) ENGINE=InnoDB DEFAULT CHARSET=latin1; ALTER TABLE `cdr` ADD KEY `calldate` (`calldate`), ADD KEY `dst` (`dst`), ADD KEY `uniqueid` (`uniqueid`); COMMIT; exit
а також готуємо місце для експорту записів дзвінків в NFS:
# mkdir /mnt/calls # chmod 777 /mnt/calls # echo "/mnt/calls -alldirs -maproot=root 192.168.0.161" > /etc/exports
а також місце, де ми зберігатимемо всю нашу кастомну озвучку
# mkdir /usr/local/etc/asterisk/ivr_media/ # mkdir /usr/local/etc/asterisk/ivr_media/dasmusic # chmod -R 777 /usr/local/etc/asterisk/ivr_media
і превентивно створюємо скрипт, який буде нотифікувати наш біллінг про вхідні дзвінки, що надходять /usr/local/etc/asterisk/notifybilling
# touch /usr/local/etc/asterisk/notifybilling # chmod a+x /usr/local/etc/asterisk/notifybilling
#!/bin/sh NUMBER=$* BILLING_SERIAL="UBxxxxxxxxxxxxxxxxxxxxx" BILLING_URL="http://192.168.0.161/billing/" NOTIFY_URL="${BILLING_URL}?module=remoteapi&key=${BILLING_SERIAL}&action=telepony&number=${NUMBER}" echo `date` ${NUMBER} >> /var/log/asterisk/income_calls.log /usr/bin/fetch -o /dev/null ${NOTIFY_URL}
Далі переходимо до власне конфігурації нашої(го?) PBX. Усі необхідні далі нам файли конфігурації лежать у /usr/local/etc/asterisk. Для початку, згадуємо, що ми ліниві та тупі, тому ми будемо використовувати старий і нікому не потрібний chan_sip замість нового та красивого PJSIP. Для цього потрібно закоментувати рядок “noload = chan_sip.so” в modules.conf, приблизно якось так:
;noload = chan_sip.so
а також там же, ми можемо вимкнути деякі модулі які нам скоріш за все не знадобляться
noload = res_hep.so noload = res_hep_pjsip.so noload = res_hep_rtcp.so noload = res_config_pgsql.so noload = cel_sqlite3_custom.so noload = cel_radius.so noload = cdr_pgsql.so noload = cdr_radius.so noload = chan_skinny.so noload = res_ari.so noload = res_phoneprov.so noload = cel_custom.so noload = res_pjsip_phoneprov_provider.so noload = res_ari_asterisk.so noload = res_ari_channels.so noload = res_ari_applications.so noload = res_ari_device_states.so noload = res_ari_recordings.so noload = res_ari_sounds.so noload = res_ari_playbacks.so noload = res_ari_bridges.so noload = res_ari_events.so noload = res_ari_endpoints.so noload = res_timing_dahdi.so noload = res_pjsip_transport_websocket.so noload = cel_tds.so noload = cdr_tds.so noload = cdr_sqlite3_custom.so noload = chan_unistim.so
Далі редагуємо sip.conf приводячи його до наступного вигляду, і залишаючи в ньому лише якісь такі, базові штуки:
[general] context=default allowoverlap=no bindport=5060 bindaddr=0.0.0.0 srvlookup=yes relaxdtmf=yes alwaysauthreject=yes videosupport=no notifybusy=yes counteronpeer=yes notifyhold=yes notifycid=ignore-context notifyringing=yes pedantic=yes callcounter=yes register_retry_403=yes [authentication] [phones](!) type=friend context=call-out secret=sharedsippassword host=dynamic nat=force_rport,comedia qualify=yes dtmfmode=auto qualifyfreq=60 qualify=2000 disallow=all allow=alaw allow=ulaw allow=gsm allow=g726 allow=g729 allow=g723 allow=g722 phone-mac-type=none call-limit=1 callgroup=1 pickupgroup=1 canreinvite=no ;================================== ; Here is some awesome phones! ;================================== #include phones.conf ;================================== ; Providers configuration below ;================================== #include providers.conf
Виходячи з цього, досить очевидно що для наших пірів, тобто SIP-телефонів з групи [phones], ми резервуємо окремий конфіг phones.conf і будемо використовувати загальний пароль sharedsippassword, який при бажанні можна перепризначити опцією secret конкретного клієнту. Але ж ми пам'ятаємо, що ми ліниві? Так? Власне наших SIP транків, через які надходять та виходять дзвінки, ми будемо описувати в providers.conf. На майбутнє вважатимемо їх нашими “SIP-провайдерами”. В принципі можна все це намалювати прямо в sip.conf і не використовуючи групи, як і роблять у більшості мануалів, але повірте - коли у вас буде кілька десятків телефонів і десяток транків - підтримка цього перетворитися на пекельне пекло. Воно вам треба?
Далі просто заповнюємо наші телефони у phones.conf
[120](phones) callerid=Boss <120> secret=bosspassword [121](phones) callerid=Maryana <121> [122](phones) callerid=Mariya <122> [123](phones) callerid= Markiyan <123>
Та наших SIP-провайдерів відповідно в providers.conf
; Ukrtelecom 0800 [0333333333] type=peer defaultuser=0333333333 secret= fromuser=0333333333 host=195.5.0.54 port=5060 context=call-in fromdomain=195.5.0.54 language=ru-ru nat=never qualifyfreq=60 qualify=2000 directmedia=no insecure=port,invite dtmfmode=rfc2833 disallow=all allow=alaw ;Zadarma trunk [444444] host=sip.zadarma.com insecure=invite,port type=peer fromdomain=sip.zadarma.com disallow=all allow=alaw dtmfmode=auto secret=zadarmasecretpassword defaultuser=444444 trunkname=444444 fromuser=444444 callbackextension=444444 context=call-in qualify=400 directmedia=no nat=force_rport,comedia
Додаємо телефони нашої техпідтримки в чергу для обдзвонювання, приводячи queues.conf до наступного виду:
;Primary tech support queue [techsupport] music = dasmusic timeout=7 wrapuptime=5 ringinuse=yes autofill=yes periodic-announce = /usr/local/etc/asterisk/ivr_media/wait periodic-announce-frequency = 15 ;possible strats: ringall, leastrecent, fewestcalls, random, rrmemory, linear, wrandom strategy = rrmemory ;Queue members here member => SIP/121 member => SIP/122 member => SIP/123
та додаємо відповідний клас музики додаючи у musiconhold.conf наступне:
[dasmusic] mode=quietmp3 directory=/usr/local/etc/asterisk/ivr_media/dasmusic
Все досить очевидно, так? А тепер намагаємось зосередитись. Зараз почнеться трохи складніше.
Описуємо поведінку всієї нашої телефонії у вигляді діалплану, приводячи extensions.conf до наступного вигляду
[general] static=yes writeprotect=no [globals] DIR_RECORDS=/mnt/calls/ [default] [recording-in] exten => s,1,Set(fname=in_${ARG1}_${STRFTIME(${EPOCH},,%Y-%m-%d-%H-%M-%S)}) exten => s,n,Set(CDR(filename)=${fname}.gsm) exten => s,n,Set(CDR(userfield)=in) exten => s,n,MixMonitor(${DIR_RECORDS}${fname}.gsm,b) exten => s,n(no),Verbose(Exit record) exten => s,n,Return() [recording-out] exten => s,1,Set(fname=out_${ARG2}_${STRFTIME(${EPOCH},,%Y-%m-%d-%H-%M-%S)}) exten => s,n,Set(CDR(filename)=${fname}.gsm) exten => s,n,Set(CDR(userfield)=out) exten => s,n,MixMonitor(${DIR_RECORDS}${fname}.gsm,b) exten => s,n(no),Verbose(Exit record) exten => s,n,Return() [handup-sip] exten => _X!,1,HangUp() ; Outcoming calls [call-out] ;Debug and testing extensions exten => 334,1,Goto(ivr-main,s,1) exten => 333,1,Queue(techsupport,t) ; internal num call exten => _XXX,1,Dial(SIP/${EXTEN}) ; external number call via 0800 exten => _XXX.,1,Set(VOLUME(RX)=8) exten => _XXX.,2,Set(VOLUME(RX)=8) exten => _XXX.,3,GoSub(recording-out,s,1,(${CALLERID(num)},${EXTEN})) exten => _XXX.,4,Dial(SIP/${EXTEN}@0333333333) ;zadarma test exten => 1111,1,Dial(SIP/${EXTEN}@444444) include => handup-sip ;Incoming calls [call-in] exten => 0333333333,1,Goto(ivr-main,s,1) exten => 444444,1,Goto(ivr-main,s,1) [ivr-main] exten => s,1,Answer() exten => s,n,Set(VOLUME(TX)=8) exten => s,n,Set(VOLUME(RX)=8) ;comment following line to disable nightmode exten => s,n,GotoIfTime(20:00-08:00,*,*,*?nightmode,s,1) exten => s,n,GoSub(notifybilling,s,1,(${CALLERID(num)})) exten => s,n,Wait(3) exten => s,n,Background(/usr/local/etc/asterisk/ivr_media/greeting) exten => s,n,GoSub(recording-in,s,1,(${CALLERID(num)},${EXTEN})) exten => s,n,Queue(techsupport,t) [nightmode] exten => s,1,Wait(2) exten => s,2,Playback(/usr/local/etc/asterisk/ivr_media/nighttime) exten => s,3,Wait(3) exten => s,4,Hangup() [notifybilling] exten => s,1,system(/usr/local/etc/asterisk/notifybilling ${ARG1}) exten => s,n,Return()
Детальніше про діалплани та те як вони працюють, ви можете дізнатись, почитавши ось цю документацію чи подивившись ось ці, дуже цікаві та пізнавальні відео на YouTube.
Стало страшно? Ну якщо так - можете помолитись і продовжувати читати далі
У випадку, якщо вам надто складно, то все що вам потрібно знати, це те що вхідні дзвінки маршрутизуються в контексті (так, це оті штуки в квадратних дужечках) call-in та передають дзвінок в контекст ivr-main якоюсь отакою конструкцією
[call-in] exten => номер_на_котрий_прилетів_дзвінок,1,Goto(ivr-main,s,1)
а те, куди буде змаршрутизовано вихідні дзвінки з ваших телефонів керується в контексті call-out. Власне за напрямок за замовчуванням, кудою будуть улітати всі наші вихідні звінки на номери довжиною більше трьох цифр відповідає оця конструкція:
[call-out] ..... exten => _XXX.,4,Dial(SIP/${EXTEN}@0333333333)
Окей, страшне закінчилось. Продовжуємо далі.
Вмикаємо запис CDR в нашу MySQL базу, додавши в конфіг cdr_mysql.conf секцію [global] наступного вигляду
[global] hostname=localhost dbname=asterisk table=cdr user=asterisk password=asteriskmysqlpassword
Також не забуваємо переконатися, що MySQL буде слухати всі потрібні нам інтерфейси, виправивши опцію bind-address у секції [mysqld] конфігу /usr/local/etc/mysql/my.cnf якось так
bind-address = 0.0.0.0
з подальшим перезапуском MySQL
# service mysql-server restart
Тепер можемо перевірити, як це все стартує запустивши Asterisk
# service asterisk start
і залогінившись у його консоль
# asterisk -r
далі ми можемо виконати, наприклад, команду sip show peers і дізнатися як виглядають наші піри
sip*CLI> sip show peers Name/username Host Dyn Forcerport Comedia ACL Port Status Description 0333333333/0333333333 195.5.0.54 No No 5060 OK (14 ms) 120 (Unspecified) D Yes Yes 0 UNKNOWN 121 (Unspecified) D Yes Yes 0 UNKNOWN 122 (Unspecified) D Yes Yes 0 UNKNOWN 123 (Unspecified) D Yes Yes 0 UNKNOWN 444444/444444 185.45.152.161 Yes Yes 5060 OK (29 ms)
Наразі, ми можемо взяти будь-який підручний SIP-клієнт чи телефон, та швиденько його налаштувати
і переконатися, що він успішно логіниться.
sip*CLI> sip show peers Name/username Host Dyn Forcerport Comedia ACL Port Status Description 0333333333/0333333333 195.5.0.54 No No 5060 OK (14 ms) 120 (Unspecified) D Yes Yes 0 UNKNOWN 121 (Unspecified) D Yes Yes 0 UNKNOWN 122/122 172.16.42.8 D Yes Yes 5060 OK (5 ms) 123 (Unspecified) D Yes Yes 0 UNKNOWN 444444/444444 185.45.152.161 Yes Yes 5060 OK (29 ms)
Також можна подивитися на стан нашої черги за допомогою команди queue show
sip*CLI> queue show techsupport has 0 calls (max unlimited) in 'rrmemory' strategy (0s holdtime, 0s talktime), W:0, C:0, A:0, SL:0.0%, SL2:0.0% within 0s Members: SIP/121 (ringinuse enabled) (Not in use) has taken no calls yet (login was 6 secs ago) SIP/123 (ringinuse enabled) (Unavailable) has taken no calls yet (login was 6 secs ago) SIP/122 (ringinuse enabled) (Not in use) has taken no calls yet (login was 6 secs ago) No Callers
Тепер можна перезавантажити сервер, щоб переконатися, що все стартує саме і нормально працює після його завантаження
# reboot
Наразі, ми можемо спробувати зателефонувати на номер 1111 через Zadarma, щоб дізнатися про стан нашого рахунку і просто послухати як воно звучить. А також спробувати зателефонувати до черги самому, скориставшись тестовим номером 334 аби послухати як це все звучатиме для користувачів при вхідному дзвінку.
Ми ж хочемо, щоб усе гарно розмовляло, вітало та повідомляло? Для початку слід запам'ятати, що всі файли з нашим озвученням ми будемо класти в /usr/local/etc/asterisk/ivr_media/ у прийнятному для Asterisk форматі. Конвертувати MP3 в нього, можна якось так:
$ lame --decode filename.mp3 tmp.wav $ sox -v 0.5 tmp.wav -t wav -b 16 -r 8000 -c 1 filename.wav $ rm tmp.wav
Виходячи з вищеописаного прикладу конфігурації ми припускаємо, що такі файли містять відповідну озвучку:
Якщо ви з якоїсь причини, не здатні за досить мало грошей домовитися з професійним диктором, який надиктує потрібні вам звукові файли з нормальною артикуляцією та поставленим голосом, можете спробувати використати щосьіз цих файлів, за авторством VikDon чисто для тестування.
Записи дзвінків, зберігаємо в .gsm, оскільки місце в вас не безлімітне, а Ubilling вміє сам нормально прослуховувати та конвертувати при збереженні їх в mp3 чи ogg.
Те, в якій черговості будуть дзвонити телефони вашої техпідтримки регулюється опцією strategy черги в конфігу queues.conf. Вони можуть бути якимись такими:
Монтуємо записи дзвінків на локальну файлову систему:
# mkdir /mnt/calls_records # mkdir /mnt/calls_archive # chmod -R 777 /mnt/calls_* # mount 192.168.0.162:/mnt/calls /mnt/calls_records
Додаємо автоматичне монтування цієї директорії при завантаженні в /etc/fstab
192.168.0.162:/mnt/calls /mnt/calls_records nfs rw 0 0
Далі в alter.ini вмикаємо власне телефонію а також заповнюємо доступ до БД з CDR:
TELEPONY_ENABLED=1 TELEPONY_CDR="192.168.0.162|asterisk|asteriskmysqlpassword|asterisk|cdr"
Вмикаємо модуль “Записи телефонних розмов”
PBXMON_ENABLED=1
Модуль “Навіщо телефонуєш?”
WDYC_ENABLED=1
та додаємо потрібні для його роботи виклики в crontab
*/1 * * * * /bin/ubapi "whydoyoucall" 5 20 * * * /bin/ubapi "whydoyoucallstats"
Він нам потрібен для відслідковування “пропущених дзвінків”, ну тобто “абонент зателефонував, повисів на лінії, йому стало сумно, він поклав слухавку”. В самому по собі “пропущенному дзвінку” немає нічого страшного. Набагато гірше, коли він в кінці робочого дня стає “дзвінком без реакції” бо абоненту ніхто не перетелефонував і не дізнався, що він хотів. Власне для забезпечення цієї самої реакції нам і потрібен модуль “Навіщо телефонуєш?”.
Та вмикаємо модуль “Історія дзвінків”
CALLSHIST_ENABLED=1
Швиденько також налаштовуємо модуль По кому подзвін?
FWTBT_ENABLED=1 FWTBT_ANYWHERE=1 FWTBT_ADMINS="maryana,mariya,markiyan" FWTBT_INTERVAL=7 FWTBT_TIMER=10 FWTBT_DESKTOP=1
Також може знадобитись “Телефонний довідник”
PHONEBOOK_ENABLED=1
де ми, щонайменше зможемо заповнити внутрішні номери наших працівників
Також непоганим кейсом, задля того аби зробити ваш сервіс ще кращим, може буде налаштувати модуль та оточення для обробки запитів зворотніх дзвінків:
CALLMEBACK_ENABLED=1
Також чисто заради естетичного задоволення, можемо додати маунтпоінт записів дзвінків до опції SYSLOAD_DISKS
SYSLOAD_DISKS="/,/mnt/calls_records/"
задля того, щоб візуально контролювати заповненість
Ось власне і все.
Тепер, при надходженні вхідного дзвінка, ваша техпідтримка зможе:
Менеджмент, в свою чергу також може контролювати, базові KPI опрацювання телефонних дзвінків техпідтримкою, за допомогою модулю “Екзистенційний кінць” куди вже автоматично складаються дані по наступних показниках:
Ну а також вибірково прослуховувати/завантажувати записи телефонних розмов у різних форматах, для розбору польотів.
Вам також, може захотітись автоматично реагувати на стан ваших абонентів, у випадку якщо вам телефонує ваш абонент з відомим вам номером у якого на рахунку заборгованість “одразу після привітання кажемо йому “шановний абонент у вас на рахунку заборгованість”, або його рахунок заморожено, про що ми також хочемо його повідомити. Ну або ще щось на кшталт того. Тут на допомогу нам прийде механіка AGI скриптів, котру ми можемо викликати з нашого контексту ivr-main. Взагалі, якщо ви розумієте, що ви робите, насправді, все лімітовано тільки вашою фантазією та скіллом.
Для початку встановлюємо PHP, на якому ми і будемо писати AGI скрипти, котрі лежатимуть у нас за шляхом /usr/local/share/asterisk/agi-bin/
# pkg install -y php82
Після чого, створюємо наступний файл скрипта /usr/local/share/asterisk/agi-bin/telepathy.php який власне і отримуватиме стан вгаданого за номером абонента, паралельно нотифікуючи біллінг про вхідний дзвінок.
#!/usr/local/bin/php -q <?php /** * Config section */ //Ubilling serial number $ubillingSerial = 'UBxxxxxxxxxxxxxxxxxxxxx'; //Full Ubilling URL for API connection $ubillingApiUrl = 'http://192.168.0.161/billing/'; $userStates = array( '2' => 'nomoney', '3' => 'frozen' ); /** * End of config section */ $stdin = fopen('php://stdin', 'r'); $stdout = fopen('php://stdout', 'w'); $number=$argv[1]; $url = $ubillingApiUrl . '?module=remoteapi&key=' . $ubillingSerial . '&action=telepony&number=' . $number; $user = file_get_contents($url); $user = trim($user); if (isset($userStates[$user])) { //uncomment following line to debug detected caller id user state //fputs($stdout,'SAY ALPHA "'.$userStates[$user].'" ""'.PHP_EOL); fputs($stdout,'EXEC PLAYBACK "/usr/local/etc/asterisk/ivr_media/'.$userStates[$user].'" ""'.PHP_EOL); fflush($stdout); } fclose ($stdin); fclose ($stdout); exit(0);
додаємо контекст telepathy котрий власне і буде викликати наш AGI скрипт з параметром у вигляді CALLERID(num)
[telepathy] exten => s,1,AGI(telepathy.php,${ARG1}) exten => s,n,Return()
ну і власне, наш контекст ivr main в діалплані, тепер може виглядати наступним чином:
[ivr-main] exten => s,1,Answer() exten => s,n,Set(VOLUME(TX)=8) exten => s,n,Set(VOLUME(RX)=8) ;comment following line to disable nightmode exten => s,n,GotoIfTime(20:00-08:00,*,*,*?nightmode,s,1) exten => s,n,Wait(3) exten => s,n,Background(/usr/local/etc/asterisk/ivr_media/greeting) exten => s,n,GoSub(telepathy,s,1,(${CALLERID(num)})) exten => s,n,GoSub(recording-in,s,1,(${CALLERID(num)},${EXTEN})) exten => s,n,Queue(techsupport,t)
власне очевидно, що ми заміняємо контекст notifybilling на telepathy для того, щоб здійснювати нотифікацію біллінгу про вхідний дзвінок а також озвучувати абоненту якийсь файл, з /usr/local/etc/asterisk/ivr_media/ відносно його статусу, перед передачею дзвінка до черги.
Коротко про статуси абонентів, що повертаються в AGI скрипт:
Отож, виходячи з цього, наступним массивом AGI скрипта телепатії, регулюється який конкретний файл з теки, буде програно абоненту одразу після привітання:
$userStates = array( '0' => 'nouser', '1' => 'allok', '2' => 'nomoney', '3' => 'frozen' );
очевидно, що на відповідні статуси буде програно файли з іменами nouser.wav, allok.wav, nomoney.wav та frozen.wav які ми покладемо у /usr/local/etc/asterisk/ivr_media/?
Також ми можемо зручно віддебажити виконання нашого контексту та AGI скрипта за допомогою команди agi set debug on в консолі Asterisk:
# asterisk -r *CLI> agi set debug on AGI Debugging Enabled
Та зателефонувавши за тестовим номером 334, нашого контексту ivr-main. Якось так:
<SIP/122-00000007>AGI Tx >> agi_request: telepathy.php <SIP/122-00000007>AGI Tx >> agi_channel: SIP/122-00000007 <SIP/122-00000007>AGI Tx >> agi_language: en <SIP/122-00000007>AGI Tx >> agi_type: SIP <SIP/122-00000007>AGI Tx >> agi_uniqueid: 1677860146.8 <SIP/122-00000007>AGI Tx >> agi_version: 18.15.1 <SIP/122-00000007>AGI Tx >> agi_callerid: 122 <SIP/122-00000007>AGI Tx >> agi_calleridname: Mariya <SIP/122-00000007>AGI Tx >> agi_callingpres: 0 <SIP/122-00000007>AGI Tx >> agi_callingani2: 0 <SIP/122-00000007>AGI Tx >> agi_callington: 0 <SIP/122-00000007>AGI Tx >> agi_callingtns: 0 <SIP/122-00000007>AGI Tx >> agi_dnid: 334 <SIP/122-00000007>AGI Tx >> agi_rdnis: unknown <SIP/122-00000007>AGI Tx >> agi_context: telepathy <SIP/122-00000007>AGI Tx >> agi_extension: s <SIP/122-00000007>AGI Tx >> agi_priority: 1 <SIP/122-00000007>AGI Tx >> agi_enhanced: 0.0 <SIP/122-00000007>AGI Tx >> agi_accountcode: <SIP/122-00000007>AGI Tx >> agi_threadid: 34418519040 <SIP/122-00000007>AGI Tx >> agi_arg_1: 122 <SIP/122-00000007>AGI Tx >> <SIP/122-00000007>AGI Rx << EXEC PLAYBACK "/usr/local/etc/asterisk/ivr_media/frozen" "" <SIP/122-00000007>AGI Tx >> 200 result=0
Дуже-дуже чорний. Початок нашого контексту ivr-main повинен виглядати наступним чином:
[ivr-main] exten => s,1,Answer() exten => s,2,GotoIf($[${BLACKLIST()}=1]?blacklist) exten => s,3,GoTo(ivr-main,s,5) exten => s,4(blacklist),Hangup()
Додавання номера в чорний список відбувається так:
asterisk -rx 'database put blacklist 0931234567 1'
asterisk -rx 'database del blacklist 0931234567'
Перегляд чорного-чорного списку номерів:
asterisk -rx 'database show blacklist'
Налаштування конференцій, теж дуже просте та зрозуміле. Для початку в діалплан, в контекст call-out необхідно додати відповідні записи, якось так:
; Outcoming calls [call-out] ; conference exten => 777,1,Answer() exten => 777,n,ConfBridge(1,confer) ....
та у конфіг /usr/local/etc/asterisk/confbridge.conf, в самому його кінці, необхідно додати якусь таку секцію налаштувань нашої конференції:
[confer] type=bridge max_members=20 mixing_interval=10 internal_sample_rate=auto record_conference=yes
Очевидно, що наші телефони, одночасно всі, зможуть між собою поспілкуватись, зідзвонившись за номером 777.