В ряде случаев у компании может возникнуть необходимость обзвонить каких-то из своих клиентов и сообщить им о чем-то, или, например, провести опрос про качеству обслуживания. Данную задачу можно решать разными способами, но мы будем исходить из того, что в данном случае ее нужно решить веб-разработчику, который привык иметь дело с Javascript/веб-сервисами и не сильно хочет вникать в особенности систем IP-телефонии. К счастью для него есть подходящий инструмент, о котором подробнее под катом.
Итак, для реализации автоматизированных обзвонов мы будем использовать платформу VoxImplant, а также встроенную в нее подсистему колл-листов (CallList). Стоит сразу отметить, что автоматизированные звонки допустимо делать только тем людям, которые на это согласились. Телефонный спам ничем не лучше СМС-спама или email-спама, не надо лишний раз раздражать людей.
Давайте рассмотрим несколько сценариев — обычная нотификация о каком-то событии (например, сообщение кода-активации или напоминание о посещении мед. учреждения) и опрос о качестве обслуживания.
В случае VoxImplant на вход с помощью HTTP-запроса подается CSV-файл со списком номеров и дополнительной информацией к каждому номеру, которая может быть использована в сценарии, запускаемому на каждую строку файла. Первая строка — это обязательный заголовок с названием параметров, чтобы потом эти параметры можно было использовать в сценарии. Существуют еще системные параметры, которые влияют на то как система будет данную строку обрабатывать. Давайте рассмотрим следующий пример:
Это контент CSV-файла, который мы отправим на обзвон. При обзвоне в сценарий VoxImplant эти данные придут в виде JSON, и мы сможем их использовать по назначению.
Создаем приложение, а в нем – сценарий и правило, к которому цепляем сценарий. Маску можно не менять, она не имеет значения при запуске через HTTP-запрос.
Наш сценарий VoxEngine должен содержать следующий код:
Метод API для запуска обзвона CreateCallList, давайте разберем параметры запроса, чтобы все было понятно:
Сделаем следующий PHP-файл с парочкой функций, которые запускают обзвон:
Результат выполнения getCallListDetails будет выглядеть как-то так (если успешно дозвонились):
Естественно, можно получить список всех обзвонов GetCallLists или остановить обзвон StopCallListProcessing.
Немного усложним задачу — кроме звонка будем еще просить ввести оценку качества обслуживания и сохранять ее в результатах обзвона. Для этого нужно будет модифицировать функции handleCallConnected, handleCallDisconnected и добавить новую handleToneReceived:
Результат будет выглядеть как-то так:
Ну вот, мы рассмотрели несколько сценариев обзвонов с помощью VoxImplant. При желании можно делать HTTP-запросы во внешний мир прямо из сценария и передавать данные куда-то в реальном времени или подключить модуль ASR с распознаванием речи и дать возможность людям ответить на вопрос прямо голосом. Звонки при желании можно отправлять через свою SIP-инфраструктуру — меняем callPSTN на callSIP в сценарии и туда передаем настройки. В общем, надеемся, что данный пост будет вам полезен и поможем вам решить свою задачу, полезных вам звонков!
Итак, для реализации автоматизированных обзвонов мы будем использовать платформу VoxImplant, а также встроенную в нее подсистему колл-листов (CallList). Стоит сразу отметить, что автоматизированные звонки допустимо делать только тем людям, которые на это согласились. Телефонный спам ничем не лучше СМС-спама или email-спама, не надо лишний раз раздражать людей.
Давайте рассмотрим несколько сценариев — обычная нотификация о каком-то событии (например, сообщение кода-активации или напоминание о посещении мед. учреждения) и опрос о качестве обслуживания.
Настройка аккаунта
В случае VoxImplant на вход с помощью HTTP-запроса подается CSV-файл со списком номеров и дополнительной информацией к каждому номеру, которая может быть использована в сценарии, запускаемому на каждую строку файла. Первая строка — это обязательный заголовок с названием параметров, чтобы потом эти параметры можно было использовать в сценарии. Существуют еще системные параметры, которые влияют на то как система будет данную строку обрабатывать. Давайте рассмотрим следующий пример:
user_id;first_name;last_name;phone_number;activation_code
0;Сергей;Иванов;74951234567;101102
Это контент CSV-файла, который мы отправим на обзвон. При обзвоне в сценарий VoxImplant эти данные придут в виде JSON, и мы сможем их использовать по назначению.
Создаем приложение, а в нем – сценарий и правило, к которому цепляем сценарий. Маску можно не менять, она не имеет значения при запуске через HTTP-запрос.
Наш сценарий VoxEngine должен содержать следующий код:
require(Modules.CallList); // Подключаем модуль CallList
require(Modules.AI);
let call,
first_name,
last_name,
phone_number,
activation_code,
playbackCounter = 0;
// Обработка события запуска сценария
VoxEngine.addEventListener(AppEvents.Started, function (e) {
let data = VoxEngine.customData(); // <-- сюда пришли данные из строки CSV в JSON-формате
data = JSON.parse(data);
user_id = data.user_id;
first_name = data.first_name;
last_name = data.last_name;
phone_number = data.phone_number;
activation_code = data.activation_code;
Logger.write("Звоним " + first_name + " " + last_name + " на номер " + phone_number);
// Звоним
call = VoxEngine.callPSTN(phone_number, "+1234567890"); // <-- вторым параметром нужно указать callerid, предварительно его авторизовав в разделе CallerIDs верхнего меню панели управления VoxImplant
// Для определения голосовой почты
call.addEventListener(CallEvents.AudioStarted, function(){
AI.detectVoicemail(call)
.then(voicemailDetected)
.catch(()=>{
Logger.write('Голосовая почта не обнаружена');
})
});
// Вешаем обработчики событий
call.addEventListener(CallEvents.Connected, handleCallConnected);
call.addEventListener(CallEvents.Failed, handleCallFailed);
call.addEventListener(CallEvents.Disconnected, handleCallDisconnected);
});
function voicemailDetected(e) {
// Голосовая почта?
if (e.confidence >= 75) {
VoxEngine.CallList.reportError("Voicemail", VoxEngine.terminate);
return;
}
}
// Дозвонились
function handleCallConnected(e) {
connected = true;
setTimeout(function () {
e.call.say("Здравствуйте, " + first_name + "! Ваш код активации: " + activation_code, { "language": VoiceList.Yandex.ru_RU_oksana });
}, 500);
e.call.addEventListener(CallEvents.PlaybackFinished, handlePlaybackFinished);
}
// Воспроизведение закончилось
function handlePlaybackFinished(e) {
e.call.removeEventListener(CallEvents.PlaybackFinished, handlePlaybackFinished);
playbackCounter++;
// Несколько раз сказали код активации и достаточно
if (playbackCounter == 4) {
e.call.hangup();
} else {
// Делаем паузу несколько секунд и проговариваем код еще раз
setTimeout(function () {
e.call.say("Ваш код активации: " + activation_code, { "language": VoiceList.Yandex.ru_RU_oksana });
e.call.addEventListener(CallEvents.PlaybackFinished, handlePlaybackFinished);
}, 2000);
}
}
function handleCallFailed(e) {
// Сообщаем модулю, что не удалось дозвониться
// в зависимости от настроек обзвона он либо попытается дозвониться еще раз через указанное время
// либо запишет результат, что дозвониться не удалось, и в колонку result_data
// CSV-файла с результатами обзвона запишет данные result, msg, code в JSON-формате
CallList.reportError({
result: false,
msg: "Failed",
code: e.code
}, VoxEngine.terminate);
}
function handleCallDisconnected(e) {
// Отправляем сообщение модулю, чтобы сообщить, что дозвонились
// result и duration будут записаны в колонку result_data
// CSV-файла с результатами обзвона в JSON-формате
CallList.reportResult({
result: true,
duration: e.duration
}, VoxEngine.terminate);
}
Запуск обзвона через HTTP API
Метод API для запуска обзвона CreateCallList, давайте разберем параметры запроса, чтобы все было понятно:
- account_name — имя аккаунта VoxImplant
- api_key — API KEY аккаунта VoxImplant
- rule_id — id-правила приложения, к которому мы прицепили сценарий
- priority — приоритет обзвона, если обзвонов много, то можно управлять какой будет раньше выполнен
- max_simultaneous — максимальное кол-во одновременно обрабатываемых записей
- num_attempts — кол-во попыток дозвона, новая попытка будет в случае если была вызвана функция CallList.reportError
- name — просто название обзвона
- file_content — CSV-файл нужно передавать в теле запроса (request body)
- interval_seconds — время до следующей попытки дозвона (в секундах)
- encoding — кодировка CSV-файла, нужно указывать, если отличается от UTF-8
- delimiter — разделитель столбцов в CSV-файле, по умолчанию ;
Сделаем следующий PHP-файл с парочкой функций, которые запускают обзвон:
<?php
define("API_URL", "https://api.voximplant.com/platform_api/");
define("API_KEY", "ваш api key");
define("ACCOUNT_NAME", "ваш account name");
define("RULE_ID", id-правила);
function httpRequest($url,$params) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
if (isset($params["post"])) curl_setopt($ch, CURLOPT_POST, 1);
if (isset($params["post_data"])) curl_setopt($ch, CURLOPT_POSTFIELDS, $params["post_data"]);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: text/csv'));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$server_output = curl_exec ($ch);
curl_close ($ch);
return $server_output;
}
function createCallList($file) {
$url = API_URL . "CreateCallList/?" .
"account_name=" . ACCOUNT_NAME .
"&api_key=" . API_KEY .
"&rule_id=" . RULE_ID .
"&max_simultaneous=10" .
"&num_attempts=2" .
"&interval_seconds=60" .
"&priority=1" .
"&name=CallList";
$data = file_get_contents($file);
$params = array('post' => true, 'post_data' => $data);
$result = httpRequest($url, $params);
echo $result;
}
function getCallListDetails($list_id, $output = "json") {
$url = API_URL . "GetCallListDetails/?" .
"account_name=" . ACCOUNT_NAME .
"&api_key=" . API_KEY .
"&list_id=" . $list_id .
"&output=" . $output;
$params = array();
$result = httpRequest($url, $params);
echo $result;
}
createCallList(URL-CSV-файла);
//getCallListDetails($list_id, "csv");
?>
Результат выполнения getCallListDetails будет выглядеть как-то так (если успешно дозвонились):
"activation_code";"user_id";"last_name";"phone_number";"first_name";"__end_execution_time";"__start_execution_time";"result_data";"last_attempt";"attmepts_left";"status_id";status
101102;0;Иванов;74951234567;Сергей;;;"{""result"":true,""duration"":27}";"2014-11-24 19:21:39";1;2;Processed
Естественно, можно получить список всех обзвонов GetCallLists или остановить обзвон StopCallListProcessing.
Пример сценария опроса
Немного усложним задачу — кроме звонка будем еще просить ввести оценку качества обслуживания и сохранять ее в результатах обзвона. Для этого нужно будет модифицировать функции handleCallConnected, handleCallDisconnected и добавить новую handleToneReceived:
function handleCallConnected(e) {
connected = true;
e.call.handleTones(true); // <-- включаем обработку ввода
setTimeout(function () {
e.call.say("Здравствуйте, " + first_name + "! Спасибо вам за посещение нашего магазина, "+
"пожалуйста, оцените качество обслуживания от одного до пяти.", { "language": VoiceList.Yandex.ru_RU_oksana });
}, 500);
e.call.addEventListener(CallEvents.PlaybackFinished, handlePlaybackFinished);
e.call.addEventListener(CallEvents.ToneReceived, handleToneReceived);
}
let rating;
function handleToneReceived(e) {
e.call.removeEventListener(CallEvents.PlaybackFinished, handlePlaybackFinished);
e.call.stopPlayback();
rating = e.tone;
e.call.say("Спасибо большое за ваш ответ!", { "language": VoiceList.Yandex.ru_RU_oksana });
e.call.addEventListener(CallEvents.PlaybackFinished, function(e) {
e.call.hangup();
});
}
function handleCallDisconnected(e) {
CallList.reportResult({
result: true,
duration: e.duration,
rating: rating,
}, VoxEngine.terminate);
}
// Воспроизведение закончилось
function handlePlaybackFinished(e) {
e.call.removeEventListener(CallEvents.PlaybackFinished, handlePlaybackFinished);
playbackCounter++;
// Несколько раз сказали код активации и достаточно
if (playbackCounter == 4) {
e.call.hangup();
} else {
// Делаем паузу несколько секунд и проговариваем код еще раз
setTimeout(function () {
e.call.say("Пожалуйста, оцените качество обслуживания от одного до пяти.", { "language": VoiceList.Yandex.ru_RU_oksana });
e.call.addEventListener(CallEvents.PlaybackFinished, handlePlaybackFinished);
}, 2000);
}
}
Результат будет выглядеть как-то так:
"user_id";"last_name";"phone_number";"first_name";"__end_execution_time";"__start_execution_time";"result_data";"last_attempt";"attmepts_left";"status_id";status
0;Иванов;74951234567;Сергей;;;"{""result"":true,""duration"":27,""rating"":""3""}";"2014-11-24 20:17:13";1;2;Processed
Ну вот, мы рассмотрели несколько сценариев обзвонов с помощью VoxImplant. При желании можно делать HTTP-запросы во внешний мир прямо из сценария и передавать данные куда-то в реальном времени или подключить модуль ASR с распознаванием речи и дать возможность людям ответить на вопрос прямо голосом. Звонки при желании можно отправлять через свою SIP-инфраструктуру — меняем callPSTN на callSIP в сценарии и туда передаем настройки. В общем, надеемся, что данный пост будет вам полезен и поможем вам решить свою задачу, полезных вам звонков!
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Был ли данный материал вам полезен?
75% Да42
14.29% Не очень8
10.71% Нет6
Проголосовали 56 пользователей. Воздержались 19 пользователей.