Звонки внутри организации с Корпоративного портала

в 11:57, , рубрики: 1c-bitrix, 1С-Битрикс, asterisk, метки: ,

Звонки внутри организации с Корпоративного портала
Многие организации используют массу разнообразных информационных систем и технических решений для обеспечения и облегчения своей работы. Рано или поздно встает вопрос об интеграции этих систем и решений, и нередко выбор «связующего звена» принимается в пользу веб-технологий. В такой момент перед веб-программистом возникает необходимость всеми этими доселе незнакомыми продуктами и решениями овладеть.

В данной статье я опишу процесс интеграции:

на примере создания системы звонков с точки зрения веб-программиста.


В первую очередь, конечно, у вас должны быть:

  1. Настроенная система телефонов внутри организации
  2. Доступные для подключения Asterisk и его веб-сервер
  3. Сведения о номерах телефонов
  4. Корпоративный портал (впрочем, только в данном примере. Решение можно использовать на любом движке аналогичной функциональности)

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

Мы будем использовать следующие элементы:

  1. Отдельную таблицу MySQL с логинами и номерами сотрудников. Данные будут выгружены из AD и импортированы с минимальными трудозатратами. В принципе, можно обращаться и к таблице пользователей Портала, но во-первых, это не приветствуется разработчиками Битрикса, а во-вторых — в нашей — как, думаю, и во многих других — организации телефонный номер может быть не только персональным, поэтому привязка только к одному пользователю нерациональна. Кроме того, мы отдельно изготовили гаджет для рабочего стола Портала, который позволяет мгновенно изменить свой внутренний номер в системе звонков, что позволяет специалистам Координационного центра легко звонить из своего профиля с любого физического рабочего места.
    Пример записи в таблице `phones`:

    id user number
    238 LutovVO 50512

  2. PHP-файл, непосредственно передающий параметры Asterisk-серверу с помощью библиотеки CURL и обрабатывающий возвращаемые значения
    call.php

    <?
    // Запрашиваем только служебные функции без вывода
    require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php");
    
    $USER = new CUser;
    $userlogin = $USER->GetLogin();
    
    // Получаем номер пользователя из внутренней базы
    $results = $DB->Query("SELECT `number` FROM `phones` WHERE `user`='".$userlogin."' LIMIT 1");
    $userphone = $results->Fetch();
    	
    if (!empty($_POST['call']))
    {
    	// Удаляем посторонныие символы из номера
    	$recipient = str_replace(' ', '', $_POST['recipient']);
    	$recipient = str_replace('+', '', $recipient);
    	$recipient = str_replace('-', '', $recipient);
    	$recipient = str_replace('(', '', $recipient);
    	$recipient = str_replace(')', '', $recipient);
    	
    	$answer = '';
    
    	// Cобираем запросы к Asterisk
    	$command = array();
    	$command[1] = 'action=login&username=PORTAL&secret=PASSWORD&events=off';
    	$command[2] = 'action=originate&channel=local/'.$userphone['number'].'@PORTAL&context=redirportal&exten='.$recipient.'&priority=1&CallerID=PORTAL';
    	$command[3] = 'action=logoff';
    	
    	// Открываем соединения с помощью библиотеки CURL
    	$curl = curl_init();
    	 
    	foreach($command as $key => $data)
    	{
    		// Храним переменную сеанса связи, без нее наши команды не заработают
    		$mansession = $_COOKIE['mansession_id'];
    		$cookie = 'mansession_id="'.$mansession.'"';
    	
    		// Задаем адрес веб-сервера Asterisk
    		curl_setopt($curl, CURLOPT_URL, 'http://127.0.0.1:8088/rawman');
    		 
    		// Включаем вывод заголовков
    		curl_setopt($curl, CURLOPT_HEADER, 1);
    		 
    		// Передаем данные методом POST
    		curl_setopt($curl, CURLOPT_POST, 1);
    		
    		// Активируем поддержку cookie
    		curl_setopt($curl, CURLOPT_COOKIE, $cookie);
    		 
    		// CURL вернет ответ, а не выведет в браузер (на время отладки можно отключить)
    		curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    		 
    		// Передаваемые переменные
    		curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
    		 
    		$res = curl_exec($curl);
    		 
    		// Если произошла ошибка, то получаем ее номер и сообщение
    		if(!$res)
    		{
    			$error = curl_error($curl).'('.curl_errno($curl).')';
    			echo $error;
    		}
    		// Если все в порядке, сохраним результат
    		else
    		{
    			// Вырежем и сохраним из заголовков ответа значение переменной сессии
    			preg_match('/mansession_id="(.*)";/', $res, $cut);
    			$_COOKIE['mansession_id'] = $cut[1];
    			
    			// Простой вывод для отладки
    			$tech_answer .= '<h2>Запрос '.$key.': '.$data.'</h2>'.'<p><b>Ответ:</b></p>'.nl2br($res).'<br/><hr><br/>';
    			$answer = '<p style="color:green;">Осуществляется звонок</p>';
    		}		
    	}
    	
    	curl_close($curl);
    	die('ok');
    }
    else 
    {
    	die('not_ok');
    }
    ?>
    

  3. JavaScript-файл, позволяющий звонить с помощью технологии AJAX без перезагрузки страницы. На 90% он состоит из создания небезызвестного объекта XMLHTTPRequest и его оберток, так что, если вы уже используете реализацию этого объекта из какой-нибудь js-библиотеки, все может быть даже компактнее
    script.js
    function createRequestObject() 
    {
      if (typeof XMLHttpRequest === 'undefined') 
      {
        XMLHttpRequest = function() 
    	{
          try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); }
            catch(e) {}
          try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); }
            catch(e) {}
          try { return new ActiveXObject("Msxml2.XMLHTTP"); }
            catch(e) {}
          try { return new ActiveXObject("Microsoft.XMLHTTP"); }
            catch(e) {}
          throw new Error("This browser does not support XMLHttpRequest.");
        };
      }
      return new XMLHttpRequest();
    }
    
    function ajax_submit(params, path) 
    {
    	var req;
    
    	req = createRequestObject();
    		
    	req.open('POST', path, true); 
    		
    	req.timeout=5000;
    		
    	req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    		
    	req.onreadystatechange = function() 
    	{  
    		if (req.readyState == 4) 
    		{
    			if(req.status == 200) 
    			{ 
    				// alert("Ответ сервера: "+req.responseText);
    				if (req.responseText=='ok')
    				{
    					// alert('Получилось!');
    				}
    				else 
    				{
    					// alert('Не получилось!');
    				}
    			}
    			else 
    			{
    				// alert('Нет связи');
    			}
    		}
    	}
    	req.send(params);
    }
    
    function call_to (number)
    {
    	var params = 'call=1&recipient='+number;
    	var path = '/services/telephony/call/';
    	ajax_submit(params, path)
    }
    

  4. Вызов функции в необходимых шаблонах или на страницах Битрикса
    <span class="link" onclick="call_to('50512')">Позвонить</span> Лютову
    

В общем-то, это все, что нужно.
Алгоритм действий сотрудника, желающего позвонить, таков:

  1. Проверить на Рабочем столе Портала, зарегистрирован ли его номер в сети (для большинства номер уже записан, перерегистрироваться приходится только новым или переезжающим сотрудникам, так что, это действие необходимо выполнить, обычно, не больше одного раза)
  2. Найти целевой номер через поиск, структуру компании или телефонный справочник
  3. Кликнуть по номеру

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

Автор: lutov

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js