Основные пользовательские сценарии и пример
- Входящий звонок на АТС на внутренний номер конкретного пользователя должен показывать карточку звонка у сотрудника в Битрикс24 (Метод telephony.externalcall.register).
- Входящий звонок с неизвестного номера (не зарегистрированного в CRM), должен попадать в очередь обработки (список пользователей, которые должны отвечать на входящие звонки):
- Одновременная очередь: всем сотрудникам, которые не отвечают на другие звонки в данный момент, одновременно показывается карточка звонка, когда кто-то из них начинает отвечать на звонок, у остальных карточка пропадает (сначала telephony.externalcall.register для первого в очереди, затем telephony.externalcall.show для остальных).
- Последовательная очередь: каждому из сотрудников очереди, которые не отвечают на другие звонки в данный момент, показывается карточка звонка на какое-то время (3-5-7 секунд), если сотрудник не начинает отвечать на звонок, карточка у него пропадает, и звонок переводится на следующего в очереди (сначала telephony.externalcall.register для первого в очереди, затем telephony.externalcall.hide и telephony.externalcall.show для следующего).
- Входящий звонок с известного номера в виде карточки звонка отображается в Битрикс24 у менеджера, ответственного за соответствующий объект CRM. (Сначала telephony.externalcall.register с SHOW = 0, который вернет либо CREATED_LEAD в случае, если телефон не был найден в CRM и был создан новый лид, либо пару CRM_ENTITY_TYPE и CRM_ENTITY_ID с указанием найденного существующего клиента.
Одновременно возвращается CRM_ACTIVITY_ID с идентификатором нового дела в CRM, в котором будет зафиксирован звонок в дальнейшем. Зная идентификатор объекта в CRM, можно при помощи методов REST по работе с CRM получить идентификатор менеджера, который отвечает за клиента, перевести звонок на него и показать ему карточку звонка telephony.externalcall.show) - Сотрудник в Битрикс24 нажимает на номер телефона в интерфейсе CRM. Приложение инициирует исходящий звонок на указанный номер на стороне АТС (событие onexternalcallstart, сотруднику показывается карточка звонка telephony.externalcall.register).
- Звонок завершен (входящий или исходящий). Факт звонка и запись фиксируется в привязке к объекту CRM (telephony.externalcall.finish. Если на момент завершения звонка в АТС еще не готова запись разговора, то вместо telephony.externalcall.finish сначала просто скрываем карточку звонка telephony.externalcall.hide, а уже потом, когда запись готова, все-таки вызываем telephony.externalcall.finish).
- На стороне АТС произошел входящий звонок в тот момент, когда связи между АТС и Битрикс24 по каким-то причинам нет. После восстановления связи информация о произошедшем звонке фиксируется в Битрикс24 (см. 1-3, но без показа карточки звонка – последовательный вызов методов telephony.externalcall.register с параметром SHOW = 0 и telephony.externalcall.finish.)
Примечание. Чтобы запись добавлялась к звонку при сценарии обзвона, приложения должны передвать CALL_LIST_ID который им придет в событии начала звонка.
Пример:
<?php /** * Created by PhpStorm. * User: sv * Date: 01.11.16 * Time: 10:44 */ // ini_set('display_errors','Off'); // формируем url нашего скрипта для использования в ajax-запросах из интерфейса приложения $script_url = ($_SERVER['SERVER_PORT'] == 443 ? 'https' : 'http') . '://' . $_SERVER['SERVER_NAME'] . (in_array($_SERVER['SERVER_PORT'], array(80, 443)) ? '' : ':' . $_SERVER['SERVER_PORT']) . $_SERVER['SCRIPT_NAME']; $appsConfig = array(); $b24domain = $_REQUEST['DOMAIN']; // если нам пришло событие исходящего звонка, то авторизация передается через узел auth в массиве request // но нам оттуда нужен только домен, авторизацию мы уже сохранили к этому моменту if (!empty($_REQUEST['auth'])) { $b24domain = $_REQUEST['auth']['domain']; } $configFileName = '/config_' . trim(str_replace('.', '_', $b24domain)) . '.php'; echo getcwd().$configFileName."<br/>"; if (file_exists(getcwd() . $configFileName)) { include_once getcwd() . $configFileName; } else { // сохраняем токены пользователя, устанавливающего приложение $appsConfig = $_REQUEST; saveParams($appsConfig); // регистрируем событие исходящего звонка restCommand('event.bind', array( "event" => 'ONEXTERNALCALLSTART', "handler" => $script_url."?action=outcoming", ), $b24domain, $appsConfig['AUTH_ID']); /* тестовое событие для проверки механизма restCommand('event.bind', array( "event" => 'ONAPPTEST', "handler" => $script_url."?action=test", ), $b24domain, $appsConfig['AUTH_ID']); */ } $action = $_REQUEST['action']; // мы просто запустили приложение в интерфейсе Битрикс24 if ($action == '') { ?> <html> <head> <meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> <!-- Latest compiled and minified CSS --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> <!-- Optional theme --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous"> <!-- Latest compiled and minified JavaScript --> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script> <script src="//api.bitrix24.com/api/v1/"></script> </head> <body> <div class="form-group"> <label for="IncomingNumber">Incoming call number</label> <input type="text" class="form-control" id="incomingNumber" placeholder="phone"> </div> <div class="form-group"> <label for="user1">User 1</label> <input type="text" class="form-control" id="user1" placeholder="user id" value="1"> </div> <div class="form-group"> <label for="user2">User 2 (for call transfer)</label> <input type="text" class="form-control" id="user2" placeholder="user id"> </div> <a class="btn btn-default" href="#" role="button" id="incoming">Incoming</a> <a class="btn btn-default" href="#" role="button" id="redirect">Redirect</a> <a class="btn btn-default" href="#" role="button" id="drop">Drop</a> <a class="btn btn-default" href="#" role="button" id="test">Event test</a> <div id="debug"></div> <? // если любопытно, можно посмотреть, какие параметры авторизации передает Битрикс24 скрипту приложения // в случае выполнения приложения во фрейме внутри Битрикс24 //echo "<pre>"; //print_r($_REQUEST); //echo "</pre>"; ?> <script> $( "#incoming" ).on( "click", function( event ) { // здесь мы имитируем работу внешней АТС, в частности, получение входящего звонка // поэтому AJAX, передача параметров авторизации и т.д. // в реальной практике, REST телефонии будет вызываться со стороны АТС, а там мы уже сохранили // авторизационные токены (см. $appsConfig$appsConfig) и сами знаем, на какой Битрикс24 отправлять // вызов REST, каким пользователям показывать карточку и т.д. auth = BX24.getAuth(); $.ajax({ url: "<?=$script_url?>", data: { action: 'incoming', user1: $( "#user1" ).val(), phone: $( "#incomingNumber" ).val(), DOMAIN: auth['domain'] }, success: function( result ) { $( "#debug" ).html( result ); } }); }); $( "#redirect" ).on( "click", function( event ) { auth = BX24.getAuth(); $.ajax({ url: "<?=$script_url?>", data: { action: 'redirect', user1: $( "#user1" ).val(), user2: $( "#user2" ).val(), DOMAIN: auth['domain'] }, success: function( result ) { $( "#debug" ).html( result ); } }); }); $( "#drop" ).on( "click", function( event ) { auth = BX24.getAuth(); $.ajax({ url: "<?=$script_url?>", data: { action: 'drop', user1: $( "#user1" ).val(), user2: $( "#user2" ).val(), DOMAIN: auth['domain'] }, success: function( result ) { $( "#debug" ).html( result ); } }); }); /* инициация тестового события на стороне серверного скрипта, ничего важного $( "#test" ).on( "click", function( event ) { auth = BX24.getAuth(); $.ajax({ url: "<?=$script_url?>", data: { action: 'eventtest', DOMAIN: auth['domain'] }, success: function( result ) { $( "#debug" ).html( result ); } }); }); */ </script> </body> </html> <? } else { switch ($action) { case 'test': writeToLog(array('test' => $_REQUEST), 'telephony test event'); break; case 'outcoming': writeToLog(array('outcoming' => $_REQUEST), 'telephony event'); $result = restCommand('telephony.externalCall.register', array( "USER_ID" => $_REQUEST['data']['USER_ID'], "PHONE_NUMBER" => $_REQUEST['data']['PHONE_NUMBER'], "TYPE" => '1', "CRM_CREATE" => 1 ), $b24domain, $appsConfig['AUTH_ID']); $appsConfig['CALL'] = $result['result']; saveParams($appsConfig); break; case 'eventtest': writeToLog(array('eventtest' => $_REQUEST), 'test event call'); $result = restCommand('event.test', array( ), $b24domain, $appsConfig['AUTH_ID']); echo "test event call"; break; case 'incoming': $result = restCommand('telephony.externalCall.register', array( "USER_ID" => $_REQUEST['user1'], "PHONE_NUMBER" => $_REQUEST['phone'], "TYPE" => '2', "CRM_CREATE" => true ), $b24domain, $appsConfig['AUTH_ID']); $appsConfig['CALL'] = $result['result']; saveParams($appsConfig); echo "incoming <pre>"; print_r($appsConfig); echo "</pre>"; break; case 'redirect': echo "redirect <pre>"; print_r($appsConfig); echo "</pre>"; if ($appsConfig['CALL']['CALL_ID'] != '') { $result = restCommand('telephony.externalCall.hide', array( "CALL_ID" => $appsConfig['CALL']['CALL_ID'], "USER_ID" => $_REQUEST['user1'] ), $b24domain, $appsConfig['AUTH_ID']); $result = restCommand('telephony.externalCall.show', array( "CALL_ID" => $appsConfig['CALL']['CALL_ID'], "USER_ID" => $_REQUEST['user2'] ), $b24domain, $appsConfig['AUTH_ID']); } echo "redirected to ".$_REQUEST['user2']; break; case 'drop': writeToLog(array('config' => $appsConfig), 'call is finishing'); if ($appsConfig['CALL']['CALL_ID'] != '') { $result = restCommand('telephony.externalCall.finish', array( "CALL_ID" => $appsConfig['CALL']['CALL_ID'], "USER_ID" => $_REQUEST['user1'], "DURATION" => '120', "STATUS_CODE" => '200', "ADD_TO_CHAT" => true ), $b24domain, $appsConfig['AUTH_ID']); $appsConfig['CALL'] = $result['result']; saveParams($appsConfig); echo "finished <pre>"; print_r($appsConfig); echo "</pre>"; writeToLog(array('request' => $_REQUEST, 'config' => $appsConfig), 'call is finished'); } echo "dropped and saved"; break; } } /** * Save application configuration. * * @param $params * * @return bool */ function saveParams($params) { $config = "<?php\n"; $config .= "\$appsConfig = " . var_export($params, true) . ";\n"; $config .= "?>"; $configFileName = '/config_' . trim(str_replace('.', '_', $_REQUEST['DOMAIN'])) . '.php'; file_put_contents(getcwd() . $configFileName, $config); return true; } /** * Send rest query to Bitrix24. * * @param $method - Rest method, ex: methods * @param array $params - Method params, ex: array() * @param array $auth - Authorize data, ex: array('domain' => 'https://test.bitrix24.com', 'access_token' => '7inpwszbuu8vnwr5jmabqa467rqur7u6') * * @return mixed */ function restCommand($method, array $params = array(), $auth_domain, $access_token) { $queryUrl = 'https://' . $auth_domain . '/rest/' . $method; $queryData = http_build_query(array_merge($params, array('auth' => $access_token))); writeToLog(array('URL' => $queryUrl, 'PARAMS' => array_merge($params, array("auth" => $access_token))), 'telephony send data'); $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_SSL_VERIFYPEER => 0, CURLOPT_POST => 1, CURLOPT_HEADER => 0, CURLOPT_RETURNTRANSFER => 1, CURLOPT_URL => $queryUrl, CURLOPT_POSTFIELDS => $queryData, CURLOPT_VERBOSE => 1 )); $result = curl_exec($curl); writeToLog(array('raw' => $result), 'telephony got data'); curl_close($curl); $result = json_decode($result, 1); return $result; } /** * Write data to log file. * * @param mixed $data * @param string $title * * @return bool */ function writeToLog($data, $title = '') { $log = "\n------------------------\n"; $log .= date("Y.m.d G:i:s") . "\n"; $log .= (strlen($title) > 0 ? $title : 'DEBUG') . "\n"; $log .= print_r($data, 1); $log .= "\n------------------------\n"; file_put_contents(getcwd() . '/tel.log', $log, FILE_APPEND); return true; } ?>
© «Битрикс», 2001-2024, «1С-Битрикс», 2024