Возможности

Телефония в amoCRM - это интеграция amoCRM со сторонней компанией, предоставляющей услугу виртуальной телефонии, посредством виджетов.

Суть интеграции amoCRM и виртуальной АТС заключается в том, что по определенным событиям происходит обмен данными. Таких событий несколько, из них формируются возможности, дальше мы рассмотрим каждую возможность в подробности и приведём примеры их реализации.

Click 2 call

При работе пользователя в amoCRM, можно обеспечить вызов какой-либо функции, при нажатии на номер телефона или e- mail адрес контакта.

Пример работы click 2 call

Данная возможность реализуется готовой функцией add_action().

Параметры функции add_action()

Параметр Описание
type Тип передаваемого параметра, может быть: “email”, “phone”
action Функция, которая будет вызываться при нажатии на номер телефона или email адрес

Рассмотрим пример использования функции add_action(), поместив её в функцию обратного вызова init, объекта callbacks структуры script.js. Подробнее о структуре script.js читайте здесь.

Пример

  1. /* script.js */
  2. init: function(){
  3.     self.add_action('phone', function(data){
  4.         self.crm_post (
  5.           'http://127.0.0.1/file.php',
  6.           {
  7.               call_to: data.value
  8.           },
  9.           function(msg){
  10.               alert('Данные отправлены');
  11.           },
  12.           'text',
  13.           function(){
  14.             alert ('Error');
  15.           }
  16.         );
  17.     });
  18. }

Важно помнить, что необходимо объявить область подключения виджета в manifest.json. Для выполнения функции add_action(), нужно задать области видимости, где есть отображённые номера телефонов или email адреса. Либо задать ограниченный спектр областей срабатывания, на ваше усмотрение, подробнее об областях подключения читайте здесь. В примере заданы все области, где встречаются номера телефонов и email адреса.

Пример

  1. /* manifest.json */
  2. "locations":[
  3.   "ccard-1",
  4.   "clist-1",
  5.   "lcard-1",
  6.   "llist-1",
  7.   "cucard-1",
  8.   "culist-1",
  9.   "comcard-1"
  10. ]

Для того, чтобы изменить надпись на кнопке, вызываемой во время нажатия на номер телефона или email адрес, необходимо в директории i18n структуры вашего виджета, внести соответствующие изменения в файле локализации *.json, так, как указано в примере ниже. Если параметр “call_action” не задан, по умолчанию в надпись на кнопке будет подставлено имя вашего виджета, являющееся обязательным параметром в manifest.json. Значение “call_action” будет подставлено в кнопку автоматически, при инициализации виджета.

Пример

  1. /* ru.json */
  2. {
  3.   "widget": {
  4.   "call_action": "Позвонить"
  5.   }
  6. }

Карточка входящего звонка

В системе amoCRM реализована возможность выводить в правом нижнем углу окошко с уведомлением. Как пример использования можно назвать уведомление о входящем звонке вызываемой телефонией.

Непосредственно в момент поступления звонка на телефон сотрудника, виртуальная АТС имеет возможность запросить через API amoCRM информацию о звонящем контакте и передать ее сотруднику.

Для осуществления поиска необходимо использовать метод contacts/list, передавая в поле query телефонный номер. При этом, как и все методы API, данный метод вызывается из-под авторизованного пользователя, а соответственно учитываются права пользователя на доступ к контактам. Т.е. для определения номера данный контакт должен быть в базе amoCRM и у соответствующего пользователя должны быть права на просмотр нужной карточки контакта.

Обязательно нужно ставить минимальный timeout на отработку запроса, т.к. иначе, в случае деградации связи между АТС и amoCRM, возможны проблемы со звонками.

Для доставки информации о входящем звонке до JS-скрипта на стороне клиента обычно используются технологии web- sockets, когда между клиентом и сервером устанавливается постоянное соединение и подписка на события. Можно использовать технологию периодических обращений через JS на сторонний сервер. Для этого раз в несколько секунд на стороне клиента подгружается JS-файл с целевого сервера, где определяется массив с состоянием канала (есть вызов, нет вызова для конкретного внутреннего телефона сотрудника).

Выбор метода зависит от технической возможности на стороне виртуальной АТС поддерживать web-sockets соединение. При этом необходимо учитывать внутренние номера сотрудников и их соответствие авторизованным в amoCRM пользователям, просматривающим интерфейс.

Пример карточки входящего звонка

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

Пример

  1. /* script.js */
  2.  self.add_call_notify = function(data){
  3.         var w_name = self.i18n('widget').name,
  4.         date_now = Math.ceil(Date.now()/1000),
  5.         lang = self.i18n('settings'),
  6.         n_data = {
  7.             from: data.from,
  8.             to: data.to,
  9.             duration: data.duration,
  10.             link: data.link,
  11.             text: w_name + ': ' + data.text,
  12.             date: date_now,
  13.           element: data.element
  14.         };
  15.  /* Делаем проверку, существует ли ID контакта, совершающего входящий вызов */
  16.         if (n_data.element.id > 0){     //Если ID существует, формируем ссылку на данный контакт в amoCRM
  17.        text = 'Вам звонит: '+n_data.element.name+'</br><a href="/contacts/detail/'+ n_data.element.id+'"> Перейти в карту
  18. контакта</a>';
  19.        n_data.text = text;
  20.        n_data.from = data.from;
  21.          if (n_data.from.length < 4){   //Проверка на внутренний номер
  22.             n_data.header = 'Внутренний номер: '+data.from+'';
  23.            }
  24.               else {
  25.                 n_data.header = 'Входящий вызов: '+data.from+'';
  26.                     }
  27.       }
  28.  AMOCRM.notifications.add_call(n_data);
  29.  };
  30.  /* Далее данные, имитирующие поступающую информацию  */
  31.     var notify_data={};
  32.     notify_data.from = '+7 (999) 111 22 33';
  33.     notify_data.to = 'Смирнов Алексей';
  34.     notify_data.element = { id: 1003619, type: "contact" };
  35.     self.add_call_notify(notify_data);

Параметр text является обязательным для передачи в функцию add_call, при этом, в случае наличия в нём ссылки, она должна удовлетворять регулярному выражению:(.*href=.*[\?\&]phone=)(.*?)([\&\'\"].*)

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

Пример

  1. /* script.js */
  2. var notifications_data = {};
  3. $.get('//'+window.location.host+'/private/api/contact_search.php?SEARCH='+ /*номер телефона*/ , function(res){
  4.     notifications_data.id = $(res).find('contact > id').eq(0).text();
  5.     notifications_data.name = $(res).find('contact > name').eq(0).text();
  6.     notifications_data.company = $(res).find('contact > company > name').eq(0).text();
  7.     });

Важно помнить, что необходимо объявить область подключения виджета в manifest.json. Для выполнения функции карточки входящего звонка, рекомендуется задать область everywhere. Определив тем самым, что ваш виджет будет срабатывать в любой области amoCRM, это позволит получать уведомления о входящем звонке вне зависимости от того, какую работу выполняет пользователь в amoCRM. Подробнее об областях подключения читайте здесь.

Пример

  1. /* manifest.json */
  2. "locations":[
  3.                 "everywhere"
  4.             ]

Так же можно вывести информацию о совершённом звонке, передав входящие данные:

Пример

  1. /* script.js, изменённые входные данные */
  2. var notify_data={};
  3. notify_data.from = 'Петрова Анна';
  4. notify_data.to = 'Смирнов Алексей';
  5. notify_data.element = { id: 1003619, type: "contact" };
  6. notify_data .duration = 60,
  7. notify_data.link = 'https://example.com/dialog.mp3';
  8. notify_data.text = 'Widget text';

Пример изменённых входных данных

Создание карточки контакта

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

Пример уведомления

Для реализации этой возможности необходимо внести изменения в метод, описанный в «Карточке входящего контакта», смотреть здесь.

Пример

  1. self.add_call_notify = function(data){
  2.         var w_name = self.i18n('widget').name,
  3.             date_now = Math.ceil(Date.now()/1000),
  4.             lang = self.i18n('notifications'),
  5.             text,
  6.             n_data = {
  7.                 to: data.to,
  8.                 duration: data.duration,
  9.                 date: date_now,
  10.                 n_data.element = data.element
  11.             };
  12.       /* Делаем проверку, существует ли ID контакта, совершающего входящий вызов */
  13.      if (n_data.element.id > 0){  //Если ID существует, формируем ссылку на данный контакт в amoCRM
  14.        text = 'Вам звонит: '+n_data.element.name+'<a href="/contacts/detail/'+ n_data.element.id+'"> Перейти в карту
  15. контакта</a>';
  16.        n_data.text = text;
  17.        n_data.from = data.from;
  18.          if (n_data.from.length < 4){   //Проверка на внутренний номер
  19.               n_data.header = 'Внутренний номер: '+data.from+'';
  20.            }
  21.            else {
  22.                 n_data.header = 'Входящий вызов: '+data.from+'';
  23.                 }
  24.      }
  25.           else {  //Если ID не существует, формируем ссылку на создание нового контакта
  26.             text = '<a href="/contacts/add/?phone='+ data.from+'">Создать контакт</a>';
  27.             n_data.text = text;
  28.             n_data.header = 'Входящий вызов '+ data.from+'';
  29.       //Обратите внимание, в случае создания нового контакта, n_data.from не заполняется!
  30.           }
  31.     AMOCRM.notifications.add_call(n_data);
  32. };
  33.    /* Далее данные, имитирующие поступающую информацию */
  34.     var notify_data={};
  35.     notify_data.from = '+7 (998) 444 55 66';
  36.     notify_data.to = 'User Name';
  37.     self.add_call_notify(notify_data);

Умная переадресация

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

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

Пример

  1. $phone_number = /* Номер телефона входящего вызова */;
  2. $subdomain = /* Ваш аккаунт — поддомен */;
  3. $link='https://'.$subdomain.'.amocrm.ru/private/api/v2/json/contacts/list?query='.$phone_number;  //Запрос к API на поиск
  4. карточки
  5. контакта
  6. $curl=curl_init(); #Сохраняем дескриптор сеанса cURL
  7. #Устанавливаем необходимые опции для сеанса cURL
  8. curl_setopt($curl,CURLOPT_RETURNTRANSFER,true);
  9. curl_setopt($curl,CURLOPT_USERAGENT,'amoCRM-API-client/1.0');
  10. curl_setopt($curl,CURLOPT_URL,$link);
  11. curl_setopt($curl,CURLOPT_HEADER,false);
  12. curl_setopt($curl,CURLOPT_COOKIEFILE,dirname(__FILE__).'/cookie.txt');
  13. curl_setopt($curl,CURLOPT_COOKIEJAR,dirname(__FILE__).'/cookie.txt');
  14. curl_setopt($curl,CURLOPT_SSL_VERIFYPEER,0);
  15. curl_setopt($curl,CURLOPT_SSL_VERIFYHOST,0);
  16. $out=curl_exec($curl); #Инициируем запрос к API и сохраняем ответ в переменную
  17. $code=curl_getinfo($curl,CURLINFO_HTTP_CODE);
  18. curl_close($curl);
  19. $Response=json_decode($out,true);
  20.         /* Из ответа, на запрос карточки пользователя,  получаем ID ответственного пользователя */
  21.        $responsible_user_id = $Response['response']['contacts'][0]['responsible_user_id'];

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

Результат звонка

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

Пример результата звонка

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

Пример

  1. define(['jquery', 'lib/components/base/modal'], function($, Modal){
  2.     /* Здесь скрипт вашего виджета */
  3. });

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

Пример

  1. setTimeout(self.call_result,30000); //устанавливаем задержку вызова функции результата звонка
  2. this.call_result = function() {
  3. /* Составляем разметку формы вводы данных, которая будет отображаться в модальном окне */
  4.     var data = [];
  5.   data.push('<style type="text/css" style="display: none">'+
  6.     'input[type="text"] {'+
  7.       'border: 1px solid #696969;'+
  8.       'border-radius: 3px;'+
  9.       '-webkit-border-radius: 3px; //закругление углов (Google Chrome)'+
  10.       '-moz-border-radius: 3px; //закругление углов (FireFox)'+
  11.       'margin: 2px;'+
  12.       'padding: 2px'+
  13.     '}'+
  14.     'input[type=submit] {'+
  15.       'background-color: #20B2AA;'+
  16.       'border: 1px #008B8B;'+
  17.       'border-radius: 3px;'+
  18.       'padding: 3px'+
  19.     '}'+
  20.   '</style>'+
  21.   '<form method="post" name="lead_data" id="call_result_data">'+
  22.     '<label for="inputs">Результат звонка +7(999)888-77-66</label><br><br>' +
  23.       '<div id="inputs">'+
  24.           '<input id="contact" type="text" name="contact_name" placeholder="Имя контакта"><br><br>'+
  25.         '<input id="lead" type="text" name="lead_name" placeholder="Название сделки"><br><br>'+
  26.         '<input id="lead_note" type="text" name="note" placeholder="Примечание"><br><br>'+
  27.         '<label for="lead_task">Тип задачи</label><br>'+
  28.           '<select name="task_type">'+
  29.             '<option value=1>Связаться с клинетом</option>'+
  30.             '<option value=2>Звонок</option>'+
  31.             '<option value=3>Встреча</option>'+
  32.             '<option value=4>Письмо</option>'+
  33.           '</select><br><br>'+
  34.         '<label for="lead_task_text">Поставить задачу</label><br>'+
  35.         '<input id="lead_task_text" type="text" name="text" placeholder="Комментарий к задаче"><br><br>'+
  36.       '</div>'+
  37.     '<input type="submit" value="Сохранить">'+
  38.   '</form>');
  39.   modal = new Modal({
  40.     class_name: 'modal-window',
  41.     init: function ($modal_body) {
  42.       $modal_body
  43.       .trigger('modal:loaded') //запускает отображение модального окна
  44.       .html(data)
  45.       .trigger('modal:centrify')  //настраивает модальное окно
  46.       .append('<span class="modal-body__close">Отмена</span>');
  47.     },
  48.     destroy: function () {
  49.     }
  50.   });
  51.   $('#call_result_data input[type="submit"]').click(function(e) {
  52.     e.preventDefault();
  53.     var data;   // переменная, которая будет содержать данные серилизации
  54.     data = $(this).parent('form').serializeArray();
  55.     setTimeout('$(".modal-body__close").trigger("click")',1000);
  56.       if(data[1]['value'] != ""){
  57.         var lead_data = [];
  58.                     lead_data = {
  59.                         "request":  {
  60.                             "leads":  {
  61.                                 "add":  [{
  62.                                     "name":data[1]['value']
  63.                                 }]
  64.                             }
  65.                         }
  66.                     };
  67.                 $.post('https://cnst.amocrm.ru/private/api/v2/json/leads/set', lead_data, function(response) {
  68.               var lead_id = response.response.leads.add[0].id;    
  69.                       if(lead_id != 0) {
  70.                         if(data[0]['value'] != ""){
  71.                                 var contact_data = [],
  72.                                 task_data = [],
  73.                                 note_data = [];
  74.                                 contact_data  = {
  75.                                     "request":  {
  76.                                         "contacts":  {
  77.                                             "add":  [{
  78.                                                 "name":data[0]['value'],
  79.                                             "linked_leads_id": lead_id
  80.                                         }]
  81.                                     }
  82.                                 }
  83.                             };
  84.                         $.post('https://cnst.amocrm.ru/private/api/v2/json/contacts/set', contact_data, function(response)
  85. {
  86.                           var contact_id = response.response.contacts.add[0].id;
  87.                     }, 'json');}
  88.                     if(data[3]['value'] != ""){
  89.                             task_data = {
  90.                                 "request":  {
  91.                                     "tasks":  {
  92.                                         "add":  [{
  93.                                             "element_id":  lead_id,
  94.                                             "element_type":  2,
  95.                                             "task_type": data[3]['value'],
  96.                                             "text":  data[4]['value']
  97.                                         }]
  98.                                     }
  99.                                 }
  100.                             };
  101.                     $.post('https://cnst.amocrm.ru/private/api/v2/json/tasks/set', task_data, function(response) {},
  102. 'json');}
  103.                         if(data[2]['value'] != ""){
  104.                                 note_data = {
  105.                                     "request":  {
  106.                                         "notes":  {
  107.                                             "add":  [{
  108.                                                 "element_id":  lead_id,
  109.                                                 "element_type":  2,
  110.                                                 "note_type":  4,
  111.                                                 "text":  data[2]['value']
  112.                                             }]
  113.                                         }
  114.                                     }
  115.                                 };
  116.                         $.post('https://cnst.amocrm.ru/private/api/v2/json/notes/set', note_data, function(response) {},
  117. 'json');}
  118.                         }
  119.                 }, 'json');
  120.       }
  121.   });
  122. };

Логирование звонка

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

  • через метод notes (Добавление событий)
  • через метод calls/add (Добавление звонков)

Более простым является добавление звонка как примечания. Для этого не требуется специальный ключ сервиса. Однако, для добавление звонка через notes необходимо обязательно передавать element_id карточки контакта, метод "calls/add этого параметра не требует, совершая поиск карточки контакта самостоятельно.

Для добавления записей в события необходимо использовать метод calls/add. При этом события добавляются только к уже существующему и найденному по номеру телефона контакту. Поэтому мы помечаем в базе отправленные и не отправленные записи звонков и не отправленные (карточки по которым еще не были созданы) еще раз пытаемся добавить в течение 18 часов. Если, через 18 часов, карточка контакта не будет создана, то звонок не будет занесён в систему.

Результат добавления звонков, отображаемый в карточке контакта

Сообщение об ошибке

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

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

Пример сообщения об ошибке

Параметры

Параметр Тип Описание
header string Имя виджета будет отображаться в заголовке
text string Сообщение об ошибке
date timestamp Дата

callbacks: объект функций обратного вызова. При добавлении нового сообщения или ошибки AJAX запрос отправляется на сервер, который возвращает номер данного сообщения в случае успешного сохранения данных, в зависимости от успешности запроса срабатывает одна из переданных функций данного объекта.

Пример

  1. var  errors = AMOCRM.notifications,
  2.     date_now = Math.ceil(Date.now()/1000),
  3.     header = self.get_settings().widget_NAME,
  4.     text = 'error'
  5.     var n_data = {
  6.         header: header, //имя виджета
  7.                 text:'<p>'+text+'</p>',//текст уведомления об ошибке
  8.                 date: date_now //дата
  9.             },
  10.         callbacks = { done: function(){console.log('done');}, //успешно добавлено и сохранено AJAX done
  11.         fail: function(){console.log('fail');}, //AJAX fail
  12.         always: function(){console.log('always');} //вызывается всегда
  13.     };
  14.     errors.add_error(n_data,callbacks);
  15. AMOCRM.notifications.show_message_error(n_data, callbacks); //Ручной вызов вашего уведомления об ошибке.

Занесение в «Неразобранное»

В amoCRM существует сущность «Неразобранное», в которую попадают все обращения из различных интеграций, в том числе и телефонии.

В «Неразобранное» попадают входящие звонки с неизвестных номеров (в системе нет привязанного контакта), принятые пользователем, которые начинают отображаться в колонке «Неразобранное». Пользователь не может самостоятельно перевести обращение в «Неразобранное».

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

Пользователь может в модальном окне результатов звонка написать примечание или создать задачу, и они привяжутся к сделке, если «Неразобранное» будет принято. При перетаскивании автоматически создаётся сделка и контакт (с телефоном, с которого производился звонок). Название сделки будет при этом “Звонок от и номер телефона”, имя контакта будет “Автоконтакт номер телефона”. При отклонении заявки она пропадет из «Неразобранного», информация о звонке пропадает.

Пример добавления звонков в "Неразобранное"

Метод для добавления неразобранных заявок.

URL метода
POST /api/v2/incoming_leads/sip

Параметры

Параметр Тип Описание
add/source_name
require
string Название источника заявки
add/source_uid
require
string Уникальный идентификатор заявки
add/pipeline_id int id цифровой воронки, если параметр не передан, то заявка будет добавлена в неразобранное первой воронки
add/created_at timestamp Дата и время создания
add/incoming_lead_info array Массив содержащий информацию о поступившей заявке
add/incoming_entities
require
array Массив содержащий информацию о создаваемых элементах сущностей. Является обязательным, поскольку после принятия неразобранного, будет создан соответствующий элемент сущности.
add/incoming_entities/leads array Массив содержащий информацию для создания новой сделки. Может содержать все параметры и дополнительные поля доступные "Сделкам" на аккаунте.
add/incoming_entities/contacts array Массив содержащий информацию для создания нового контакта. Может содержать все параметры и дополнительные поля доступные "Контактам" на аккаунте.
add/incoming_entities/companies array Массив содержащий информацию для создания новой компании. Может содержать все параметры и дополнительные поля доступные "Компаниям" на аккаунте.
add/incoming_lead_info/to
require
int Идентификатор пользователя, который принял звонок
add/incoming_lead_info/from
require
string Внешний номер телефона
add/incoming_lead_info/date_call
require
timestamp Дата и время звонка
add/incoming_lead_info/duration
require
int Продолжительность звонка
add/incoming_lead_info/link
require
string Ссылка на запись звонка
add/incoming_lead_info/service_code
require
string Код виджета или сервиса, через который был совершён звонок
add/incoming_lead_info/uniq
require
string Уникальный код звонка
add/incoming_lead_info/add_note
require
bool Флаг, если передан этот параметр, то по принятию заявки в созданные сущности будет добавлено событие о совершённом звонке.

Пример

  1. {
  2.    add: [
  3.       {
  4.          source_name: "ОАО Коспромсервис",
  5.          source_uid: "a1fee7c0fc436088e64ba2e8822ba2b3",
  6.          created_at: "1510261200",
  7.          pipeline_id: "41563",
  8.          incoming_entities: {
  9.             leads: [
  10.                {
  11.                   name: "Техническое обслуживание бензопил",
  12.                   created_at: "1509483600",
  13.                   status_id: "13667502",
  14.                   responsible_user_id: "504141",
  15.                   price: "83000",
  16.                   tags: "ТО, услуги",
  17.                   notes: [
  18.                      {
  19.                         note_type: "7",
  20.                         element_type: "lead",
  21.                         text: "Отправить дубликат договора"
  22.                      }
  23.                   ],
  24.                   custom_fields: [
  25.                      {
  26.                         id: "4399917",
  27.                         values: [
  28.                            "3692247",
  29.                            "3692248"
  30.                         ]
  31.                      }
  32.                   ]
  33.                }
  34.             ],
  35.             contacts: [
  36.                {
  37.                   name: "Александр Петрович Смирнов",
  38.                   custom_fields: [
  39.                      {
  40.                         id: "4396818",
  41.                         values: [
  42.                            {
  43.                               value: "89457898713",
  44.                               enum: "WORK"
  45.                            }
  46.                         ]
  47.                      },
  48.                      {
  49.                         id: "4396819",
  50.                         values: [
  51.                            {
  52.                               value: "email@email.com",
  53.                               enum: "WORK"
  54.                            }
  55.                         ]
  56.                      },
  57.                      {
  58.                         id: "4400115",
  59.                         values: [
  60.                            {
  61.                               value: "ул. Ленина, д. 1",
  62.                               subtype: "address_line_1"
  63.                            },
  64.                            {
  65.                               value: "Кострома",
  66.                               subtype: "city"
  67.                            },
  68.                            {
  69.                               value: "156000",
  70.                               subtype: "zip"
  71.                            },
  72.                            {
  73.                               value: "RU",
  74.                               subtype: "country"
  75.                            }
  76.                         ]
  77.                      }
  78.                   ],
  79.                   responsible_user_id: "504141",
  80.                   date_create: "1509483600"
  81.                }
  82.             ],
  83.             companies: [
  84.                {
  85.                   name: "ОАО Коспромсервис"
  86.                }
  87.             ]
  88.          },
  89.          incoming_lead_info: {
  90.             to: "41565",
  91.             from: "89456153101",
  92.             date_call: "1509483600",
  93.             duration: "54",
  94.             link: https://www.example.com/records/2017/11/01/98431.mp3,
  95.             service_code: "CkKwPam6",
  96.             uniq: "a1fee7c0fc436088e64ba2e8822ba2b3ewrw",
  97.             add_note: "Договорились о сотрудничестве"
  98.          }
  99.       }
  100.    ]
  101. }

Список обзвона

Существует возможность создавать списки обзвона, из списков контаков, компаний и сделок. Для этого необходимо указать желаемые для добавления элементы списка и через вкладку «ещё» передать выбранные элементы в ваш список обзвона.

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

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

Пример выбора элементов

Пример списка обзвона

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

Пример

  1. this.callbacks = {
  2. contacts: { //Выбираем элементы сущностей из списков контактов или компаний
  3.         selected: function () {
  4.           var data = self.list_selected()['selected'],
  5.             nothing_added = true;
  6.           $.each(data, function (k, v) {
  7.             (function (v) {
  8.               var call_element = {},
  9.                 list_model = AMOCRM.data.current_list.where({id: v.id}),
  10.                 company;
  11.               list_model = list_model[0] || {};
  12. /* Получаем данные от каждого выбранного элемента */
  13.               call_element.element_id = v.id;
  14.               call_element.element_type = list_model.get('element_type');
  15.               call_element.type = list_model.get('element_type');
  16.               call_element.phone = v.phones[0] || false;
  17. /* Область видимости списка компаний, такая же как и область видимости контактов — clist. В связи с этим, нам необходимо
  18. дополнительно
  19. уточнить, к какой сущности относятся выбранные элементы */
  20.               call_element.entity = call_element.element_type == 1 ? 'contact' : 'company';
  21.               call_element.element = {};
  22.               call_element.element.text = list_model.get('name')['text'];
  23.               call_element.element.url = list_model.get('name')['url'];
  24.               company = list_model.get('company_name') || false;
  25.               if (company) {
  26.                 call_element.company = {};
  27.                 call_element.company.text = company.name;
  28.                 call_element.company.url = company.url;
  29.               }
  30.               if (call_element.phone) {
  31.                 self.__CallsList.addCall(call_element);   //Передаём выбранные элементы в вашу функцию обработки, addCall
  32. не является
  33. готовым методом SDK, приведён как пример
  34.                 nothing_added = false;
  35.                 $(document).trigger('list:cookies:update');
  36.               } else if (nothing_added && k == data.length - 1) {
  37.                 self.notifers.show_message_error({
  38.                   text: self.i18n('caller').nothing_to_add,
  39.                   without_header: true
  40.                 });
  41.               }
  42.             })(v);
  43.           });
  44.         }
  45.       },
  46.       leads: {  //Выбираем элементы из  списка сделок
  47.         selected: function () {
  48.           var data = self.list_selected()['selected'];
  49.           (function (data) {
  50.             self.tools.request({
  51.                 selected: data
  52.               },
  53.               'get_contacts_by_leads',
  54.               function (data) {
  55.  
  56.                 data.contacts = data.contacts || [];
  57.                 if (data.contacts.length <= 0) {
  58.                   self.notifers.show_message_error({
  59.                     text: self.i18n('caller').nothing_to_add,
  60.                     without_header: true
  61.                   });
  62.                   return;
  63.                 }
  64.                 $.each(data.contacts, function (k, v) {
  65.                   (function (v) {
  66.                     var call_element = {},
  67.                       company = false,
  68.                       list_model = AMOCRM.data.current_list.where({id: v.id});
  69.                     list_model = list_model[0] || {};
  70.  
  71.                     call_element.element_id = v.element_id;
  72.                     call_element.element_type = v.element_type;
  73.                     call_element.type = v.element_type;
  74.                     call_element.phone = v.phone || false;
  75.                     call_element.entity = v.entity;
  76.                     call_element.element = v.element;
  77.                     company = v.company || false;
  78.                     if (typeof company == 'object') {
  79.                       call_element.company = {};
  80.                       call_element.company.text = company.text;
  81.                       call_element.company.url = company.url;
  82.                     }
  83.                     if (call_element.phone) {
  84.                       self.__CallsList.addCall(call_element); //Передаём выбранные элементы в вашу функцию обработки,
  85. addCall не является
  86. готовым методом SDK, приведён как пример
  87.                       $(document).trigger('list:cookies:update');
  88.                     }
  89.                   })(v);
  90.                 });
  91.               }
  92.             );
  93.           })(data);
  94.         }
  95.       }
  96. };

Поскольку мы рекомендуем задавать область видимости „everywhere”, для всех виджетов телефонии, в manifest.json, то нет необходимости задавать дополнительные области видимости для выбора элементов из списка.

Далее нам необходимо воспроизвести выбранные элементы в виде списка. В примере мы приведём рендер шаблона формата *.twig, со структурой самого шаблона.

Пример

  1. render: function (calls) {
  2.         var _this = this;
  3.         _this.widget.getTemplate( //Выбираем шаблон call_list
  4.           'call_list',
  5.           {},
  6.           function (template, base_params) {
  7.             _this.$el.html(template.render(_.extend(base_params, {
  8.               list_expanded: 0,
  9.               open_contact: !(cookie.get(_this.widget.params.widget_code + '_open_contact') == '0'),
  10.               lang: _this.lang
  11.             })));
  12.             _this.$el.find('#sortable_calls_list').sortable({ //сортировка звонков
  13.               items: 'div.amo__vox__implant_call__list_wrapper__list__task',
  14.               handle: '.icon-sortable',
  15.               axis: 'y',
  16.               containment: '#vox_imp__call_list_wrapper .amo__vox__implant_call__list_wrapper__list',
  17.               scroll: false,
  18.               tolerance: 'pointer',
  19.               stop: function () {
  20.                 _this.startSort();
  21.               }
  22.             });
  23.             calls = calls || [];
  24.             if (calls.length > 0) {
  25.               _this.calls.push(calls);  //Добавление в ваш массив для обзвона, calls не является готовым методом SDK,
  26. приведён как пример
  27.             }
  28.           }
  29.         );
  30.         return this;
  31.       }

Пример *.twig шаблона для списка обзвона.

  1. <div id="vox_imp__call_list_wrapper" class="{{ widget_code }}_call__list_wrapper{% if list_expanded %} expanded{% endif %}
  2. {{ widget_code
  3. }}">
  4.   <div class="{{ widget_code }}_call__list_wrapper__header">
  5.     <span id="clear_call_list" class="{{ widget_code }}_call__list_wrapper__header_icon icon-clear"
  6.           title="{{ lang.clear }}"></span>
  7.  
  8.     <div class="{{ widget_code }}_call__list_wrapper__header_additional_option">
  9.       <span id="clear_call_list" class="{{ widget_code }}_call__list_wrapper__header_clear">{{ lang.clear }}</span>
  10.     </div>
  11.     <span class="{{ widget_code }}_call__list_wrapper__header_name">{{ lang.call_list }}:</span>
  12.  
  13.     <div class="{{ widget_code }}_call__list_wrapper__header__switcher">
  14.       <span class="{{ widget_code }}_call__list_wrapper__header__switcher_text">{{ lang.open_contact_w_calling }}</span>
  15.  
  16.       <div class="switcher_wrapper">
  17.         <label for="call_list_switcher"
  18.                class="switcher call_list_switcher switcher__{% if open_contact == 1 %}on{% else %}off{% endif %}"
  19.                id=""></label>
  20.         <input type="checkbox" value="Y" name="call_list_switcher" id="call_list_switcher" class="switcher__checkbox">
  21.       </div>
  22.     </div>
  23.   </div>
  24.   <div class="{{ widget_code }}_call__list_wrapper__hint">{{ lang.empty_calls_list }}</div>
  25.   <div class="{{ widget_code }}_call__list_wrapper__list custom-scroll" id="sortable_calls_list"></div>
  26. </div>
  27. <div class="{{ widget_code }}_call__footer {{ widget_code }}">
  28.   <div id="vox_imp__call_list_btn" class="{{ widget_code }}_call__btn {{ widget_code }}_call__list_btn"
  29.        title="{{ lang.call_list }}">
  30.     <span class="nav__notifications__counter call_list_notifications"></span>
  31.   </div>
  32.   <div class="{{ widget_code }}_call__status">
  33.     <div class="{{ widget_code }}_call__status__contact"></div>
  34.     <div class="{{ widget_code }}_call__status__talk">
  35.       <span class="{{ widget_code }}_call__status__talk__time"></span>
  36.             <span id="vox_implant__icon_wrapper" class="{{ widget_code }}__icon_wrapper">
  37.                 <span id="vox_imp__rec_call" class="{{ widget_code }}_call__status__talk__rec rec_is_on"
  38.                       title="{{ lang.talk_recording }}"></span>
  39.                 <span id="vox_imp__play_call" class="{{ widget_code }}_call__status__queue_pause"
  40.                       title="{{ lang.pause }}"></span>
  41.             </span>
  42.     </div>
  43.   </div>
  44.   <div class="{{ widget_code }}_call_options">
  45.     <div id="vox_imp__mic_btn" class="{{ widget_code }}_call__btn {{ widget_code }}_call__mute_mic_btn mute_is_on"
  46.          title="{{ lang.mute_speaker }}"></div>
  47.     <div class="{{ widget_code }}_call__btn {{ widget_code }}_call__skip_btn" title="{{ lang.skip }}"></div>
  48.     <div id="vox_imp__dial_btn" class="{{ widget_code }}_call__btn {{ widget_code }}_call__dial_btn"
  49.          title="{{ lang.dialling }}"></div>
  50.     <div id="vox_imp__hung_up_btn" class="{{ widget_code }}_call__btn {{ widget_code }}_call__phone_btn js-hungup_call">
  51. </div>
  52.   </div>
  53. </div>

Функция встроенного звонка (WebRTC)

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

WebRTC - решение с открытым кодом, и некоторые виджеты для интеграции amoCRM с виртуальными АТС используют его.

Отображение, работающей функции совершения звонков, в различных браузерах выглядит по-разному. В Mozilla Firefox это иконка микрофона. В браузере Google Chrome активная функция отображается в виде красного знака на вкладке и иконки видеокамеры в правой части адресной строки, подтверждающей доступ к вашему микрофону.

Пример встроенного звонка

Пример работы с WebRTC в amoCRM.

Пример

  1. initYourWidget: function () {
  2.     $.getScript('///* ссылка *//your_script.min.js', _.bind(function () {
  3.  
  4.     /* Обработка вашего скрипта работы с телефонией */
  5.  
  6.     }, this));
  7.  
  8.   initialize: function (params) {
  9.   AMOCRM.widgets.notificationsPhone({
  10.               ns: this.widget.ns,
  11.              click: _.bind(function () {
  12.                   this.$el.toggle();  //Отображение панели работы с WebRTC
  13.               }, this)
  14.     });
  15. }