Pull to refresh

Реализация подрузки информации о клиенте через API

Давно хотел, чтобы мои операторы выдели информацию о клиенте и знали уже перед самим входящим звонком — кто звонит. Но покупать готовые модуля за басновловные деньги не хотелось.

Вариант нашелся сам…

Так как у нас звёздочка в мир не смотрит, то очевидно что все выполняется на сервере с астериском.

Итак, нашел библиотеку PHP Tail, спасибо автору Тошио Такигучи.

Задумка такова, php грепать логи звездочки на предмет входящего звонка, смотреть номер телефона входящего звонка, далее скармливать номер, в нашем случае самописному биллингу.
Полученный ответ, то ли это инфа о клиенте, то ли что номер не найден ни в одной карточке клиента выводить на экран, приостановить выполнение до нажатия оператором кнопки Далее (для того чтобы он успел поработать с информацией).

Итак выполнение:

1. В библиотеке от Тошио Такигучи в файле Log.php необходимо заменить строку

$tail = new PHPTail("/path/to/log");

на

$tail = new PHPTail("/var/log/asterisk/full");

ну или другой адрес если у Вас лог пишется в другой файл.

2. Основные телодвижения будут происходить с файлом PHPTail.php.

В function updateLog() необходимо задать четкое понимание входящего звонка и номера телефона этого звонка.

Реализовано так:


if (value.includes('macro-user-callerid') && value.includes('Local/'+grep) && value.includes('CALLERID(name)=')) {
    var str = value.split('CALLERID(name)=');
    var num = str[1].replace(/\D+/g, '')
......
}

Далее ajax-ом передаем полученный номер телефона на другой php-файл где и происходит обращение к api биллинга.


$.ajax({
   type: "POST",
    url: "curl.php?num="+num,
    success: function(data) {
        if (data!=''){
           var res = JSON.parse(data);
           // далее работаем с полученными данными
           ...
           clearInterval(intervalID); //останавливаем и ждем действия от оператора
          }
         else {
             clearInterval(intervalID); //останавливаем и ждем действия от оператора
             // Для того чтобы оператор мог подвязать этот номер телефона к карточке клиента
          }                                          

Полный код PHPTail.php


<?php

class PHPTail {
        private $log = "";
        private $updateTime;
        private $maxSizeToLoad;
        public function __construct($log, $defaultUpdateTime = 2000, $maxSizeToLoad = 2097152) {
                $this->log = $log;
                $this->updateTime = $defaultUpdateTime;
                $this->maxSizeToLoad = $maxSizeToLoad;
        }
        public function getNewLines($lastFetchedSize, $grepKeyword, $invert) {
                clearstatcache();
                $fsize = filesize($this->log);
                $maxLength = ($fsize - $lastFetchedSize);
                if($maxLength > $this->maxSizeToLoad) {
                  return json_encode(array("size" => $fsize, "data" => array("ERROR: PHPTail attempted to load more (".round(($maxLength / 1048576), 2)."MB) then the maximum size (".round(($this->maxSizeToLoad / 1048576), 2)."MB) of bytes into memory. You should lower the defaultUpdateTime to prevent this from happening. ")));
                }
                $data = array();
                if($maxLength > 0) {
                    $fp = fopen($this->log, 'r');
                    fseek($fp, -$maxLength , SEEK_END);
                    $data = explode("\n", fread($fp, $maxLength));
                }
                if($invert == 0) {
                    $data = preg_grep("/$grepKeyword/",$data);
                }
                else {
                    $data = preg_grep("/$grepKeyword/",$data, PREG_GREP_INVERT);
                }
                if(end($data) == "") {
                    array_pop($data);
                }
                return json_encode(array("size" => $fsize, "data" => $data));
        }
        public function generateGUI() {
                ?>
                <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
                "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
                <html xmlns="http://www.w3.org/1999/xhtml">
                        <head>
                                <title>Info about called</title>
                                <link rel="shortcut icon" href="/admin/images/favicon.ico">
                                <meta http-equiv="content-type" content="text/html;charset=utf-8" />
                                <link type="text/css" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.9/themes/flick/jquery-ui.css" rel="stylesheet"></link>
                                <style type="text/css">
                                   #grepKeyword, #settings {font-size: 80%;}
                                   .float {background: #f5f5f5;z-index: 9999;border-bottom: 1px solid black;padding: 10px 0 10px 0;margin: 0px;height: 30px;width: 100%;text-align: left;}
                                </style>
                                <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
                                <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.9/jquery-ui.min.js"></script>
                                <script type="text/javascript">
                                        /* <![CDATA[ */
                                        lastSize = <?php echo filesize($this->log); ?>;
                                        grep = "";
                                        invert = 0;
                                        documentHeight = 0;
                                        scrollPosition = 0;
                                        scroll = true;
                                        $(document).ready(function(){
                                                $( "#settings" ).dialog({
                                                        modal: true,
                                                        resizable: false,
                                                        draggable: false,
                                                        autoOpen: false,
                                                        width: 590,
                                                        height: 270,
                                                        buttons: {
                                                                Close: function() {
                                                                        $( this ).dialog( "close" );
                                                                }
                                                        },
                                                        close: function(event, ui) {
                                                                grep = $("#grep").val();
                                                                invert = $('#invert input:radio:checked').val();
                                                                $("#grepspan").html("Ваш номер телефона: \"" + grep + "\"");
                                                                $("#invertspan").html("Inverted: " + (invert == 1 ? 'true' : 'false'));
                                                        }
                                                });
                                                $('#grep').keyup(function(e) {
                                                        if(e.keyCode == 13) {
                                                                $( "#settings" ).dialog('close');
                                                        }
                                                });
                                                $("#grep").focus();
                                                $("#grepKeyword").button();
                                                $("#grepKeyword").click(function(){
                                                        $( "#settings" ).dialog('open');
                                                        $("#grepKeyword").removeClass('ui-state-focus');
                                                });
                                                $(window).scroll(function(e) {
                                                    if ($(window).scrollTop() > 0) {
                                                        $('.float').css({
                                                            position: 'fixed',
                                                            top: '0',
                                                            left: 'auto'
                                                        });
                                                    } else {
                                                        $('.float').css({
                                                            position: 'static'
                                                        });
                                                    }
                                                });
                                                $(window).resize(function(){
                                                        if(scroll) {
                                                                scrollToBottom();
                                                        }
                                                });
                                                $(window).scroll(function(){
                                                        documentHeight = $(document).height();
                                                        scrollPosition = $(window).height() + $(window).scrollTop();
                                                        if(documentHeight <= scrollPosition) {
                                                            scroll = true;
                                                        }
                                                        else {
                                                            scroll = false;
                                                        }
                                                });
                                                scrollToBottom();

                                        });
                                        function scrollToBottom() {
                                            $('.ui-widget-overlay').width($(document).width());
                                            $('.ui-widget-overlay').height($(document).height());
                                            $("html, body").scrollTop($(document).height());
                                            if($( "#settings" ).dialog("isOpen")) {
                                                 $('.ui-widget-overlay').width($(document).width());
                                                 $('.ui-widget-overlay').height($(document).height());
                                                 $( "#settings" ).dialog("option", "position", "center");
                                            }
                                        }
                                        function updateLog() {
                                          $('#start').css('opacity','0.2');
                                          $('#start').css('pointer-events','none');
                                          $("#results").empty();
                                          $.getJSON('?ajax=1&lastsize='+lastSize + '&grep='+grep + '&invert='+invert, function(data) {
                                            lastSize = data.size;
                                            $.each(data.data, function(key, value) {
                                              if (value.includes('macro-user-callerid') && value.includes('Local/'+grep) && value.includes('CALLERID(name)=')) {
                                                var str = value.split('CALLERID(name)=');
                                                var num = str[1].replace(/\D+/g, '');
                                                $.ajax({
                                                  type: "POST",
                                                  url: "curl.php?num="+num,
                                                  success: function(data) {
                                                    if (data!=''){
                                                      var res = JSON.parse(data);
                                                      var text='<form><h2>Информация о входящем звонке</h2><h3><a href="'+res.contract_url+'" target="_blank" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" style="font-size:80%;"><span class="ui-button-text">Открыть в биллинге</span></a></h3><fieldset id="user-details"><label for="tel">Телефон:</label><input type="text" name="tel" value="'+num+'"/><label for="addres">Адрес:</label><input type="text" name="addres" value="'+res.adress.replace("'", "")+'"/><label for="fio">ФИО:</label><input type="text" name="fio" value="'+res.fio+'"  /><label for="lc">Счёт:</label><input type="text" name="lc" value="'+res.lc+'"  /><label for="balance">Баланс:</label><input type="text" name="balance" value="'+res.balance+'"  /></fieldset>';
                                                      text+='<div style="width: 100%;text-align: right;float: left;"><a class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" onclick=\'intervalID = setInterval("updateLog()", 1000)\'><span class="ui-button-text">Далее</span></a></div></form>';
                                                      $("#results").html(text);
                                                      clearInterval(intervalID);
                                                    }
                                                    else {
                                                      clearInterval(intervalID);
                                                      text='<form id="add_new"><h2>Информация о входящем звонке</h2> <h3 id="add_new_result">Клиент не найден</h3> <div id="add_cont"><label for="tel">Телефон:</label><input type="text" id="tel_update_tel" name="tel" value="'+num+'"/><label for="lc">Счёт:</label><input type="text" id="tel_update_lc" name="lc"/><a id="addnum_to_contract" onclick="update_num()" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only"><span class="ui-button-text">Добавить телефон к учетной записи</span></a></div><a class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" onclick=\'intervalID = setInterval("updateLog()", 1000)\'><span class="ui-button-text">Далее</span></a></form>';
                                                      $("#results").html(text);
                                                    }
                                                  }
                                                });
                                              }
                                            });
                                            if(scroll) {
                                              scrollToBottom();
                                            }
                                          });
                                        }
                                        /* ]]> */
                                </script>
                                <script type="text/javascript">
                                  function update_num(){
                                    var tel=$("#tel_update_tel").val();
                                    var lc=$("#tel_update_lc").val();
                                      $.ajax({
                                        type: "POST",
                                        url: "curl_send_phone.php?tel="+tel+"&lc="+lc,
                                        success: function(response){
                                          var res2 = JSON.parse(response);
                                          if (res2.result) {
                                            if (res2.result==true) {
                                              $("#add_cont").fadeOut();
                                              $("#add_new_result").html('Номер успешно добавлен к карточке абонента');
                                            }
                                            else {
                                              $("#add_cont").fadeOut();
                                              $("#add_new_result").html('Произошла ошибка, попробуйте позже');
                                            }
                                          }
                                        }
                                      });
                                  }
                                </script>
                                <link href='//fonts.googleapis.com/css?family=Yanone+Kaffeesatz' rel='stylesheet' type='text/css' />
                                <style>
                                  body {margin: 0 auto;background: #f5f5f5;color: #555;width: 800px;font-family: 'Yanone Kaffeesatz', arial, sans-serif;}
                                  h1 {color: #555;margin: 0 0 20px 0;}
                                  label {font-size: 20px;color: #666;}
                                  fieldset {border: none;}
                                  #user-details {float: left;width: 40%;}
                                  #requests-message {float: left;width: 45%;}
                                  #user-message {float: left;width: 100%;}
                                  textarea {width: 390px;height: 175px;}
                                  form {float: left;border: 1px solid #ddd;padding: 30px 40px 20px 40px;margin: 75px 0 0 0;width: 715px;background: #fff;-webkit-border-radius: 10px;-moz-border-radius: 10px;border-radius: 10px;background: -webkit-gradient(linear, 0% 0%, 0% 40%, from(#EEE), to(#FFF));background: -moz-linear-gradient(0% 40% 90deg,#FFF, #EEE); -webkit-box-shadow:0px 0 50px #ccc;-moz-box-shadow:0px 0 50px #ccc;box-shadow:0px 0 50px #ccc;}
                                  input, textarea {padding: 8px;margin: 4px 0 20px 0;background: #fff;width: 220px;display:block;font-size: 14px;color: #555;border: 1px #ddd solid;-webkit-box-shadow: 0px 0px 4px #aaa;-moz-box-shadow: 0px 0px 4px #aaa;box-shadow: 0px 0px 4px #aaa;-webkit-transition: background 0.3s linear;}
                                  input{width:90%}
                                  input:hover, textarea:hover {background: #eee;}
                                  #user-message>label {display: block;}
                                  </style>
                        </head>
                        <body>
                          <div id="settings" title="Введите Ваш внутренний номер телефона">
                            <input id="grep" type="text" value=""/>
                              <div id="invert" style="display:none">
                                <input type="radio" value="1" id="invert1" name="invert" /><label for="invert1">Yes</label>
                                <input type="radio" value="0" id="invert2" name="invert" checked="checked" /><label for="invert2">No</label>
                              </div>
                            </div>
                            <div class="float" >
                              <button id="grepKeyword">Внутренний номер</button>
                              <span style="display:none">Tailing file: <?php echo $this->log; ?></span>  <span id="grepspan" >Ваш номер телефона: ""</span> <span style="display:none" id="invertspan">Inverted: false</span>
                              <a class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" style="font-size:80%;float:right" onclick='intervalID = setInterval("updateLog()", 1000)' id="start"><span class="ui-button-text">Начать</span></a>
                            </div>
                            <div id="results">

                            </div>
                            <script type="text/javascript">
                              function update_num(){
                                var tel=$("#tel_update_tel").val();
                                var lc=$("#tel_update_lc").val();
                                  $.ajax({
                                    type: "POST",
                                    url: "curl_send_phone.php?tel="+tel+"&lc="+lc,
                                    success: function(response){
                                      var res2 = JSON.parse(response);
                                      if (res2.result) {
                                        if (res2.result==true) {
                                          $("#add_cont").fadeOut();
                                          $("#add_new_result").html('Номер успешно добавлен к карточке абонента');
                                        }
                                        else {
                                          $("#add_cont").fadeOut();
                                          $("#add_new_result").html('Произошла ошибка, попробуйте позже');
                                        }
                                      }
                                    }
                                  });
                              }
                            </script>
                        </body>



                </html>
                <?php
        }
}

3. Создаем файлы которые и будут отправлять запросы api
curl.php — получает инфу о клиенте


<?php
$num = $_REQUEST['num'];
if ($_REQUEST['num']!='')
{
  $url = "адрес к api";
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  curl_setopt($ch, CURLOPT_URL, $url);
  $result = curl_exec($ch);
  curl_close($ch);
  print($result);
}
 ?>

curl_send_phone.php — записывает номер телефона в карточку клиента


<?php

if ( ($_REQUEST['tel']!='') && ($_REQUEST['uid']!='') )
{
  $tel = $_REQUEST['tel'];
  $uid = $_REQUEST['uid'];

  $url = "адрес к api";
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  curl_setopt($ch, CURLOPT_URL, $url);
  $result = curl_exec($ch);
  curl_close($ch);
  print($result);
}
 ?>

4. Кладем эти 4-ре файла в /var/www/html/ (ну или в другое место, в зависимости от Вашей конфигурации Asterisk-а)

P.S. Не пишите, что мол есть AMI, оно не столь гибкое.
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.
Change theme settings