Дополнительный автоматический анализ вызовов
В ряде случаев получения обработанной в Tariscope информации о вызовах недостаточно и требуется дополнительный анализ данных, который хотелось бы, чтобы Tariscope выполнял автоматически. К примеру, служба безопасности компании хотела бы оперативно знать обо всех вызовах, выполненных сотрудниками из телефонов ведомственной АТС к пожарной охране, полиции или скорой помощи. Другой пример, когда желательно знать обо всех исходящих звонках, стоимость которых выше определенной величины, или о звонках на (с) телефоны из черного списка. Можно придумать еще ряд случаев, когда необходимо оперативно получать сообщения об определенных вызовах.
Конечно, будет не лучшим решением подобных задач посадить за монитор с Tariscope сотрудника, отслеживающего такие вызовы. Но этого делать не надо, если использовать все возможности Tariscope. Tariscope можно настроить так, что он будет по окончании каждого вызова автоматически выполнять дополнительный анализ данных вызова на предмет соответствия предварительно заданным условиям, например, как мы упоминали ранее, выполнение каким-либо сотрудником вызова на какие-либо конкретные телефонные номера.
Особый случай, требующий оперативного отслеживания, это обнаружение телефонного фрода. Под телефонным фродом подразумевается определенный тип мошенничества, когда разными средствами выполняются несанкционированные вызовы, как правило, международные, за счет компании. В 2023 году по данным международной ассоциации CFCA (Communications Fraud Control Association) потери от телефонного фрода составляют около 38,95 млрд. рублей. долларов США[1].
Выявление фрода существенно сложнее, чем обнаружение, например, вызовов на конкретные телефонные номера, так как заранее неизвестно, на какие номера выполняются вызовы, когда, какой продолжительности. Для обнаружения фрода, как правило, рекомендуется использовать специальные системы, в большинстве случаев работа которых основана на сравнении конкретного вызова с моделью поведения конкретного абонента, группы абонентов и в целом компании. Tariscope имеет такую подсистему обнаружения фрода, но эта подсистема не входит в базовую лицензию на Tariscope и должна приобретаться дополнительно к базовой лицензии.
Вместе с тем, даже не купив такую подсистему, Tariscope дает возможность обнаруживать подозрительные вызовы, которые могут быть фродом. В этой статье мы как раз рассмотрим, как это сделать.
Во-первых,будем рассматривать только исходящие международные звонки стоимостью сверх заданной величины, так как фрод значительно реже используется для междугородных и тем более городских вызовов.
Во-вторых,из указанных вызовов в первом условии наиболее подозрительными вызовами с признаками фрода следует считать выполняемые в нерабочее время в выходные и праздничные дни.
В-третьих, можно оценивать страны, на которые выполнялся вызов. Считается, что больше всего звонков, являющихся фродом, выполняется в страны Карибского бассейна, а также Азии и Африки.
И, наконец, можно оценивать вызовы на принадлежность фроду от абонентов, данные по которым отсутствуют в базе данных системы Tariscope.
Теперь рассмотрим, каким образом поиск вызовов с частью вышеуказанных признаков можно реализовать в системе Tariscope.
В настройках службы Tariscope Observer можно выполнять сценарии при наступлении определенных событий. Для этого в ветке меню Сбор данных/Observer системы Tariscope следует выбрать пункт меню Управление сбором данных. Откроется страница настройки Сбор данных/Observer, пример которой приведен на рисунке 1.
Рисунок 1
Выберите строку из необходимых Observer, если у вас их несколько, и щелкните на панели инструментов по иконке Изменить. В появившемся меню выберите Сценарии Observer. В результате откроется страница Сценарии Observer, пример которой показан на рисунке 2.
Рисунок 2
Это окно содержит список событий, при пришествии которых Tariscope может запустить связанный с этим событием сценарий.
Возможна реакция на следующие события:
- Подключение источника данных.
- Отключение источника данных.
- Изменение класса абонента.
- Изменение класса группы.
- Периодическое действие.
- Новый вызов обработан.
- Ошибка подключения базы данных.
Для анализа вызовов на предмет принадлежности их к фроду в списке Событие следует выбрать событие Новый вызов проработан, а в списке Сценарии выбрать файл, содержащий сценарий анализа фрода. Поставляемые с Tariscope сценарии по умолчанию устанавливаются в папку C:\ProgramData\Tariscope\ObserverScripts
После выбора необходимого сценария сохраните настройки (рисунок 2).
Сценарии должны быть написаны на языке C#. Среди сценариев, поставляемых с Tariscope, есть файл fraud.cs. Он позволяет отправлять сообщения либо на заданный в сценарии электронный адрес или на электронный адрес, заданный в настройках Tariscope, о исходящих международных звонках продолжительностью более 150 секунд, выполненных в промежуток времени: с 19:00 до 08:00. Эти параметры пользователь Tariscope может изменить, удалить или добавить другие.
Для написания новых сценариев или редактирования существующих желательно иметь представление о программировании на языке C#, а также о создании запросов SQL.
Если вы не уверены в своих силах, обратитесь в службу технической поддержки компании SoftPI, так как неправильно написанный сценарий может нанести ущерб системе Tariscope.
Написание сценариев силами компании SoftPI не входит в услуги гарантийной или послегарантийной поддержки и производится за отдельную оплату.
Структура всех сценариев, используемых в Tariscope, одинакова. Каждый сценарий реализует интерфейс IScript.
В этом интерфейсе есть два метода:
1. Метод Init. Этот метод вызывается один раз при запуске сценария, когда служба Tariscope Observer компилирует и инициализирует этот сценарий.
2. Метод Main. В нем выполняются операции, связанные с конкретным событием. В метод Main передается объект Parameters.
3. При инициализации сценария в него передается интерфейс IScriptHost, позволяющий сценарию выполнять некоторые операции. К примеру, отправить сообщение по электронной почте.
Листинг сценария fraud.cs приведен ниже:
using Microsoft.Data.SqlClient;
using SoftPI.Tariscope.WebAdministration.Observer.Scripting.Interfaces;
using SoftPI.Tariscope.WebAdministration.Observer.Scripting.Models;
using System;
using SoftPi.Tariscope.DAL;
public class FraudScanner : IScript
{
private IScriptHost Host;
private bool NeedFinish = false;
//
//
********************************************************************************************
//
private int MAX_CALL_DURATION_S = 150;
private int CALLTYPE_INTERNATIONAL = 5;
private TimeSpan BEGINNING_OF_WORK = TimeSpan.Parse("08:00:00");
private TimeSpan END_OF_WORK = TimeSpan.Parse("19:00:00");
//
//
*********************************************************************************************
//
public void Init(IScriptHost host)
{
this.Host = host;
host.Close += OnClose;
NeedFinish = false;
}
private void OnClose(ref bool Cancel)
{
return;
}
public void Main(object Parameters)
{
NewCallActionParameters actionParameters = (NewCallActionParameters)Parameters;
try
{
this.Host.AddEvent("New call processing, ID= " + actionParameters.Id);
using (SqlConnection cn = new SqlConnection(this.Host.DatabaseConnectionString))
{
cn.Open();
CallItems CallItems = CallItems.Instance(cn);
SqlCommand cmd = CallItems.GetCommand("SELECT ID, Originator, Dialnumber,
CallDateTime, CallSeconds, CallType FROM viCalls WHERE ID=@callid");
cmd.Parameters.AddWithValue("@callid", actionParameters.Id);
using (SqlDataReader rs = cmd.ExecuteReader())
{
if (rs.Read())
{
if (rs.GetInt16(5) == CALLTYPE_INTERNATIONAL &&
rs.GetInt32(4) > MAX_CALL_DURATION_S &&
(((rs.GetDateTime(3).TimeOfDay > END_OF_WORK ||
rs.GetDateTime(3).TimeOfDay < BEGINNING_OF_WORK)) ||
(rs.GetDateTime(3).DayOfWeek == DayOfWeek.Sunday ||
rs.GetDateTime(3).DayOfWeek == DayOfWeek.Saturday)))
this.Host.SendMail("", "Fraud Detection system", "Suspicious call detected. ID=" + actionParameters.Id + " CallDateTime=" + rs.GetDateTime(3) + " Call duration=" + rs.GetInt32(4));
}
}
}
}
catch (Exception ex)
{
this.Host.AddEvent("Error running script: " + ex.ToString());
}
}
}
Для человека далекого от программирования приведенный выше код сценария может показаться совершенно непонятным. На самом деле, это не совсем так. В тексте сценария красным цветом выделены строки кода, в которых при необходимости возможно вносить изменения.
Рассмотрим первые четыре выделенных строки:
private int MAX_CALL_DURATION_S = 150;
private int CALLTYPE_INTERNATIONAL = 5;
private TimeSpan BEGINNING_OF_WORK = TimeSpan.Parse("08:00:00");
private TimeSpan END_OF_WORK = TimeSpan.Parse("19:00:00");
Эти строки объявляют четыре переменных:
- MAX_CALL_DURATION_S – это продолжительность разговора, равная 150 секунд, то есть 2 минуты 30 секунд. Вы можете изменить это значение на любое целое положительное число или 0.
- CALLTYPE_INTERNATIONAL – это тип вызова для международных разговоров, применяемых в Tariscope. Его значение равно 5. Если вы собираетесь рассматривать только международные вызовы, то не изменяйте это значение. Если вас интересуют другие вызовы, то определить их значение можно из документа Tariscope 4.6. Каталог баз данных.
- BEGINNING_OF_WORK – это время начала рабочего дня, которое здесь равно 8 часам утра. Вы можете изменить это значение на любое другое реальное значение времени начала рабочего дня
- END_OF_WORK – это время окончания рабочего дня, которое здесь равно 7 часов вечера. Вы можете изменить это значение на любое другое реальное значение времени истечения рабочего дня.
Следующая выделенная строка:
SELECT ID, Originator, Dialnumber, CallDateTime, CallSeconds, CallType FROM viCalls WHERE ID=@callid
Это SQL запрос к представлению viCalls на получение из него для текущего вызова, заданного условием ID=@callid , где @callid является параметром, содержащим идентификатор последнего вызова, который был обработан в Observer. Этот SQL запрос позволяет получить следующие поля:
- ID. Идентификатор записи.
- Originator. Телефонный номер, с которого был исполнен вызов.
- Dialnumber. Телефонный номер, на который был исполнен вызов.
- CallDateTime. Дата и время выполнения вызова.
- CallSeconds.Продолжительность вызова в секундах.
- CallType. Тип вызова.
При необходимости можно получить и другие параметры вызова из списка полей представления viCall.
Следующая выделенная часть сценария выполняет анализ данных на соответствие заданным условиям:
(rs.GetInt16(5) == CALLTYPE_INTERNATIONAL &&
rs.GetInt32(4) > MAX_CALL_DURATION_S &&
(((rs.GetDateTime(3).TimeOfDay > END_OF_WORK ||
rs.GetDateTime(3).TimeOfDay < BEGINNING_OF_WORK)) ||
(rs.GetDateTime(3).DayOfWeek == DayOfWeek.Sunday ||
rs.GetDateTime(3).DayOfWeek == DayOfWeek.Saturday)))
Этот код используется в операторе if в качестве условия соответствия данных. Он состоит из следующих условий:
rs.GetInt16(5) = CALLTYPE_INTERNATIONAL
Указывается значение 5-го поля запроса (поле CallType в SQL запросе). Отсчет полей начинается с 0. Значение поля сравнивается со значением переменной CALLTYPE_INTERNATIONAL. То есть это условие позволяет выявить, является ли этот вызов международным.
rs.GetInt32(4) > MAX_CALL_DURATION_S
Берется значение 4-го поля SQL запроса (поле CallSeconds). Отсчет значений начинается с 0. Значение поля сравнивается со значением переменной MAX_CALL_DURATION_S.
(rs.GetDateTime(3).TimeOfDay > END_OF_WORK ||
rs.GetDateTime(3).TimeOfDay < BEGINNING_OF_WORK))
В этом условии используется значение 3-го поля запроса, то есть поля CallDateTime. Проверяется, выпадает ли время вызова на промежуток времени между окончанием рабочего дня и началом следующего рабочего дня.
(rs.GetDateTime(3).DayOfWeek == DayOfWeek.Sunday ||
rs.GetDateTime(3).DayOfWeek == DayOfWeek.Saturday)
Это альтернативное условие времени вызова, которому должны соответствовать все международные вызовы продолжительностью более 150 секунд, выполненные в субботу или воскресенье.
Используя логические операторы && и || можно по-разному рассматривать соответствие вызова требуемым условиям.
Если результат проверки есть истина, то выполняется команда по отправке по электронной почте сообщения об этом вызове.
this.Host.SendMail("", "Fraud Detection system", "Suspicious call detected. ID=" + actionParameters.Id + " CallDateTime=" + rs.GetDateTime(3) + " Call duration=" + rs.GetInt32(4));
this.Host.SendMail() – это функция, с помощью которой отправляется сообщение по электронной почте. Эта функция имеет три параметра, которые находятся внутри скобок и разделяются запятыми:
- Первый параметр задает электронный адрес, куда отправляется сообщение. Если этот параметр пуст (""), как указано в приведенном выше выражении, то используется электронный адрес, указанный в настройке Tariscope Сообщение&почта. Если вы хотите отправлять сообщение на другой адрес, чем указанный на этой странице настройки или вы не настраивали этот параметр в Tariscope, то в кавычках следует задать этот адрес, например, "Этот адрес электронной почты защищён от спам-ботов. У вас должен быть включен JavaScript для просмотра.".
- Вторым параметром является тема электронного письма. В этом сценарии таким параметром является "Fraud Detection System". При желании можно заменить этот параметр, например, на "Получен вызов с признаками фрода" или какой-либо другой.
- Третий параметр – это содержимое текста сообщения. В данном сценарии это:
"Suspicious call detected. ID=" + actionParameters.Id + " CallDateTime=" + rs.GetDateTime(3) + " Call duration=" + rs.GetInt32(4) .
Рассмотрим более подробно эту строчку.
Часть строки "Suspicious call detected. ID=" можно заменить, например, на следующее:
“Обнаружен подозрительный вызов с идентификатором =” . Значение этого идентификатора находится в actionParameters.ID.
Следующая часть строки " CallDateTime=" + rs.GetDateTime(3) этого вызова. Возможно, будет лучше, если эту часть строки заменить на следующую:
“ Дата и время вызова: “ & rs.GetDateTime(3)
И, напоследок, выражение + "Call duration=" + rs.GetInt32(4) содержать длительность вызова. Также, для удобства восприятия информации, можно заменить эту часть строки:
“ Продолжительность вызова:” & rs.GetInt32(4)
В строке SQL запроса, который рассматривался выше, содержится запрос еще двух параметров: Originator и Dialnumber. Соответственно, их значение также возможно выводить в теле электронного письма. Для этого следует добавить следующую строчку:
“ Вызов выполнялся из номера ” & rs.GetInt32(1) “ на номер “ & rs.GetImt32(2)
Если модифицировать SQL запрос, то в сообщении можно выводить информацию об абоненте, из номера которого выполнялся вызов, наименование населенного пункта, куда выполнялся вызов и другую информацию.
Private decimal MAX_CALL_COST = 10.0
Теперь необходимо добавить в SQL запрос получение информации о стоимости вызова. Для этого следует воспользоваться описанием представления viCalls в документе "Каталог баз данных Tariscope 4.x", чтобы найти требуемое поле. Это поле Cost. Тогда запрос должен выглядеть следующим образом:
SELECT ID, Originator, Dialnumber, CallDateTime, CallSeconds, CallType, Cost FROM viCalls WHERE ID=@callid
Если нас не интересует продолжительность вызова, то из запроса можно исключить поле CallSeconds. И теперь, получив с помощью этого SQL запроса данные по вызову , следует их проанализировать на соответствие интересующих нас условий: международный вызов со стоимостью более 10 гривен. Для этого строку, где проводится анализ, следует записать следующим образом:
(rs.GetInt16(5) = CALLTYPE_INTERNATIONAL &&
rs.GetInt32(4)> MAX_CALL_DURATION_S &&
rs.GetDecimal(6) > 10.0) &&
(((rs.GetDateTime(3).TimeOfDay > END_OF_WORK ||
rs.GetDateTime(3).TimeOfDay < BEGINNING_OF_WORK)) ||
(rs.GetDateTime(3).DayOfWeek == DayOfWeek.Sunday ||
rs.GetDateTime(3).DayOfWeek == DayOfWeek.Saturday))
Эта строка предполагает, что запрос поля CallSeconds остался. В случае удаления в строке анализа данных изменится значение в скобках, указывающих на номер поля в запросе, начиная с 0.
Аналогичным образом можно продолжать усложнять условия для выявления вызовов с признаками фрода.
При использовании сценариев для дополнительной обработки данных вызовов всегда следует помнить, что это использование повышает нагрузку на сервер и может привести к замедлению обработки.
Помимо этого, если данные о вызовах поступают в Tariscope с задержкой, например при получении их через FTP сервер, то и сообщения о подозрительных вызовах также будут сформированы с задержкой.
Если приведенной выше информации вам недостаточно для создания необходимого сценария, обратитесь в службу поддержки SoftPI.