Asterisk и Openfire/Jabber: XMPP сообщение о входящем звонке с именем и отделом из Active Directory

Нужно, чтобы Asterisk при входящем звонке сотруднику, отправлял ему в Jabber сообщение о том кто звонит. В случае, если это наш сотрудник заведенный в AD, помимо номера в сообщении будет его ФИО, должность и название отдела (если эти данные введены). Стоит заметить, что астериск сам умеет слать сообщения используя JabberSend, но по некоторым причинам мне этот способ не подошел, к тому же пришлось бы все равно использовать внешний скрипт для связи с AD.

Схема работы следующая: астериск при входящем звонке запускает скрипт, которому параметрами передаем входящий и исходящий номера. Далее скрипт лезет в AD и по входящему номеру находит логин пользователя, чтобы отправить ему сообщение в jabber. По исходящему номеру скрипт вытягивает из AD всю доступную инфу, после чего формирует и отправляет сообщение.

Писать будем на php,  в системе должен быть установлен пакет php5-ldap. Для отправки xmpp сообщений нам понадобится библиотека XMPPHP, разместим её в /etc/asterisk/script/ldap/. Также нужно включить в Openfire механизм аутентификации PLAIN, у моих пользователей настроена сквозная авторизация по доменным учеткам (GSSAPPI), поэтому PLAIN был выключен и сначала отправка сообщений не срабатывала.

В домене нужно создать пользователя с правами чтения каталога, в моему случае user-for-ldap. Далее создаем файл /etc/asterisk/script/ldap/sendxmpp.php и наполняем следующим содержанием, корректируя под себя:
<?php

/* Переменные для получения параметров */
$phoneto = $argv[1];
$phonefrom = $argv[2];
$username = "";
$userdep = "";
$usertitle = "";
$userlogin="";
$xmppmessage="";

/* Вытягиваем по номеру телефона инфу из AD */
$LDAP_BINDDN = "user-for-ldap@yourdomain.local";
$LDAP_PASS = "password";
$LDAP_BASE_DN = "DC=yourdomain,DC=local";

function ConnectToServer()
{
  $LDAP_SERVER = "your-domain-contriller-ip";
  $LDAP_PORT = "389";
  $ds=ldap_connect($LDAP_SERVER, $LDAP_PORT);
  ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
  ldap_set_option($ds, LDAP_OPT_REFERRALS, 0);
  return $ds;
}

/* Ищем по первому аргументу пользователя которому отправить сообщение */

if ($phoneto != "") {

$ds=ConnectToServer();
$ldapbind = ldap_bind($ds, $LDAP_BINDDN , $LDAP_PASS);

if ($ldapbind) {
    /* Ищем среди не отключенных учетных записей по полю телефон (Пользователь AD - Свойства - Общие - Номер телефона) */ 
    $filter = "(&(telephonenumber=$phoneto)(objectClass=top)(objectCategory=person)(objectClass=user)(objectClass=person)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))";
    $sr=ldap_search($ds, $LDAP_BASE_DN, $filter, array("telephonenumber","samaccountname"));
    ldap_sort( $ds, $sr, "telephonenumber");
    $info = ldap_get_entries($ds, $sr);

    for($i=0; $i<$info["count"]; $i++) {
        $userlogin = $info[$i]["samaccountname"][0];
    }
}

} else {echo "Первая переменная пустая"."\n";}
/* Ищем по второму аргументу пользователя от которого был звонок */
if ($phonefrom != "") {
$ldapbind = ldap_bind($ds, $LDAP_BINDDN , $LDAP_PASS);
if ($ldapbind) {
   $filter = "(&(telephonenumber=$phonefrom)(objectClass=top)(objectCategory=person)(objectClass=user)(objectClass=person)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))";
   $sr=ldap_search($ds, $LDAP_BASE_DN, $filter, array("displayname", "department", "title",  "mail", "telephonenumber","samaccountname"));
   ldap_sort( $ds, $sr, "displayname");
   $info = ldap_get_entries($ds, $sr);
   for($i=0; $i<$info["count"]; $i++) {
       $username = $info[$i]["displayname"][0];
       $userdep = $info[$i]["department"][0];
       $usertitle = $info[$i]["title"][0];
    }
}
ldap_close($ds);
} else {echo "Вторая переменная пустая"."\n";}
/* Формируем сообщение для xmpp */
/* Если у сотрудника не задано имя, должность или отдел, то не отображаем соотв. заголовки */
 if ($username == "") $xmppmessage = 'Входящий звонок от '.$phonefrom;
 if ($username !== "")
 {
   if ($userdep == "" && $usertitle == "") $xmppmessage = 'Входящий звонок от '.$phonefrom."\n".'Имя: '.$username;
   elseif ($userdep == "" && $usertitle !== "") $xmppmessage = 'Входящий звонок от '.$phonefrom."\n".'Имя: '.$username."\n".'Должность: '.$usertitle;
   elseif ($usertitle == "" && $userdep !== "") $xmppmessage = 'Входящий звонок от '.$phonefrom."\n".'Имя: '.$username."\n".'Отдел: '.$userdep;
   else $xmppmessage = 'Входящий звонок от '.$phonefrom."\n".'Имя: '.$username."\n".'Должность: '.$usertitle."\n".'Отдел: '.$userdep;
 }
/* Или можно использовать способ короче */
/*
$xmppmessage = 'Входящий звонок от '.
$phonefrom."\n".
($username?'Имя '.$username."\n":'').
($usertitle?'Должность: '.$usertitle."\n":'').
($userdep?'Отдел: '.$userdep."\n":'');
*/
/* Отправляем сообщение xmpp пользователю */
include 'XMPPHP/XMPP.php';
$conn = new XMPPHP_XMPP('openfire.yourdomain.local', 5222, 'jabberuser', 'password-for-jabberuser','xmpphp','openfire.yourdomain.local', $printlog=true, $loglevel=0);
try {
  $conn->connect();
  $conn->processUntil('session_start');
  if ($conn->isDisconnected()) { echo "can't connect to jabber server"; }
  $conn->presence();
  $conn->message($userlogin.'@yourdomain.local', $xmppmessage, 'normal');
  $conn->disconnect();
  }
catch(XMPPHP_Exception $e) { die($e->getMessage()); }

/* В случае, если XMPPHP вам не подходит (версия PHP7 и выше) можно отправить сообщение через консольную sendxmpp таким образом */
$sendmessage="echo '".$xmppmessage."' | sendxmpp -t -n -j openfire.yourdomain.local:5222 -u jabberuser -p password-for-jabberuser ".$userlogin."@yourdomain.local";
shell_exec($sendmessage);
?>
Запускать из командной строки следующим образом (номер 101 входящий, 102 исходящий):
php /etc/asterisk/script/ldap/sendxmpp.php 101 102
Теперь перейдем к астеру. Находим нужный контекст, в котором у вас входящие звонки, и перед вызовом вставляем:
exten => s,n,System(php /etc/asterisk/script/ldap/sendxmpp.php ${EXTEN} ${CALLERID(num)} &)
Символ & в конце позволяет не дожидаться, пока скрипт отработает для перехода к следующим командам.

В следующей статье напишу, как настроил исходящий звонок из Miranda NG используя Asterisk AMI.
UPD 17 апреля 2019
Если вы используете PHP версии 7 и выше, то библиотека XMPP работать не будет. Внес изменения в код добавив возможность отправить XMPP сообщение через sendxmpp (apt install sendxmpp).

Комментариев нет:

Отправить комментарий