Сергей Маликов
23.04.2020
26008

Автоматизированная проверка баланса и информирование звонком

В статье описан скрипт, запускающийся с заданным интервалом, проверяющего остаток на счете у какого-либо сервиса (на примере dadata, smsc.ru) и, при достижении установленного пограничного значения, информирующего о балансе с помощью звонка на заданный в скрипте номер. Проверить баланс можно с помощью отправляемого на сервер GET или POST запроса. Если сервис поддерживает такую возможность, то в […]

В статье описан скрипт, запускающийся с заданным интервалом, проверяющего остаток на счете у какого-либо сервиса (на примере dadata, smsc.ru) и, при достижении установленного пограничного значения, информирующего о балансе с помощью звонка на заданный в скрипте номер.

Проверить баланс можно с помощью отправляемого на сервер GET или POST запроса. Если сервис поддерживает такую возможность, то в документации будут описаны конкретные примеры с передаваемыми параметрами. Например, для получения баланса smsru необходимо отослать GET запрос вида:

https://sms.ru/my/balance?api_id=[ваш_api_id]&json=1

У некоторых сервисов для использования их API может потребоваться заключение договора. Для приведенных в примере сервисов dadata, smsru необходимо только зарегистрироваться и подтвердить свою учетную запись.

В статье использовались стандартные записи FreePBX из директории /var/lib/asterisk/sounds/ru/digits. Если у вас отсутствуют какие-либо файлы, озвучивающие цифры, разряды, названия валют, их необходимо предварительно записать и загрузить на сервер.

Создаем php скрипт (например, в /usr/local/bin) и устанавливаем права на запуск

cd /usr/local/bin

touch check_balance.php

chmod +x check_balance.php

nano check_balance.php

Создание файла, изменение прав
Создание файла, изменение прав

В скрипт будет передаваться два параметра. Первый – пороговое значение баланса, по достижении которого, будут создаваться call файлы и происходить автоинформирование, второй – имя сервиса (smsru|dadata|all).

Подробнее о call файлах – статья

Содержание скрипта:

<?php

//параметры token, secret – из личного кабинета dadata

$dadata_token=»pppppppppppppppppppppppppppppppppppppppp»; $dadata_secret=»pppppppppppppppppppppppppppppppppppppppp»;

//параметр api_id – из личного кабинета sms.ru

$smsru_api_id=» PPPPPPPP-PPPP-PPPP-PPPP-PPPPPPPPPPP»;

/*

Первый переданный в скрипт параметр- пороговое значение остатка средств на  балансе,с которого начинаются уведомления. Второй – имя сервиса или all

вызов функции, проверяющей остаток на счете.

*/

check_balance($argv[1], $argv[2]);

function check_balance($balance_threshold, $service=’all’){

switch ($service) {

                                   case ‘all’:

                                                                     get_dadata_balance($balance_threshold);

                                                                     sleep(15);

                                                                     get_smsru_balance($balance_threshold);

                                                                     break;

                                   case ‘smsru’:

                                                                     get_smsru_balance($balance_threshold);

                                                                     break;

                                   case ‘dadata’:

                                                                     get_dadata_balance($balance_threshold);

                                                                     break;

 }

}

/*

Функция, проверяющая баланс dadata. пороговое значение(balance_threshold) задается пользователем, параметры dadata_token, dadata_secret из ЛК. Если баланс ниже установленного порогового значения – создает call файл

*/

function get_dadata_balance($balance_threshold, $dadata_token, $dadata_secret

//отправляем get запрос к сервису

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, ‘https://dadata.ru/api/v2/profile/balance’);

curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

curl_setopt($ch, CURLOPT_CUSTOMREQUEST, ‘GET’);

$headers = array();

//токен авторизации

$headers[] = ‘Authorization: Token ‘ . $dadata_token;

//секретный ключ

$headers[] = ‘X-Secret: ‘ . $dadata_secret;

curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);

if (curl_errno($ch)) {

    echo ‘Error:’ . curl_error($ch);

}

curl_close($ch);

//полученную строку в формате json превращаем в ассоциативный массив

$balance = json_decode($result,true);

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

if($balance[‘balance’] <= $balance_threshold){

                                   generate_call_file($balance[‘balance’], «custom/dadata»);

                                   }

}

/*

Функция, проверяющая баланс сервиса smsru. Пороговое значение(balance_threshold) задается пользователем. Если баланс ниже установленного порогового значения – создает call файл

*/

function get_smsru_balance($balance_threshold, $smsru_api_id){

$body = file_get_contents(«https://sms.ru/my/balance?api_id=» . $smsru_api_id . «&json=1»);

 $json = json_decode($body,true);

if ($json) { // Получен ответ от сервера

      if ($json[‘status’] == «OK») { // Запрос выполнился

        // Ваш баланс $json[‘balance’];

                                   echo «SMSRU balance\r\n»;

                                   var_dump($json);

                                                                     if($json[‘balance’] <= $balance_threshold){

                                                                     generate_call_file($json[‘balance’], «custom/smsru»);

                                                                     }

    } else {

        // Запрос не выполнился

        // Код ошибки: $json[‘status_code’] Текст ошибки: $json[‘status_text’]

    }

} else {

        // Запрос не выполнился

}

}

  /*

Функция, генерирующая call файл. /var/spool/asterisk/outgoing/ — директория для call файлов по умолчанию. bal – текущий баланс. message – проигрываемое для сервиса сообщение перед озвучиванием баланса.

*/

function generate_call_file($bal, $message){

 $file_name = ‘alert’ . rand(0,100) . ‘.call’;

 $tmppath = ‘/root/’ . $file_name;

/* т.к. Asterisk постоянно отслеживает call файлы, их необходимо создавать в другой директории, иначе Asterisk может прочитать call файл, записанный наполовину */

$fp = fopen(«$tmppath», «w»);

$kopecks = 0;

$roubles = 0;

//если есть дробная часть

if(stripos($bal, ‘.’)){

                                   $bal_array = explode(«.», $bal);

                                   var_dump($bal_array);

                                   $roubles = $bal_array[0];

                                   $kopecks = $bal_array[1];

                                   if(strlen($kopecks) < 2){$kopecks .= ‘0’;}

                                   if(substr($kopecks,0,1) == 0){$kopecks = substr($kopecks,1);}

}else{

                                   $roubles = $bal;

}

/*определяем какие именно файлы будут проигрываться при озвучивании баланса

в voice_data будет строка вида custom/message&digits/20&digits/1000-i&digits/9&digits/roubley */

$voice_data =  $message . «&» . get_balance_voiced_files($roubles) .

«&digits/roubley»;

/* если есть копейки – добавляем соответствующие записи в список озвучиваемых файлов */

if($kopecks != 0){

                                   $voice_data .= «&» . get_balance_voiced_files($kopecks) . «&digits/kopeek»;

/*текст call файла определяем с помощью heredoc конструкции.

100 – номер, на который будет производиться вызов

300 – номер, с которого будет производиться вызов. После ответа на звонок – приложение Playback (воспроизведение сообщения о балансе)*/

$text = <<<STR

Channel: SIP/100

Callerid: 300

MaxRetries: 1

RetryTime: 60

WaitTime: 30

Application: Playback

Data: $voice_data

STR;

  //записываем файл во временную директорию

fwrite($fp, $text);

  // закрываем

fclose($fp);

//указываем директорию, в которой Asterisk отслеживает появление call файлов

$dstpath = ‘/var/spool/asterisk/outgoing/’ . $file_name;

  // копируем туда call файл

copy($tmppath, $dstpath);

move_uploaded_file($tmppath, $dstpath);

unlink($tmppath);

  //устанавливаем пользователя, группу, права

chown($dstpath, ‘asterisk’);

chgrp($dstpath, 495);

chmod($dstpath, 0644);

 

}

/* Функция, определяющая, какие файлы будут проигрываться при озвучивании

имеющегося остатка на балансе. напр. преобразует 20009 в строку с именами звуковых файлов — digits/20&digits/1000-i&digits/9 number — число(баланс), второй параметр — определяет была ли функция вызвана реккурсивно, для корректности возвращаемой строки */

function get_balance_voiced_files($number, $root=1){

                                   if($root and $number == 0){

                                                                     return «digits/» . $number . «&»;

                                   }elseif($number < 0){

                                                                     return «custom/minus&» . get_balance_voiced_files(substr($number,1), 0);

                                   }

                                   else{

                                   switch (strlen($number)) {

                                                                     case 0:

                                                                                                        return ;

                                                                                                        break;

                                                                     case 1:

                                                                                                        if($number != 0){

                                                                                                        return «digits/» . $number;

                                                                                                        }

                                                                                                        else return;

                                                                                                        break;

                                                                     case 2:

                                                                                                        if(substr($number,0,1) == 0){

                                                                                                                                           //нет десятков

                                                                                                                                           return get_balance_voiced_files(substr($number,1), 0);

                                                                                                        }elseif($number > 20){

                                                                                                                                           //числа > 20

                                                                                                                                           return «digits/» . substr($number,0,1) . «0» . «&» . get_balance_voiced_files(substr($number,1), 0);

                                                                                                        }else{

                                                                                                                                           //числа 10-20

                                                                                                                                           return «digits/» . $number;

                                                                                                        }

                                                                                                        break;

                                                                     case 3:

                                                                                                        if(substr($number,0,1) != 0){

  //есть сотни

                                                                                                                                           return «digits/» . substr($number,0,1) . «00» . «&»  . get_balance_voiced_files(substr($number,1), 0);

                                                                                                        }else{

                                                                                                                                           return get_balance_voiced_files(substr($number,1), 0);

                                                                                                        }

                                                                                                        break;

                                                                     case 4:

                                                                                                        if(substr($number,0,1) == 0 ){

                                                                                                                                           return «digits/1000-i» . «&» . get_balance_voiced_files(substr($number,1), 0);

                                                                                                        }elseif(substr($number,0,1) == 1){

                                                                                                                                           return «digits/» . 1000 . «&»  . get_balance_voiced_files(substr($number,1), 0);

                                                                                                        }elseif(substr($number,0,1) == 2){

                                                                                                                                           return «digits/» . 2000 . «&»  . get_balance_voiced_files(substr($number,1), 0);

                                                                                                        }else{

                                   return «digits/» . substr($number,0,1) . «&» . «digits/1000-i» . «&»  . get_balance_voiced_files(substr($number,1), 0);

                        }

                                                                                                        break;

                                                                     case 5:

                                                                                                        if(substr($number,0,2) < 11 or substr($number,0,2) > 19){

                                //числа 10XXX и 20000+

                                return «digits/» . substr($number,0,1) . «0» . «&» . get_balance_voiced_files(substr($number,1), 0);

                        }else{

                                //числа 11000-19999

                                return «digits/» . substr($number,0,2) . «&» . «digits/1000-i» . «&»  . get_balance_voiced_files(substr($number,2), 0);

                        }

                        break;                                                         

                                                                     }

                                   }

  }

  ?>

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

Для автоматизации проверки в crontab необходимо добавить задание и указать периодичность его запуска. Выполняем команду:

crontab -e

Добавляем задание. Например: запуск скрипта, проверяющего баланс на всех сервисах каждый час, установленное пороговое значение — 1000:

0 */1 * * * /usr/bin/php /usr/local/bin/check_balance.php 1000 all

Если для редактирования заданий в crontab используется редактор  vi – см. статью с основными командами

Добавление задания в crontab
Добавление задания в crontab

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

Звонок автоинформатора о балансе в консоли
Звонок автоинформатора о балансе в консоли
Подписаться
Уведомить о
guest
0 комментариев
Межтекстовые Отзывы
Посмотреть все комментарии

Остались вопросы?

Я - Виталий Шелест, менеджер компании Voxlink. Хотите уточнить детали или готовы оставить заявку? Укажите номер телефона, я перезвоню в течение 3-х секунд.

VoIP оборудование

ближайшие курсы

ближайшие Вебинары

ONLINE

10 доводов в пользу Asterisk

Распространяется бесплатно.

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

Безопасен в использовании.

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

Надежен в эксплуатации.

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

Гибкий в настройке.

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

Имеет огромный функционал.

Во многом именно Asterisk показал какой должна быть современная телефонная станция. За многие годы развития функциональность Asterisk расширилась, а все основные возможности по-прежнему доступны бесплатно сразу после установки.

Интегрируется с любыми системами.

То, что Asterisk не умеет сам, он позволяет реализовать за счет интеграции. Это могут быть интеграции с коммерческими телефонными станциями, CRM, ERP системами, биллингом, сервисами колл-трекинга, колл-бэка и модулями статистики и аналитики.

Позволяет телефонизировать офис за считанные часы.

В нашей практике были проекты, реализованные за один рабочий день. Это значит, что утром к нам обращался клиент, а уже через несколько часов он пользовался новой IP-АТС. Безусловно, такая скорость редкость, ведь АТС – инструмент зарабатывания денег для многих компаний и спешка во внедрении не уместна. Но в случае острой необходимости Asterisk готов к быстрому старту.

Отличная масштабируемость.

Очень утомительно постоянно возвращаться к одному и тому же вопросу. Такое часто бывает в случае некачественного исполнения работ или выбора заведомо неподходящего бизнес-решения. С Asterisk точно не будет такой проблемы! Телефонная станция, построенная на Asterisk может быть масштабируема до немыслимых размеров. Главное – правильно подобрать оборудование.

Повышает управляемость бизнеса.

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

Снижает расходы на связь.

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