All pages
Powered by GitBook
1 of 11

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Входящая маршрутизация

Выбор провайдера при переадресации на мобильный

Задача: На АТС заведено несколько провайдеров А,Б,В,Г… Вызов поступает на MikoPBX через провайдера А. При наборе мобильного номера сотрудника вызов должен также идти через провайдера А. Провайдер должен поддерживать более одного одновременного вызова.

  1. Перейдите в раздел Система → Кастомизация системных файлов

Меню кастомизации системных файлов
  1. Откройте для редактирования конфигурационный файл extensions.conf.

Редактирование файла Extensions.conf
  1. Установите режим «Добавлять в конец файла». В черное окно добавьте следующий фрагмент кода:

[all-outgoing-custom]
exten => _[0-9*#+a-zA-Z][0-9*#+a-zA-Z]!,1,NoOp(-)
    same => n,NoOp("${PROVIDER_ID}" --- "${ONLY_THIS_PROVIDER}")
    same => n,Set(NEED_RETURN=${UNDEFINED})
    same => n,ExecIf($["${ONLY_THIS_PROVIDER}x" == "x"]?return)
    same => n,ExecIf($["${PROVIDER_ID}" != "${ONLY_THIS_PROVIDER}"]?Set(NEED_RETURN=1))
    same => n,ExecIf($["${PROVIDER_ID}" != "${ONLY_THIS_PROVIDER}"]?Set(ROUTFOUND=${UNDEFINED}))
    same => n,Return()
    
[add-trim-prefix-clid-custom]
exten => _[0-9*#+a-zA-Z][0-9*#+a-zA-Z]!,1,NoOp(start check blacklist)
    same => n,ExecIf($["${CHANNEL(channeltype)}" == "PJSIP" ]?Set(__ONLY_THIS_PROVIDER=${CHANNEL(endpoint)}))
    same => n,Return()
Код для extension.conf
  1. Для каждого провайдера необходимо описать исходящий маршрут

  2. Заполните для сотрудников мобильные номера см. документацию

  3. Ограничьте использование исходящих маршрутов для пользователей, используйте модуль «Группы пользователей»

  4. Теперь если выходящий вызов направить на мобильный сотрудника, к примеру через IVR меню, то вызов будет направлен через того же провайдера, через которого пришел

ВНИМАНИЕ: Инструкции актуальны только для MikoPBX 2022.2.96+

Разрешить донабор внутреннего номера в очереди

Такая необходимость может возникнуть во многих случаях, К примеру когда клиент устал ждать на линии, можно предложить ему оставить голосовое сообщение, соединить с известным клиенту внутренним номером.

  1. Перейдите во вкладку "Кастомизация системных файлов"

  1. Откройте для редактирования файл "queues.conf"

  1. В черном окне найдите секцию очереди, которую необходимо настроить

  1. Выберите режим "Добавлять в конец файла". Добавьте аналогичную секцию с приставкой (+) :

В данном примере мы описали контекст internal, разрешен набор всех внутренних номеров. Можно указать контекст IVR меню, в формате ivr<ВнутреннийНомерIVR>

[QUEUE-16C8964EE3372C20812A4286183C2BC7](+)
context=internal
Раздел "Кастомизация системных файлов
Файл "queues.conf"
Секции очереди
Код для "queues.conf"

Уведомление о занятости, Call Waiting

  1. Перейдите в раздел Кастомизация системных файлов

Раздел "Кастомизация системных файлов"
  1. Перейдите к редактированию файла "modules.conf"

Редактирование файла "modules.conf"
  1. Добавьте в конец файла следующий код:

load => func_extstate.so
Код для "modules.conf"
  1. Перейдите к редактированию файла "extensions.conf"

Редактирование файла "extensions.conf"
  1. Добавьте в конец файла следующий код:

[internal-users-custom]
exten => _X!,1,Progress()
  same => n,ExecIf($["${EXTENSION_STATE(${EXTEN})@internal-hints}" = "INUSE" || "${EXTENSION_STATE(${EXTEN}@internal-hints)}" = "RINGINUSE"]?Playback(beep))
  same => n,ExecIf($["${EXTENSION_STATE(${EXTEN})@internal-hints}" = "INUSE" || "${EXTENSION_STATE(${EXTEN}@internal-hints)}" = "RINGINUSE"]?Set(TRANSFER_OPTIONS=${TRANSFER_OPTIONS}m))
    same => n,return
Код для "extensions.conf"
  1. В карточке сотрудника, в поле «Расширенные настройки» - «Дополнительные параметры» установите значение

[endpoint]
device_state_busy_at = 3

Если сотрудник будет занят, то звонящему будет проигран файл beep (короткий гудок), затем вместо гудков будет проигрываться музыка, пока сотрудник не ответит на вызов

device_state_busy_at - это то количество разговоров, при котором следует считать сотрудника «занятым», в этом случае начнут работать правила «Настройки маршрутизации», описанные в карточке сотрудника.

В случае некорректной работы решения задачи, измените код в extensions.conf на:

[internal-users-custom]
exten => _X!,1,Progress()
same => n,NoOp(${EXTEN})
same => n,NoOp(${DEVICE_STATE(PJSIP/${EXTEN})})
same => n,ExecIf($["${DEVICE_STATE(PJSIP/${EXTEN})}" = "INUSE" || "${DEVICE_STATE(PJSIP/${EXTEN})}" = "RINGINUSE"]?Background(nomer&zanjat))
same => n,ExecIf($["${DEVICE_STATE(PJSIP/${EXTEN})}" = "INUSE" || "${DEVICE_STATE(PJSIP/${EXTEN})}" = "RINGINUSE"]?Set(TRANSFER_OPTIONS=${TRANSFER_OPTIONS}m(callwaiting)))
same => n,return

Базовый пример IVR

Постановка задачи

Клиент звонит в компанию, звучит приветственное сообщение (голосовое приветствие).

Во время проигрывания голосового приветствия клиент может набрать любой внутренний номер, например, добавочный номер сотрудника.

Также клиент может ввести с телефона цифры:

  • 1 - вызов в этом случае направится на сотрудника с внутренним номером 201.

  • 2 - вызов направится на сотрудника с внутренним номером 202.

Если клиент ничего не ввел / некорректно набрал номер, то происходит переадресация на номер по умолчанию - сотрудника с внутренним номером 201.

Схематично задачу можно представить следующим образом:

Схема поставленной задачи

Решение

1. Создаем учетные записи сотрудников по инструкции. Подключаем программные или аппаратные телефоны к данным учетным записям.

Сотрудники
  1. Добавляем звуковой файл приветствия по инструкции, который будет слышать клиент при звонке на номер компании.

Меню "Звуковые файлы"
  1. Добавляем новое IVR-меню по инструкции.

IVR меню

При звонке на голосовое меню (Номер IVR меню) начинает проигрываться звуковой файл «Голосовое приветствие».

Во время проигрывания голосового меню можно набрать:

  • любой внутренний номер, например, добавочный номер сотрудника. За эту возможность отвечает флаг Разрешить донабор любого внутреннего номера.

  • цифру 1 - вызов направится на сотрудника с внутренним номером 201

  • цифру 2 - вызов направится на сотрудника с внутренним номером 202

Если во время проигрывания голосового меню клиент ничего не ввел, то после проигрывания голосового меню происходит ожидание 7 секунд для набора комбинации цифр. «Общее время для набора номера» = «Длительность звукового файла» + 7 секунд.

Если «Общее время для набора номера» истекло, то происходит переадресация на «Номер по умолчанию», т.е. на сотрудника с внутренним номером 101.

Если необходимо повторно воспроизвести голосовое приветствие и дать клиенту возможность снова ввести номер, то установите «Количество повторов, перед переводом на номер по умолчанию» в значение 2 и более. Происходит повторное голосовое оповещение и ожидание 7 секунд, то есть следующая попытка IVR. Как только попытки превышают указанное значение - происходит переадресация на «Номер по умолчанию».

Если пользователь некорректно набирает номер или вообще ничего не набирает, то происходит повторное голосовое оповещение (в случае если Количество повторов установлено больше 2-х), либо происходит переадресация на «Номер по умолчанию» (в случае если Количество повторов равно 1).

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

Провайдеры телефонии
  1. Настраиваем прием всех входящих звонков через заведенного провайдера на IVR-меню.

Новое правило обработки входящих вызовов

Инструкции по настройке входящей маршрутизации доступны по ссылке.

Пример реализации типового маршрута входящих вызовов

Постановка задачи

Клиент звонит в компанию, звучит приветственное сообщение (голосовое приветствие).

Во время проигрывания голосового приветствия клиент может набрать любой внутренний номер, например, добавочный номер сотрудника или добавочный номер отдела.

После проигрывания голосового приветствия клиент может ввести с телефона цифры:

  • 1 - вызов в этом случае направится в отдел продаж. Отдел продаж - это очередь вызовов, состоящая из двух агентов очереди (двух сотрудников). При звонке в отдел продаж вызов должен поступать на телефоны сотрудников одновременно. Если в течение 25 секунд никто из сотрудников не ответил на звонок клиента, то вызов должен направиться на мобильные номера сотрудников.

  • 2 - вызов направится в отдел технической поддержки. Отдел технической поддержки - это очередь вызовов, состоящая из трех агентов очереди (трех сотрудников). Вызов должен поступать на любого свободного сотрудника (агента очереди). Если клиент ожидает ответ на свой звонок более 30 секунд, то вызов должен быть переведен на секретаря.

Если клиент ничего не ввел / некорректно набрал номер, то происходит повторное голосовое оповещение и клиент может снова ввести номер. Как только все попытки ввода корректного номера для клиента завершатся, то происходит переадресация вызова на секретаря.

Решение

Очереди вызовов

Инструкции по очередям вызовов доступны по ссылке.

Для нашего примера необходимо создать три очереди вызова:

  1. Отдел продаж (мобильные номера сотрудников)

  2. Отдел продаж (внутренние номера сотрудников)

  3. Отдел технической поддержки

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

  1. Перейдите в раздел Телефония → Очереди вызовов. Нажмите на кнопку «Создать новую очередь».

Создание новой очереди
  1. Создаем очередь вызовов для отдела продаж (для мобильных номеров сотрудников).

Очередь для отдела продаж(мобильные)
  1. Создаем очередь вызовов для отдела продаж (для внутренних номеров сотрудников).

Очередь для отдела продаж
  1. Указываем, что если в течение 25 секунд никто из сотрудников не ответил на звонок клиента, то вызов должен направиться на мобильные номера сотрудников.

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

Очередь для отдела технической поддержки

IVR-меню

Инструкции по IVR-меню доступны по ссылке.

  1. Перейдите в раздел Телефония → IVR меню. Нажмите на кнопку «Создать новое IVR меню».

Создание нового IVR меню
  1. Указываем настройки IVR согласно нашему описанию.

IVR Menu

Входящий маршрут

Инструкции по входящим маршрутам доступны по ссылке.

  1. На последнем шаге создаем входящий маршрут вызова для нашего провайдера. В разделе Маршрутизация → Входящие маршруты добавляем новое правило.

Раздел "Входящие маршруты"
  1. Заполните данные согласно шаблону:

Новое правило обработки входящих вызовов

Настройка индивидуального нерабочего времени для учетной записи провайдера

Постановка задачи

В MikoPBX в разделе Маршрутизация → Нерабочее время настроены правила маршрутизации вызовов в нерабочее время. Данные правила распространяются на все вызовы, независимо от того на какой номер компании позвонил клиент. Необходимо для провайдера Zadarma настроить индивидуальное нерабочее время. Рабочее время для данного провайдера: с 9.00 до 18.00 по МСК.

Решение

Способ 1

  1. Перейдите в раздел Модули → Приложения диалпланов. Создайте новое приложение (диалплан Asterisk) по инструкции. Параметры приложения принимают вид:

Параметры создаваемого диалплана
  1. Программный код созданного приложения:

1,ExecIfTime(09:00-18:00,mon-fri,*,*?Goto(internal,2003,1))
n,Goto(internal,201,1)
Программный код создаваемого приложения

Команда ExecIfTime выполняет указанное приложение Asterisk, если текущее время соответствует заданной спецификации времени. Если нам позвонят с 9:00 до 18:00 в любой будний день (с понедельника по пятницу), то мы перенаправляем вызов (команда Goto) на номер 2003. 2003 - это номер IVR-меню.

Настройки в IVR меню

Иначе вызов направится сотруднику с внутренним номером 201.

  1. Настраиваем правила входящей маршрутизации для созданного провайдера. Переходим в раздел Маршрутизация → Входящие маршруты. Направляем все входящие вызовы на созданное приложение.

Настройки входящих маршрутов

Способ 2

  1. Найдите и скопируйте ID-провайдера. Чтобы это сделать - перейдите в конфигурацию необходимого провайдера. В нашем примере - это SIP-1687941868

ID провайдера
  1. Перейдите в раздел Система -> Кастомизация системных файлов

Раздел "Кастомизация системных файлов"
  1. Откройте для редактирования конфигурационный файл extensions.conf.

Конфигурационный файл "extensions.conf"
  1. Установите режим «Добавлять в конец файла». В черное окно добавьте следующий фрагмент кода:

[SIP-1687941868-incoming-custom]
exten => _.!,1,NoOp(check time)
    same => n,ExecIfTime(00:00-09:00,mon-fri,*,*?Macro(playback-exit,/offload/asterisk/sounds/other/out_work_times))
    same => n,ExecIfTime(18:00-23:59,mon-fri,*,*?Macro(playback-exit,/offload/asterisk/sounds/other/out_work_times))
    same => n,return
Код для extensions.conf

В выше приведенном фрагменте кода Вам необходимо составить правильное наименование контекста. Формат создаваемого контекста:

[ID-ПРОВАЙДЕРА-incoming-custom]
  • ID-ПРОВАЙДЕРА - значение, которое вы сохранили на втором шаге данной инструкции. В нашем примере это SIP-1687941868.

Рабочее время с 9.00 до 18.00, следовательно необходимо задать два интервала для нерабочего времени: 00:00-09:00 и 18:00-23:59.

Команда ExecIfTime

Более подробно разберём команду ExecIfTime. Эта команда выполняет указанное приложение Asterisk, если текущее время соответствует заданной спецификации времени. В нашем случае команда выполняет проигрывание звукового файла, расположенного в директории /offload/asterisk/sounds/other/out_work_times в MikoPBX. Синтаксис команды:

ExecIfTime(times,weekdays,mdays,months?appname[(appargs)])
  • times - Диапазоны времени в 24-часовом формате

  • weekdays - Дни недели (mon, tue, wed, thu, fri, sat, sun)

  • mdays - Дни месяца (1-31)

  • months - Месяцы (jan, feb, mar, apr и т. д.)

  • appname[(appargs)] - команда Asterisk с указанием параметров вызова

В нашем примере указаны диапазон времени, диапазон дней недели. Вместо указания дней месяцев и месяцев введены *. Этот символ означает «для всех остальных случаев».

ExecIfTime(00:00-08:00,mon-fri,*,*?Macro(playback-exit,/offload/asterisk/sounds/other/out_work_times))

Маршрутизация по DID номеру

Введение

При настройке входящей маршрутизации часто возникает ситуация, когда провайдер предоставляет учетную одну запись SIP для нескольких купленных номеров телефонов.

К примеру у МИКО есть номера телефонов:

  • +7(495)229-30-42

  • +7(499)638-25-84

В интерфейсе MikoPBX создана только одна учетная запись «Провайдер телефонии». Каждый номер телефона необходимо направить на свой маршрут, к примеру на различные IVR.

Тут к приходит на помощь DID номер, который провайдер может передавать при входящих звонках. Зная DID номер, можно для провайдера описать несколько входящие маршрутов, с различными DID, что позволит решить описанную выше задачу.

Как это работает

Для анализа звонков я обычно использую «приложение Sngrep». Вот пример запроса от провайдера при входящем:

INVITE sip:[email protected] SIP/2.0
Via: SIP/2.0/UDP 81.88.86.65:5060;branch=z9hG4bK1cf7.16247c44.0;cid=2
Max-Forwards: 67
Contact: <sip:81.88.86.65>
To: <sip:[email protected]>
From: "79260577653"<sip:[email protected]>;tag=5e1a5a28
Call-ID: JUm-E_ISk4DPaL8Npv2Hlw..
CSeq: 1 INVITE
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, UPDATE, UPDATE, INFO, REFER, MESSAGE
Content-Type: application/sdp
Supported: replaces
User-Agent: Softswitch3
Content-Length: 351

При получении такого пакета, MikoPBX проанализирует первую строку с ключевым словом «INVITE», значение «84996382584» и будет являться DID номером.

Возможные особенности

DID в заголовке To

На практике, не всегда все так просто. К примеру я встречал провайдера, который присылает следующий INVITE:

INVITE sip:[email protected] SIP/2.0
Via: SIP/2.0/UDP 81.88.86.65:5060;branch=z9hG4bK1cf7.16247c44.0;cid=2
Max-Forwards: 67
Contact: <sip:81.88.86.65>
To: <sip:[email protected]>
From: "79260577653"<sip:[email protected]>;tag=5e1a5a28
Call-ID: JUm-E_ISk4DPaL8Npv2Hlw..
CSeq: 1 INVITE
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, UPDATE, UPDATE, INFO, REFER, MESSAGE
Content-Type: application/sdp
Supported: replaces
User-Agent: Softswitch3
Content-Length: 351

В этом случае в строке «INVITE» описывается логин учетной записи, в вот DID уже описывается в заголовке «». Для корректной настройки достаточно в разделе Кастомизация системных файлов добавить в конец файла «extensions.conf» следующие строки:

[SIP-1622040384-incoming-custom]
exten => _[0-9*#+a-zA-Z][0-9*#+a-zA-Z]!,1,NoOp(------)
	same => n,Set(toNum=${PJSIP_PARSE_URI(${PJSIP_HEADER(read,To)},user)})
	same => n,ExecIf($["${toNum}" != "${EXTEN}"]?Goto(${CUT(CONTEXT,,1-3)},${toNum},1))
	same => n,return
  • функция «PJSIP_HEADER» считывает значение заголовка «To»

  • функция «PJSIP_PARSE_URI» получает из значения заголовка поле «user», которое соответствует значению DID

  • Goto перемещает канал в начало, для повторной инициализации маршрута

  • "1-3" - означает, что нужно взять первые три слова из "SIP-1622040384-incoming-custom", по сути, нужно из этой строки получить все до "-custom", в старых версиях АТС может потребоваться скорректировать это правило

  • SIP-1622040384 - это ID учетной записи провайдера MikoPBX, можно подсмотреть в адресной строке браузера при редактировании учетной записи

Код для решения проблемы

Замена DID на произвольный

Следующий пример удобно применять, когда провайдер не предоставляет информации по номеру, на который пришел вызов, поступает информация только о логине. При этом, важно, чтобы одному логину соответствовал один DID.

[add-trim-prefix-clid-custom]
exten => user1,1,Goto(SIP-1622040384-incoming,74952293042,1)
exten => admin,1,Goto(SIP-1622040000-incoming,74952291111,1)

exten => _[0-9*#+a-zA-Z]!,2,return
  • "user1" и "admin" - это примеры популярных логин

Установить CID на основании DID

[add-trim-prefix-clid-custom]
exten => _[0-9*#+a-zA-Z][0-9*#+a-zA-Z]!,1,NoOp(...)
	same => n,GosubIf($["${DIALPLAN_EXISTS(did-from-cid-map,${EXTEN},1)}" == "1"]?cid-from-did-map,${EXTEN},1)
	same => n,return
[cid-from-did-map]
exten => 74952293042,1,Set(CALLERID(name)=Sales)
exten => 74952291111,1,Set(CALLERID(name)=Support)

exten => _[0-9*#+a-zA-Z]!,2,return
  • Если вызов поступен на номер 74952293042, то CID (name) будет установлен в значение Sales

  • Если вызов поступен на номер 74952291111, то CID (name) будет установлен в значение Support

DID произвольном заголовке

Такое встречается при использовании сервиса roistat. Сервис при входящем может прислать следующий запрос:

INVITE sip:[email protected] SIP/2.0
Via: SIP/2.0/UDP 81.88.86.65:5060;branch=z9hG4bK1cf7.16247c44.0;cid=2
Max-Forwards: 67
Contact: <sip:81.88.86.65>
To: <sip:[email protected]>
From: "79260577653"<sip:[email protected]>;tag=5e1a5a28
Call-ID: JUm-E_ISk4DPaL8Npv2Hlw..
CSeq: 1 INVITE
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, UPDATE, UPDATE, INFO, REFER, MESSAGE
Content-Type: application/sdp
Supported: replaces
User-Agent: Softswitch3
x-roistat-phone: 84996382584
Content-Length: 351

Корректного DID нет ни в INVITE, ни в поле To, но при этом появился новый заголовок «x-roistat-phone».

Для корректной настройки достаточно в разделе Кастомизация системных файлов добавить в конец файла «extensions.conf» следующие строки:

[SIP-1622040384-incoming-custom]
exten => _[0-9*#+a-zA-Z][0-9*#+a-zA-Z]!,1,NoOp(------)
	same => n,Set(toNum=${PJSIP_HEADER(read,x-roistat-phone)})
	same => n,ExecIf($["${toNum}x" != "x" && "${toNum}" != "${EXTEN}"]?Goto(${CUT(CONTEXT,,1-3)},${toNum},1))
	same => n,return
  1. функция «PJSIP_HEADER» считывает значение заголовка «x-roistat-phone»

  2. Goto перемещает канал в начало, для повторной инициализации маршрута

Манго офис

Получение номера, на который позвонил клиент из поля «Diversion»:

[SIP-1622040384-incoming-custom]
exten => _[0-9*#+a-zA-Z][0-9*#+a-zA-Z]!,1,NoOp(------)
	same => n,Set(tmpDiversion=${PJSIP_HEADER(read,Diversion)})
	same => n,ExecIf($["x${tmpDiversion}" != "x"]?Set(toNum=${CUT(CUT(tmpDiversion,>,1),:,2)}))
	same => n,ExecIf($["${toNum}x" != "x" && "${toNum}" != "${EXTEN}"]?Goto(${CUT(CONTEXT,,1-3)},${toNum},1))
	same => n,return
	

Более универсальный вариант:

[add-trim-prefix-clid-custom]
exten => _[0-9*#+a-zA-Z][0-9*#+a-zA-Z]!,1,NoOp(------)
	same => n,Set(tmpDiversion=${PJSIP_HEADER(read,Diversion)})
	same => n,ExecIf($["x${tmpDiversion}" != "x"]?Set(toNum=${CUT(CUT(tmpDiversion,@,1),:,2)}))
	same => n,ExecIf($["${toNum}x" != "x" && "${toNum}" != "${EXTEN}"]?Goto(${contextID},${toNum},1))
	same => n,return

Novafon (zadarma)

Получение номера, на который позвонил клиент из заголовка «CALLED_DID»:

[SIP-1622040384-incoming-custom]
exten => _[0-9*#+a-zA-Z][0-9*#+a-zA-Z]!,1,NoOp(------)
	same => n,Set(toNum=${PJSIP_HEADER(read,CALLED_DID)})
	same => n,ExecIf($["${toNum}x" != "x" && "${toNum}" != "${EXTEN}"]?Goto(${CUT(CONTEXT,,1-3)},${toNum},1))
	same => n,return

Черные и белые списки

Периодически каждая компания сталкивается с проблемой поступления «спам» звонков. В связи с этим возникает потребность блокировки определенных номеров, чтобы звонки с этих номеров не поступали.

Продвинутый вариант

  1. Создайте новое «Приложение диалплан»

  2. Укажите произвольное название, к примеру Blacklist

  3. Выберите «Тип кода» - «PHP AGI Скрипт»

  4. Укажите короткий номер для приложения, к примеру 99

  5. На вкладке «Программный код» вставьте:

    <?php
    require_once('Globals.php');
    use MikoPBX\Core\Asterisk\AGI;
    
    $agi        = new AGI();
    $isTransfer = !empty($agi->get_variable('ISTRANSFER', true));
    $number     = substr($agi->request['agi_callerid'], -10);
    $cliNumber  = isset($argv[2]) && !empty($argv[2]) ? substr($argv[2], -10) : $number;
    $actionFlag = $isTransfer ? 1 : (isset($argv[1]) ? intval($argv[1]) : null);
    
    $agi->verbose('Action flag: ' . $actionFlag . ', Phone number: ' . $cliNumber, 1);
    $filename = '/storage/usbdisk1/mikopbx/custom_modules/blacklist.txt';
    if(file_exists($filename)){
        $blacklist = file($filename, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
        $isInBlacklist = in_array($cliNumber, $blacklist);
    }else{
        $isInBlacklist = false;
    }
    
    if (is_null($actionFlag) || is_null($cliNumber)) {
        if($isInBlacklist){
            $agi->verbose('The number was found in the blacklist. The call will be completed');
            $agi->hangup();
        }
        exit(0);
    }
    
    if ($actionFlag === 1) {
        if (!$isInBlacklist) {
            $agi->verbose('Adding number to black list (fileWriteContent): ' . $cliNumber, 1);
            $blacklist[] = $cliNumber;
            \MikoPBX\Core\System\Util::fileWriteContent($filename, implode(PHP_EOL, $blacklist) . PHP_EOL);
        } else {
            $agi->verbose('Number already exists in the black list: ' . $cliNumber, 1);
        }
        $filename = '/storage/usbdisk1/mikopbx/custom_modules/blacklist_add.wav';
        if(file_exists("$filename")){
            $agi->exec('Playback', \MikoPBX\Core\System\Util::trimExtensionForFile($filename));
        }
    } elseif ($actionFlag === 0) {
        if ($isInBlacklist) {
            $agi->verbose('Removing number from black list (fileWriteContent): ' . $cliNumber, 1);
            $blacklist = array_filter($blacklist, function($blacklistedNumber) use ($cliNumber) {
                return $blacklistedNumber !== $cliNumber;
            });
            \MikoPBX\Core\System\Util::fileWriteContent($filename, implode(PHP_EOL, $blacklist) . PHP_EOL);
        } else {
            $agi->verbose('Number not found in black list: ' . $cliNumber, 1);
        }
        $filename = '/storage/usbdisk1/mikopbx/custom_modules/blacklist_remove.wav';
        if(file_exists("$filename")){
            $agi->exec('Playback', \MikoPBX\Core\System\Util::trimExtensionForFile($filename));
        }
    } else {
        $agi->verbose('Invalid action flag: ' . $actionFlag . '. Use 1 to add, 0 to remove.', 1);
        exit(1);
    }
    $agi->verbose('Operation completed successfully.', 1);
  6. Сохраните изменения и скопируйте идентификатор приложения из адресной строки браузера, в этом примере "DIALPLAN-APP-1C34052A".

  7. Перейдите в раздел Система → Кастомизация системных файлов, откройте для редактирования файл extensions.conf

  8. Выберите режим «Добавлять в конец файла», внизу в черное поле для редактирования вставьте следующие строки:

    [internal-transfer](+)
    exten => _99,1,Set(__ISTRANSFER=transfer_)
     	same => n,Goto(internal,${EXTEN},1)
     
    [applications](+)
    exten => _1*X.,1,AGI(DIALPLAN-APP-1C34052A.php,1,${EXTEN:3})
    exten => _0*X.,1,AGI(DIALPLAN-APP-1C34052A.php,0,${EXTEN:3})	
     	
    [add-trim-prefix-clid-custom]
    exten => _[0-9*#+a-zA-Z][0-9*#+a-zA-Z]!,1,NoOp(start check blacklist)
    	same => n,AGI(DIALPLAN-APP-1C34052A.php)
    	same => n,Return()

    , где «DIALPLAN-APP-1C34052A» - это идентификатор приложения, найти можно в адресной строке браузера при редактирвоании приложения

  9. Сохраните изменения!

Черный список телефонов будет храниться в файле: «/storage/usbdisk1/mikopbx/custom_modules/balcklist.txt»

Также можно на АТС загрузить файлы оповещения о добавлении в черный список:

/storage/usbdisk1/mikopbx/custom_modules/blacklist_add.wav

/storage/usbdisk1/mikopbx/custom_modules/blacklist_remove.wav Для добавления номера в черный список просто выполните переадресацию на номер 99 (слепую, без консультации) Наберите 1*74950000300 для добавления номера в черный список Наберите 0*74950000300 для удаления номера из черного списка

Упрощенная реализация

Подойдет для старых версий MikoPBX

  1. Перейдите в раздел Система → Кастомизация системных файлов.

Раздел "Кастомизация системных файлов"
  1. Откройте для редактирования конфигурационный файл extensions.conf.

Редактирование конфигурационного файла "Extensions.conf"
  1. Установите режим "Добавлять в конец файла" и вставьте следующий код:

[add-trim-prefix-clid-custom]
exten => _X!,1,NoOp(...)
    ; Черный список номеров. Вызов будет завершен. 
    same => n,ExecIf($["${CALLERID(num)}" == "72942293042"]?Hangup())
    same => n,ExecIf($["${CALLERID(num)}" == "72942293043"]?Hangup())
    same => n,ExecIf($["${CALLERID(num)}" == "72942293044"]?Hangup())
    same => n,return
Код для файла "extnsions.conf"

Белый список номеров иногда требуется описать для конкретных провайдеров:

[ID-ПРОВАЙДЕРА-incoming-custom]
exten => _X!,1,NoOp(...)
    ; Белый список номеров. 
    same => n,ExecIf($["${CALLERID(num)}" == "72942291111"]?return)
    same => n,ExecIf($["${CALLERID(num)}" == "72942291112"]?return)
    same => n,ExecIf($["${CALLERID(num)}" == "72942291113"]?return)
    same => n,Hangup()
  • ID-ПРОВАЙДЕРА - значение, которое вы можете найти в адресной строке в момент конфигурации провайдера

Как найти ID провайдера:

Вывод информации о did-номере

Постановка задачи

MikoPBX может определить номер телефона, на который пришел звонок от клиента. Например, сотрудникам компании при поступлении входящего звонка от клиента необходимо понимать, на какой номер позвонил клиент. Данная информация должна выводиться при поступлении звонка от клиента и отображаться на телефоне. Номер, на который позвонил клиент, называется did-номером. Далее в инструкции рассмотрим, каким образом вывести информацию о did-номере на экране Вашего телефона.

Отображение DID-номера при внешнем входящем звонке

  1. Перейдите в раздел Маршрутизация → Провайдеры телефонии. Откройте для редактирования учетную запись провайдера для редактирования. Скопируйте в адресной строке ID провайдера, через которого абоненты звонят Вам в компанию. Обращаем Ваше внимание, что в нашем примере используется единственный провайдер. Если у Вас настроено подключение нескольких провайдеров, то ниже описанные действия необходимо выполнить для каждого провайдера. В нашем примере ID провайдера принимает вид: SIP-1687941868

ID провайдера
  1. Перейдите в раздел Система -> Кастомизация системных файлов

Раздел "Кастомизация системных файлов"
  1. Откройте для редактирования конфигурационный файл extensions.conf.

Конфигурационный файл "extensions.conf"
  1. Установите режим «Добавлять в конец файла». В черное окно добавьте следующий фрагмент кода:

[SIP-1687941868-incoming-custom]
exten => _.!,1,NoOp(from_did)
    same => n,ExecIf($[ "${FROM_DID}x" != "x" ]?Set(CALLERID(name)=${FROM_DID}))
    same => n,return
Код для extensions.conf

В выше приведенном фрагменте кода Вам необходимо составить правильное наименование контекста. Формат создаваемого контекста:

[ID-ПРОВАЙДЕРА-incoming-custom]
  • ID-ПРОВАЙДЕРА - значение, которое вы сохранили на первом шаге данной инструкции. В нашем примере это SIP-1687941868.

Добавление к did-номеру наименование линии

Помимо did-номера можно вывести наименование провайдера / линии, через которую прошел вызов. Для этого необходимо выполнить следующие действия:

  1. Перейдите в раздел Маршрутизация → Провайдеры телефонии. Откройте учетную запись провайдера для редактирования. В поле Дополнительные параметры задайте переменную с указанием наименования провайдера.

[endpoint]
set_var=MIKO_LINE_NAME=PT

В нашем примере наименование линии будет идентично наименованию провайдера - PT.

Дополнительные параметры для провайдера
  1. Перейдите в раздел Система -> Кастомизация системных файлов

Раздел "Кастомизация системных файлов"
  1. Откройте для редактирования конфигурационный файл extensions.conf.

Конфигурационный файл "extensions.conf"
  1. Установите режим «Добавлять в конец файла». В черное окно добавьте следующий фрагмент кода:

[SIP-1687941868-incoming-custom]
exten => _.!,1,NoOp(from_did)
    same => n,ExecIf($[ "${FROM_DID}x" != "x"  && "${MIKO_LINE_NAME}x" != "x" ]?Set(CALLERID(name)=${MIKO_LINE_NAME} ${FROM_DID}))
    same => n,return	
Код для extensions.conf

В выше приведенном фрагменте кода Вам необходимо составить правильное наименование контекста. Формат создаваемого контекста:

[ID-ПРОВАЙДЕРА-incoming-custom]
  • ID-ПРОВАЙДЕРА - значение, которое вы сохранили на первом шаге данной инструкции. В нашем примере это SIP-1687941868.

Нормализация входящего номера телефона

При подключении к MikoPBX более одного провайдера может сложится ситуация, что номер телефона клиентов поступает в различном формате:

  • В 7и значном виде - 2293042

  • Через «+», к пример +79257184444

  • Через «8», к примеру 89257184444

Появляется необходимость привести все к одному формату.

  1. Перейдите в раздел Маршрутизация → Провайдеры телефонии. Откройте для редактирования учетную запись провайдера для редактирования. Скопируйте в адресной строке ID провайдера, через которого абоненты звонят Вам в компанию. Обращаем Ваше внимание, что в нашем примере используется единственный провайдер. Если у Вас настроено подключение нескольких провайдеров, то ниже описанные действия необходимо выполнить для каждого провайдера.

Где найти ID провайдера

В нашем примере ID провайдера принимает вид: SIP-1687947415

  1. Перейдите в раздел Система → Кастомизация системных файлов.

Раздел "Кастомизация системных файлов"
  1. Откройте для редактирования конфигурационный файл extensions.conf.

Редактирование конфигурационного файла "extensions.conf"
  1. Выберите режим "Добавлять в конец файла". В черное окно добавьте следующий фрагмент кода:

[SIP-1687947415-incoming-custom]
exten => _.!,1,NoOp(---)
    ; Отсекаем плюс
    same => n,Set(CALLERID(num)=${REPLACE(CALLERID(num),"+")})
    ; Для 11ти значного номера отсекаем первую цифру и добавляем 7
    same => n,ExecIf($[ ${LEN(${CALLERID(num)})} == 11 ]?Set(CALLERID(num)=7${CALLERID(num):1}))
    ; Для 7ми значного номера добавляем код страны 7 и код города 495
    same => n,ExecIf($[ ${LEN(${CALLERID(num)})} == 7 ]?Set(CALLERID(num)=7495${CALLERID(num)}))
    same => n,return
; Если номер звонящего начинается с 886142 (11 значный), то отрезать код города "886142" 
exten => _.X!/_886142XXXXX,1,Set(CALLERID(num)=${CALLERID(num):5})
    same => n,return

В выше приведенном фрагменте кода Вам необходимо составить правильное наименование контекста. Формат создаваемого контекста:

[ID-ПРОВАЙДЕРА-incoming-custom]
  • ID-ПРОВАЙДЕРА - значение, которое вы сохранили на первом шаге данной инструкции. В нашем примере это SIP-1687947415.

Код для exensions.conf

Обращаем Ваше внимание, если у Вас в MikoPBX подключено несколько провайдеров, выше описанный фрагмент кода нужно составить для каждого провайдера, учитывая уникальность ID каждого из провайдеров.

Если необходимо добавить нормализацию для всех провайдеров сразу, то достаточно описать контекст «add-trim-prefix-clid-custom». Пример, все 10ти значным АОН добавить 7ку:

[add-trim-prefix-clid-custom]
exten => _.X!,1,ExecIf($[ ${LEN(${CALLERID(num)})} == 10 ]?Set(CALLERID(num)=7${CALLERID(num)}))
	same => n,return