Делаем очередь входящих звонков с функцией callback

26d75647d96b4a0d9b059fb1e11b653c.jpg При звонках в колл-центр компаний часто приходится сталкиваться с большим временем ожидания на линии, многие из нас слушали надоедливую мелодию в течение десятков минут хотя бы раз в жизни. Самое интересное заключается в том, что это совершенно невыгодно компании в колл-центр которой вы звоните, особенно если вы звоните на номер 8–800. К счастью, уже давно придуман способ, позволяющий решить данную проблему — это callback или обратный вызов. Суть этого способа очень простая: позвонившему предлагают отключиться от колл-центра при этом его номер так и остается в очереди на обслуживание и как только его очередь подойдет, то ему автоматически наберут и соединят с оператором, на которого распределился его звонок. Таким образом убиваем сразу несколько зайцев: не занимаются линии колл-центра, не тратятся дорогостоящие минуты 8–800, а клиенты не испытывают лишнего раздражения в ожидании ответа. Вендоры колл-центрового ПО хотят за такую функцию весьма приличных денег, а мы под катом расскажем как данный функционал достаточно просто и быстро реализуется с помощью платформы VoxImplant.Так как мы уже писали про организацию колл-центра с помощью VoxImplant, то повторять эту часть в данной статье не будем, а сосредоточимся на изменениях, которые необходимо сделать в сценариях для реализации коллбэк-функции. Сразу замечу, что данная функциональность доступна только для сценариев, в которых подключается модуль ACD для работы с очередями. Сценарий, отвечающий за обработку входящих звонков с учетом нашей коллбэк-функции будет выглядеть следующим образом: // Подключаем модуль ACD require (Modules.ACD);

var request, // <-- тут будем хранить экземпляр ACDRequest originalCall, // <-- входящий звонок callerid, statusInterval, callback = false; // <-- флаг для коллбэк-режима

// Вешаем обработчик входящего вызова VoxEngine.addEventListener (AppEvents.CallAlerting, handleInboundCall);

// Обрабатываем входящий вызов function handleInboundCall (e) { originalCall = e.call; callerid = e.callerid; // Вешаем обработчики originalCall.addEventListener (CallEvents.Connected, handleCallConnected); originalCall.addEventListener (CallEvents.PlaybackFinished, handlePlaybackFinished); originalCall.addEventListener (CallEvents.Failed, cleanup); originalCall.addEventListener (CallEvents.Disconnected, cleanup); // Отвечаем на звонок originalCall.answer (); }

// Завершаем сессию function cleanup (e) { if (request) { // Если звонок в очереди — удаляем request.cancel (); request = null; } // Закончить сессию VoxEngine.terminate (); }

// Играем музыку после окончания проигрывания голоса или музыки function handlePlaybackFinished (e) { e.call.startPlayback («http://cdn.voximplant.com/toto.mp3»); }

// Обработчик нажатий на кнопки function handleToneReceived (e) { if (e.tone == »#») { callback = true; originalCall.hangup (); // <-- несмотря на отсутствие звонков сессия не завершится } }

// Звонок соединен function handleCallConnected (e) { // Включаем обработку нажатий на кнопки телефона originalCall.handleTones (true); originalCall.addEventListener (CallEvents.ToneReceived, handleToneReceived); // Отправляем звонок в очередь 'MainQueue', которую мы создали в панели управления request = VoxEngine.enqueueACDRequest («MainQueue», callerid);

// Получаем статус после того как звонок поставлен в очередь request.addEventListener (ACDEvents.Queued, function (acdevent) { request.getStatus (); });

// Сообщаем звонящему о примерном времени ожидания и месте в очереди request.addEventListener (ACDEvents.Waiting, function (acdevent) { var minutesLeft = acdevent.ewt + 1; var minutesWord = » минуты.»; if ((minutesLeft > 10 && minutesLeft < 20) || (minutesLeft % 10 > 4 || minutesLeft % 10 == 0)) { minutesWord = » минут.»; } else if (minutesLeft % 10 == 1) { minutesWord = » минуту.»; } originalCall.say («Вы находитесь в очереди под номером » + acdevent.position + ». Оператор ответит Вам менее чем через » + (acdevent.ewt + 1) + minutesWord + » Вы также можете нажать решетку и мы сами перезвоним вам как только оператор будет готов обслужить ваш вызов.», Language.RU_RUSSIAN_FEMALE); });

// Отправляем звонок оператору request.addEventListener (ACDEvents.OperatorReached, function (acdevent) { if (callback) { // В случае если клиент выбрал коллбэк, то после распределения вызова на оператора сообщаем оператору, что нужно дождаться соединения с клиентом acdevent.operatorCall.say («Пожалуйста, дождитесь соединения с клиентом.», Language.RU_RUSSIAN_FEMALE); acdevent.operatorCall.addEventListener (CallEvents.Disconnected, VoxEngine.terminate); acdevent.operatorCall.addEventListener (CallEvents.PlaybackFinished, function (callevent) { // Делаем коллбэк originalCall = VoxEngine.callUser (callerid); originalCall.addEventListener (CallEvents.Connected, function (callevent) { VoxEngine.sendMediaBetween (acdevent.operatorCall, originalCall); clearInterval (statusInterval); }); originalCall.addEventListener (CallEvents.Failed, cleanup); originalCall.addEventListener (CallEvents.Disconnected, cleanup); }); } else { VoxEngine.sendMediaBetween (acdevent.operatorCall, originalCall); acdevent.operatorCall.addEventListener (CallEvents.Disconnected, VoxEngine.terminate); clearInterval (statusInterval); } });

// Нет доступных операторов — ни один оператор не обслуживает очередь request.addEventListener (ACDEvents.Offline, function (acdevent) { originalCall.say («К сожалению, сейчас нет доступных операторов. Пожалуйста, попробуйте позвонить позднее.», Language.RU_RUSSIAN_FEMALE); originalCall.addEventListener (CallEvents.PlaybackFinished, function (e) { VoxEngine.terminate (); }); });

// Получаем и сообщаем статус каждые 30 секунд statusInterval = setInterval (request.getStatus, 30000); } Вот собственно и все. Немного подправив сценарий из предыдущего туториала про ACD мы получили очередь с коллбэком. Базовый сценарий, который мы меняли, доступен на github.com/voximplant/acd, также как и простейший веб-фон для операторов.Работа с очередью через HTTP API Предыдущий пример был сделан для случая когда сначала есть входящий звонок, в реальной жизни могут встречаться случаи, когда клиент сразу заказывает на сайте коллбэк и нам нужно его разместить в очереди на обработку. В целом, очередь — это абстрактная сущность, туда на обработку можно кидать не только звонки, но и, например, emailы, сообщения и т.д. В такой ситуации сценарий надо запускать через метод StartScenarios HTTP API, а сам сценарий немного трансформируется: var displayName, callback = true; // Обработка заупуска сессии через StartScenarios VoxEngine.addEventListener (AppEvents.Started, function (e) { var data = VoxEngine.customData (); // Будем в script_custom_data передавать имя клиента и его номер в виде номер: имя data = data.split (»:»); callerid = data[0]; displayName = data[1]; Logger.write («Put »+displayName+» with number »+callerid+» in a queue»); // Ставим запрос в очередь 'MainQueue' request = VoxEngine.enqueueACDRequest («MainQueue», callerid); // … дальше все то же самое, что и в предыдущем сценарии }); P.S. А что если… Нас иногда спрашивают: «а что если мы хотим использовать SIP-телефоны вместо веб-телефонов, сделанных с помощью VoxImplant Web SDK в нашем колл-центре? «Отвечаем: «как ни странно, это возможно, но подробнее об этом мы расскажем в отдельной статье».

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

© Habrahabr.ru