16 June 2014

Быстрое создание callback-сценариев с помощью Voximplant

Voximplant corporate blogWebsite developmentDevelopment of communication systems
Tutorial
Не удивительно, что во многих бизнес процессах так или иначе встречается такая задача как позвонить на один номер телефона и потом соединить его с другим номером. Чаще всего такой сервис называют callback или обратный вызов, иногда — заказ звонка. Многие встречали его на сайтах интернет-магазинов, но в большинстве случаев это не автоматизированный обратный звонок, а обычная заявка, которая падает менеджеру на email или появляется в CRM, после чего менеджер ручками набирает номер клиента и с ним беседует. Некоторые крупные компании реализуют автоматизированный callback и даже интегрируют его с очередями в контакт-центре. В данном посте мы рассмотрим как буквально за несколько минут создать callback-сценарий с помощью платформы VoxImplant, а также интегрировать это хозяйство с каким-нибудь существующим бэкендом для сохранения/получения данных по звонку, запасайтесь поп-корном и добро пожаловать под кат.
Для начала продублируем схему в более крупном размере, чтобы было проще объяснить, что, как и с чем взаимодействует при реализации нашего callback-сервиса.

Выглядит немного громоздко, но на деле все очень просто и удобно. Разработчик VoxImplant (чтобы получить аккаунт разработчика нужно зарегистрироваться на сайте, это абсолютно бесплатно) через HTTP API делает запрос к облаку VoxImplant после чего сервер сценариев запускает заранее написанный на JS сценарий, в котором описана логика совершения звонков, их соединения, а также, при желании, бизнес-логика. Перед тем как делать HTTP-запрос для запуска сценария, очевидно, нужно его написать внутри приложения и прикрепить к правилу, id этого правила потом нужно будет указывать в HTTP-запросе, чтобы было понятно какой сценарий должен быть запущен. Итак, по порядку:
  1. Создаем приложение VoxImplant.
  2. Создаем в нем сценарий.
  3. Создаем правило и привязываем к нему сценарий.
  4. Делаем HTTP-запрос для запуска сценария.

После совершения HTTP-запроса для запуска сценария, если все сделано правильно, в ответ придет media_session_access_url, который позволяет после запуска сценария продолжить удаленное управление его работой. Например, если нужно в какой-то определенный момент закончить выполнение сценария, то можно написать в сценарии следующее:

VoxEngine.addEventListener(AppEvents.HttpRequest, handleHttpRequest); 
function handleHttpRequest(e) {
  VoxEngine.terminate();
}

В таком случае, сделав запрос по media_session_access_url, вы прекратите выполнение сценария. Возвращаемся к реализации нашего колбэка на телефонные номера. Создаем приложение в соответствующем разделе панели управления, назовем его банально callback (в итоге полное название будет callback.имя_аккаунта.voximplant.com), и в разделе «Сценарии» создаем новый сценарий CallbackHabr следующего вида:

var call1, call2, data;
const callerId = "+1234567890"; // Арендованный или верифицированный номер телефона

VoxEngine.addEventListener(AppEvents.Started, handleScenarioStart);

function handleScenarioStart(e) {
  // в сценарий можно передать данные с помощью механизма customData,
  // параметр script_custom_data в HTTP-запросе StartScenarios
  // передадим в нем номера в виде строки номер1:номер2
  data = VoxEngine.customData();
  data = data.split(":");
  // начало выполнения сценария - звоним на номер 1
  call1 = VoxEngine.callPSTN(data[0], callerId);
  // обработчики событий
  call1.addEventListener(CallEvents.Connected, handleCall1Connected);
  call1.addEventListener(CallEvents.Failed, function(e) { VoxEngine.terminate(); });
  call1.addEventListener(CallEvents.Disconnected, function(e) { VoxEngine.terminate(); });
}

function handleCall1Connected(e) {
  // первый звонок соединен успешно, проигрываем сообщение
  call1.say("Здравствуйте, это звонок от сервиса Колбэк, ожидайте соединения", Language.RU_RUSSIAN_FEMALE);
  call1.addEventListener(CallEvents.PlaybackFinished, function(e1) {
     // после проигрывания сообщения пытаемся дозвониться до номера 2
    call2 = VoxEngine.callPSTN(data[1], callerId);
    // обработчики событий
    call2.addEventListener(CallEvents.Connected, handleCall2Connected);
    call2.addEventListener(CallEvents.Failed, function(e2) { 
        call1.say("К сожалению, соединение не может быть установлено", Language.RU_RUSSIAN_FEMALE);
        call1.addEventListener(CallEvents.PlaybackFinished, function(e3) { VoxEngine.terminate(); });      
    });
    call2.addEventListener(CallEvents.Disconnected, function(e2) { VoxEngine.terminate(); });
  });
}

function handleCall2Connected(e) {
  // соединяем два звонка - звук 
  VoxEngine.sendMediaBetween(call1, call2);
  // и сигнализацию
  VoxEngine.easyProcess(call1, call2);
}

Если коротко, то данный сценарий звонит на номера, которые мы передаем через специальный параметр запроса StartScenarios script_custom_data в виде строки номер1: номер2. Сначала дозваниваемся на номер1 и проигрываем сообщение с помощью TTS, после чего дозваниваемся на номер2 и соединяем два звонка друг с другом. В данном сценарии мы никак не отрабатываем некоторые случаи, например, если не дозвонились на номер1, то просто завершаем выполнение сценария. Если немного поколдовать, то можно оповещать внешний мир о том, что что-то пошло не так, меняем
call1.addEventListener(CallEvents.Failed, function(e) { VoxEngine.terminate(); });

на
call1.addEventListener(CallEvents.Failed, handleCall1Failed);

и описываем handleCall1Failed:
function handleCall1Failed(e) {
  // тут можно узнать причину 
  var code = e.code,
      reason = e.reason;
  // и отправить ее во внешний мир с помощью HTTP-запроса
  Net.httpRequest("http://somewebservice", function(e1) {
    // информация по реузльтатам запроса - e1.code, e1.text, e1.data, e1.headers
    // убиваем сессию
    VoxEngine.terminate();
  });
}

Это самый простой пример с GET-запросом. Для настройки и управления HTTP-запросом со стороны сценария доступен класс HttpRequestOptions.
Таким же образом с помощью Date можно замерять длительность отдельных звонков или сессии внутри сценария и отправлять данные во внешний мир, если по каким-то причинам лезть в историю звонков для получения этой информации не соответствует логике сервиса/приложения. Как вы уже, наверное, поняли, мы пытались сделать очень гибкую систему, чтобы механизм решения тех или иных задач разработчик мог выбирать сам.
После того как сценарий готов, нам нужно пойти в раздел «Роутинг», чтобы подцепить его к правилу и в итоге получить ID правила:


Ну в общем и все, теперь можно делать HTTP-запрос StartScenarios, для которого потребуется еще ряд параметров, свой api_key можно узнать в разделе Profile. Запрос в итоге будет выглядеть как-то так:

https://api.voximplant.com/platform_api/StartScenarios/?account_id=1&api_key=eec36d6c-a0eb-46b5-a006-1c2b65343bac&rule_id=55033&script_custom_data=number1%3Anumber2

В результате успеха в ответ придет что-то в духе:
{
	"result" : 1,
	"media_session_access_url" : "http:\/\/1.2.3.4:12092\/request?id=93e41c6e20811b9b.1380201554.0@1.2.3.4&token=36bc7ce95edc679e32d83bb6f3ad985f"
}

Через этот media_session_access_url можно будет дальше общаться с сессией при необходимости. Для отладки работы сценария всегда доступны логи, которые находятся в разделе «История звонков», а также наш убердебагер, доступный внутри каждого из сценариев (кнопка сверху). Для удобства мы загрузили сценарий из данного поста на GitHub, чтобы можно было быстро поэкспериментировать.

Callback-сценарий на GitHub
Only registered users can participate in poll. Log in, please.
Был ли данный материал Вам полезен?
85.71% Да 48
14.29% Нет 8
56 users voted. 6 users abstained.
Tags:voximplantcallbackобратный звонок
Hubs: Voximplant corporate blog Website development Development of communication systems
+3
15.4k 42
Comments 41
Top of the last 24 hours