SMS - уведомления, smpp

Технические вопросы по UTM 5.0
Аватара пользователя
Magnum72
Сообщения: 1947
Зарегистрирован: Чт сен 22, 2005 06:54
Контактная информация:

Сообщение Magnum72 »

Да там нечего делать, ставишь триггеры на таблицы, которые будет заполнять табличку сообщений который надо отправить по смс, далее скрипт который по крону выбирает новые записи и отправляет на smpp шлюз (15 строчек на php)

Pulse
Сообщения: 945
Зарегистрирован: Вт окт 03, 2006 12:58

Сообщение Pulse »

на триггер мозгов не хватило, но раз в 15 минут делаю выборку из таблицы сообщений....
P.S. хотя гораздо проще было бы если бы разработчики вместо отправки сообщения предусмотрели бы это событие в аффекторе.

kirush
Сообщения: 699
Зарегистрирован: Пт фев 04, 2005 13:58

Сообщение kirush »

так кто готов выполнить работу под ключ?
Программеров в штате нет ;(

Pulse
Сообщения: 945
Зарегистрирован: Вт окт 03, 2006 12:58

Сообщение Pulse »

если поможет, то вот основная идея

Код: Выделить всё

#!/usr/local/bin/php
<?php
//ini_set&#40;'display_errors',1&#41;;
$mysqlserver="localhost";
$mysqluser="****";
$mysqlpass="****";
$mysqldb="UTM5";
$time_min=15;

$link = mysql_connect &#40;$mysqlserver, $mysqluser, $mysqlpass&#41; or die&#40;"Can't connect&#58; " . mysql_error&#40;&#41;&#41;;
mysql_select_db&#40;$mysqldb, $link&#41;;
//$set=mysql_query&#40;"SET NAMES latin1"&#41;;
$nowdate=date&#40;"U"&#41;;


$query="select receiver_id,message from messages where send_date>$nowdate-360*60 and is_for_all<>1 and sender_id=0";

//oOCecho $query;
$res=mysql_query&#40;$query&#41; or trigger_error&#40;mysql_error&#40;&#41;.$query&#41;;

while &#40;$row = mysql_fetch_array&#40;$res, MYSQL_NUM&#41;&#41; &#123;
    //echo $row&#91;1&#93;;
    $a=$row&#91;1&#93;;
    $a=iconv&#40;'UTF-8', 'KOI8-R//IGNORE',$row&#91;1&#93;&#41;; // $row&#91;0&#93; - user_id $row&#91;1&#93; - строка сообщения, конвертируем её
    //echo $a;
    $tmp_str=explode&#40;" осталось ",$a&#41;;// делим строку относительно \" осталось \"
    $tmp_str2=explode&#40;" ",$tmp_str&#91;1&#93;&#41;;// первую часть делим по пробелам
    $uid=$row&#91;0&#93;;
    $balance=round&#40;$tmp_str2&#91;0&#93;,2&#41;;

    //$query2="select mobile_telephone from users where basic_account=$acc";
    $query2="select user_contacts.contact
            from user_contacts,users
            where user_contacts.descr='sms' and users.id=user_contacts.uid and users.id=$uid and users.is_deleted!=1";
    $res2=mysql_query&#40;$query2&#41; or trigger_error&#40;mysql_error&#40;&#41;.$query&#41;;
    $row2 = mysql_fetch_array&#40;$res2, MYSQL_NUM&#41;;
    $phone=$row2&#91;0&#93;;
    if &#40;&#40;isset&#40;$phone&#41;&#41;&&&#40;$phone!==FALSE&#41;&#41; &#123;
        echo " user_id $uid balance $balance phone $phone\n";
        system&#40;"/root/sms/sms-smpp.pl $phone $balance $uid"&#41;;
    &#125;
&#125;
//print_r&#40;$res&#41;;

?>
триггеры не умею и боюсь :) хотя триггером было бы правильней

Arti
Сообщения: 266
Зарегистрирован: Пн окт 01, 2007 02:44

Сообщение Arti »

Да триггеры на мой взгляд не особо нужны. Врядли Вы будете отсылать SMS в 4 часа ночи ;)

У меня сверх простой вариант: В таблице аккаунтов дополнительное поле - время последнего оповещения, дополнительный параметр (ID 1) определяет пользователей которым не нужно ничего оправлять.

Дёргается из крона несколько раз в день. Уведомления оправляется владельцам аккаунтов, баланса которых хватит на время меньшее чем DAY_TO_BLOCK, расчитывается по сумме периодических услуг и уведомлене которым оправлялось позже чем LAST_REMINDER дней назад. После зачисления платежа можно устанавливать в 1 (или значение меньшее чем текущее_время - LAST_REMINDER ) время последней оправки, также можно учитывать поле кредит.... короче солится по-вкусу ;).

Код: Выделить всё

#!/usr/local/bin/perl -w                                                                                                                                     
                                                                                                                                                             
use DBI&#40;&#41;;                                                                                                                                                   
                                                                                                                                                             
use HTML&#58;&#58;Entities;                                                                                                                                          
use URI&#58;&#58;Escape;                                                                                                                                             
use LWP&#58;&#58;Simple;                                                                                                                                             

$GLOBAL_CONFIG&#123;'LOG_FILE'&#125;=     "/var/log/sms-" . time&#40;&#41;;

$GLOBAL_CONFIG&#123;'DB_HOST'&#125; =     'localhost';
$GLOBAL_CONFIG&#123;'UTM_MAIN_DB'&#125; = 'UTM5';     
$GLOBAL_CONFIG&#123;'DB_USER'&#125; =     'XXXXXXXXXXXX';     
$GLOBAL_CONFIG&#123;'DB_PASS'&#125; =     'YYYYYYYYYYYYYY';         

$GLOBAL_CONFIG&#123;'BALANCE_MIN'&#125; = '20';                   #нижняя граница баланса пользователя
$GLOBAL_CONFIG&#123;'BALANCE_MAX'&#125; = '160';                  #верхняя --//--                     
$GLOBAL_CONFIG&#123;'DAY_TO_BLOCK'&#125;= '4';                    #расчетное время до блокировки  &#40;дни&#41;
$GLOBAL_CONFIG&#123;'LAST_REMINDER'&#125;='5';                    #передичность отправки SMS &#40;дни&#41;     
$GLOBAL_CONFIG&#123;'SMS_SEND_PAUSE'&#125;='5';                   #пауза между попытками отправки SMS  
$GLOBAL_CONFIG&#123;'SMS_SEND_TRY'&#125;= '5';                    #количество попыток отправки         

$GLOBAL_CONFIG&#123;'KANNEL_USER'&#125; = 'XXXXXXXXXXX';             #пользователь для отправки SMS
$GLOBAL_CONFIG&#123;'KANNEL_PASS'&#125;=  'YYYYYYYYYYYY';         #пароль                       
$GLOBAL_CONFIG&#123;'KANNEL_HOST'&#125;=  '192.168.XX.XX&#58;YYYY';#                             
$GLOBAL_CONFIG&#123;'SMS_FROM'&#125; =    '=ПОДПИСЬ=';           #подпись SMS                  

%DAYS = &#40;
        '0' => 'в течении дня',
        '1' => 'через один день',
        '2' => 'через два дня',  
        '3' => 'через три дня',  
        '4' => 'через четыре дня',
        '5' => 'через пять дней', 
        '6' => 'через шесть дней'&#41;;

#$GLOBAL_CONFIG&#123;'SMS_TEXT'&#125;="Товарищ _USER_NAME_!\nБаланс Вашего счета номер _ACCOUNT_ID_ равен\n_BALANCE_\nБлокировка лицевого счёта ожидается _DAY_BLOCK_";
#$GLOBAL_CONFIG&#123;'SMS_TEXT'&#125;="Уважаемый абонент, сообщаем, что баланс Вашего счета номер _ACCOUNT_ID_ равен\n_BALANCE_\nБлокировка доступа в Интернет ожидается _DAY_BLOCK_";                                                                                                                                              
$GLOBAL_CONFIG&#123;'SMS_TEXT'&#125;="Баланс Вашего лицевого счета номер _ACCOUNT_ID_ равен _BALANCE_. Блокировка доступа в Интернет ожидается _DAY_BLOCK_";           

sub DO_SELECT;
sub GET_FIELDS;
sub ADDITIONAL_ATR_SYNC;
sub ACCOUNTS_SELECT;    
sub SMS_SEND;           



        #!!!проверить!!!
        $DB = DBI->connect&#40;"DBI&#58;mysql&#58;$GLOBAL_CONFIG&#123;'UTM_MAIN_DB'&#125;&#58;$GLOBAL_CONFIG&#123;'DB_HOST'&#125;",
                $GLOBAL_CONFIG&#123;'DB_USER'&#125;, $GLOBAL_CONFIG&#123;'DB_PASS'&#125;&#41;;                         
        $DB->do&#40;"SET NAMES koi8r"&#41;;                                                            

        open&#40;LOG,"> $GLOBAL_CONFIG&#123;'LOG_FILE'&#125;"&#41;;


        ADDITIONAL_ATR_SYNC&#40;\$DB&#41;;
        ACCOUNTS_SELECT&#40;\$DB&#41;;    

        $DB->disconnect;
        close &#40;LOG&#41;;    

        exit;


#выбирает строку  из таблицы
sub DO_SELECT &#123;             
        my &#40;$DataBase, $Result, $Query&#41; = @_;
        my $Sth;                             
#       print "$Query\n";                    
        $Sth=$$DataBase->prepare&#40;$Query&#41;;    
        $Sth->execute&#40;&#41;;                     
        if &#40;!&#40;$Sth->rows&#41;&#41; &#123;                 
              $Sth->finish;                  
              return;                        
        &#125;                                    
        %&#123;$Result&#125; = %&#123;$Sth->fetchrow_hashref&#125;;
        $Sth->finish;                          
&#125;                                              

#выбирает множество строк из таблицы
sub GET_FIELDS &#123;                    
        my &#40;$DataBase, $Result, $Query&#41; = @_;
        my &#40;$Sth, $Line&#41;;                    
#       print "$Query\n";                    
        $Sth = $$DataBase->prepare&#40;$Query&#41;;  
        $Sth->execute&#40;&#41;;                     
        while &#40;$Line = $Sth->fetchrow_hashref &#41; &#123;
                push @&#123;$Result&#125;, $Line;          
        &#125;                                        

        $Sth->finish;
&#125;                    

#Синхронизвция "дополнительных параметров пользователя" параметры содержащие пустую строку - удаляются
sub ADDITIONAL_ATR_SYNC &#123;                                                                             
        my &#40;$DataBase&#41; = @_;                                                                          
        my &#40;$Query&#41;;                                                                                  

        #Помечаем ЛС владельцы которых хотят получать SMS уведомления
        $Query="UPDATE users_accounts SET last_reminder=1 WHERE uid IN
                &#40;select userid FROM user_additional_params WHERE paramid=1 AND value = ''&#41;;";
        $$DataBase->do&#40;$Query&#41;;                                                              

        #Удаляем пустые дополнительные параметры
        $Query="DELETE FROM user_additional_params WHERE value = '';";
        $$DataBase->do&#40;$Query&#41;;                                       

        #Помечаем ЛС владельцы которых НЕ хотят получать SMS уведомления
        $Query="UPDATE users_accounts SET last_reminder=0 WHERE uid IN  
                &#40;select userid FROM user_additional_params WHERE paramid=1&#41;;";
        $$DataBase->do&#40;$Query&#41;;                                               
&#125;                                                                             

#Выборка данных для отправки SMS оповещения и вызов процедуры оправки SMS
sub ACCOUNTS_SELECT &#123;                                                    
        my &#40;$DataBase&#41; = @_;                                             
        my &#40;$Query, %Time, %Last, $DayToBlock, $CountSMS, $ThresholdDate, @BalanceInfoList, $UserBalance, %UserId, %UserInfo&#41; = &#40;&#41;;

        $CountSMS = 0;

        $Query = "SELECT DAYOFMONTH&#40;LAST_DAY&#40;NOW&#40;&#41;&#41;&#41; AS day;";
        DO_SELECT&#40;$DataBase, \%Last, $Query&#41;;                 


        $Query = "SELECT UNIX_TIMESTAMP&#40;NOW&#40;&#41; - INTERVAL ".$GLOBAL_CONFIG&#123;'LAST_REMINDER'&#125;." DAY&#41; AS threshold,
                  UNIX_TIMESTAMP&#40;&#41; AS now;";                                                                   
        DO_SELECT&#40;$DataBase, \%Time, $Query&#41;;                                                                  

        $Query = "SELECT id, balance FROM accounts WHERE is_deleted=0 AND is_blocked=0 AND  balance<".
                $GLOBAL_CONFIG&#123;'BALANCE_MAX'&#125;." AND balance>".$GLOBAL_CONFIG&#123;'BALANCE_MIN'&#125;;                                           

        #print $Query;
        GET_FIELDS &#40;$DataBase, \@BalanceInfoList, $Query&#41;;

        foreach $UserBalance &#40;@BalanceInfoList&#41;&#123;
                %PeriodServSum = &#40;&#41;;            
                %UserId   = &#40;&#41;;                 
                %UserInfo = &#40;&#41;;                 

                $Query = "SELECT uid FROM users_accounts WHERE account_id=".$$UserBalance&#123;'id'&#125;.
                " AND last_reminder > 0 AND last_reminder <" . $Time&#123;'threshold'&#125;;              
                DO_SELECT&#40;$DataBase, \%UserId, $Query&#41;;                                         

                if &#40;!&#40;$UserId&#123;'uid'&#125;&#41;&#41;&#123;
                        next;          
                &#125;                      

                $Query = "SELECT sum&#40;cost&#41; AS summ FROM periodic_services_data WHERE id IN" .
                "&#40;select service_id from service_links WHERE account_id = ".$$UserBalance&#123;'id'&#125;." AND is_deleted = 0&#41;;";
                DO_SELECT&#40;$DataBase, \%PeriodServSum, $Query&#41;;                                                          

                if &#40; !&#40;$PeriodServSum&#123;'summ'&#125;&#41;&#41;&#123;
                        print &#40;LOG "\tEE! BalanceID $$UserBalance&#123;'id'&#125;&#58;  Сумма переодических услуг равна нулю\n"&#41;;
                        next;                                                                                      
                &#125;                                                                                                  

                $DayToBlock = &#40; &#40;$$UserBalance&#123;'balance'&#125; * $Last&#123;'day'&#125;&#41; / $PeriodServSum&#123;'summ'&#125; &#41;;
                if &#40;$DayToBlock > $GLOBAL_CONFIG&#123;'DAY_TO_BLOCK'&#125;&#41;&#123;                                   
                        next;                                                                        
                &#125;                                                                                    

                $Query = "SELECT full_name, mobile_telephone FROM users WHERE id=".$UserId&#123;'uid'&#125;;
                DO_SELECT&#40;$DataBase, \%UserInfo, $Query&#41;;                                         

                $UserInfo&#123;'BalanceId'&#125; = $$UserBalance&#123;'id'&#125;;
                $UserInfo&#123;'balance'&#125;   = $$UserBalance&#123;'balance'&#125;;
                $UserInfo&#123;'DayToBlock'&#125;= $DayToBlock;             
                if &#40;$SendFlag = SMS_SEND&#40;\%UserInfo&#41;&#41;&#123;            

                        if &#40;$SendFlag < 0&#41;&#123;
                                print &#40;LOG "\tEE! KANNEL лежит. Не буду ничего больше слать\n"&#41;;
                                last;                                                           
                        &#125;                                                                       
                        next;                                                                   
                &#125;                                                                               

                $CountSMS++;
                #Записываем дату отправки уведомления
                $Query = "UPDATE users_accounts SET last_reminder=" . $Time&#123;'now'&#125; .
                      " WHERE account_id=" . $UserInfo&#123;'BalanceId'&#125;;                
                $$DataBase->do&#40;$Query&#41;;                                             
        &#125;                                                                           

        printf &#40;LOG "\tОтправлено собщенией&#58; %d\n", $CountSMS&#41;;
&#125;                                                              

#отправка SMS
sub SMS_SEND &#123;
        my &#40;$Info&#41; = @_;
        my &#40;$TelNum, $Msg, $Balance, $Day, $DayToBlock, $EncodMsg, $Url, $Content&#41;;


        if &#40; $$Info&#123;'mobile_telephone'&#125; =~ m/8&#91;-_\s&#93;&#40;9\d&#123;2&#125;&#41;&#91;-_\s&#93;&#40;\d&#123;3&#125;&#41;&#91;-_\s&#93;&#40;\d&#123;2&#125;&#41;&#91;-_\s&#93;&#40;\d&#123;2&#125;&#41;/&#41;&#123;
                $TelNum = "7$1$2$3$4";
        &#125; else &#123;
                print &#40;LOG "\tEE! Не нравится мне этот номер $$Info&#123;'mobile_telephone'&#125;\n"&#41;;
                return 1 ;
        &#125;


        $Day = int&#40;$$Info&#123;'DayToBlock'&#125;&#41;;
        $DayToBlock = $DAYS&#123;"$Day"&#125;;
        $Balance = sprintf&#40;"%.2f руб", $$Info&#123;'balance'&#125;&#41;;
        $Msg = $GLOBAL_CONFIG&#123;'SMS_TEXT'&#125;;
        $Msg =~ s/_USER_NAME_/$$Info&#123;'full_name'&#125;/;
        $Msg =~ s/_ACCOUNT_ID_/$$Info&#123;'BalanceId'&#125;/;
        $Msg =~ s/_BALANCE_/$Balance/;
        $Msg =~ s/_DAY_BLOCK_/$DayToBlock/;

#       print "--------------------SMS--------------------------\n";
#       print "$Msg\n";
        $EncodMsg = uri_escape&#40; $Msg &#41;;

        $Url='http&#58;//' . $GLOBAL_CONFIG&#123;'KANNEL_HOST'&#125; . '/cgi-bin/sendsms?user=' . $GLOBAL_CONFIG&#123;'KANNEL_USER'&#125; .
                '&pass=' . $GLOBAL_CONFIG&#123;'KANNEL_PASS'&#125; . '&from=' . $GLOBAL_CONFIG&#123;'SMS_FROM'&#125; .
                '&to=' . $TelNum . '&coding=2&charset=KOI8-R' . '&text=' . $EncodMsg;

#       print "-------------------------------------------------\n";


        $SendCount = $GLOBAL_CONFIG&#123;'SMS_SEND_TRY'&#125;;

        while &#40; $SendCount > 0&#41; &#123;

                if &#40; &#40;$Content = get $Url&#41;&#41;&#123;
                last;
                &#125;

                $SendCount--;
                printf &#40;LOG "\tEE! Не отправляется однако. %s, попытка %d\n", $TelNum, $GLOBAL_CONFIG&#123;'SMS_SEND_TRY'&#125; - $SendCount&#41;;
                sleep &#40;1&#41;;
        &#125;

        sleep &#40;$GLOBAL_CONFIG&#123;'SMS_SEND_PAUSE'&#125; + rand&#40;2&#41;&#41;;

        if  &#40; $SendCount <=0&#41;&#123;
                return -1 ;
        &#125;

        print &#40;LOG "BalanceID&#58; $$Info&#123;'BalanceId'&#125; tel.$TelNum  уведомление отослано\n"&#41;;
        return 0;
&#125;


Puzan_aga
Сообщения: 105
Зарегистрирован: Чт сен 11, 2008 10:43

Сообщение Puzan_aga »

to Arti

А как у вас реализован шлюз. Через который отправляется смс ?

Pulse
Сообщения: 945
Зарегистрирован: Вт окт 03, 2006 12:58

Сообщение Pulse »

написано жэ KANNEL, кстати, неужели такая серьёзная нагрузка, что перловый скрипт не проканает?

Puzan_aga
Сообщения: 105
Зарегистрирован: Чт сен 11, 2008 10:43

Сообщение Puzan_aga »

Pulse писал(а):написано жэ KANNEL, кстати, неужели такая серьёзная нагрузка, что перловый скрипт не проканает?
я под вопроссом имел немнго другое.

Я спрашивал используется сторонний шлюз или свой(например usb модем с симкой)

Arti
Сообщения: 266
Зарегистрирован: Пн окт 01, 2007 02:44

Сообщение Arti »

Если вернутся к началу, то видно что изначально речь шла про smpp.

У оператора(подключение непосредственно к оператору сотовой связи) есть определённые требования для подключения. Например сообщения должны отправляться "пачкой" т.е. без разрыва сессии. KANNEL удовлетворяет требованиям.

Puzan_aga
Сообщения: 105
Зарегистрирован: Чт сен 11, 2008 10:43

Сообщение Puzan_aga »

Chris писал(а):У меня модем с симкой стоит )) сименсовский )))
Приветствую.

А не подскажеш как у тебя реализовано через модем.

Хотим купить USB флешку с симкой и реализовать расылку смс.

gil
Сообщения: 355
Зарегистрирован: Вт ноя 11, 2008 14:28

Сообщение gil »

Puzan_aga писал(а):Хотим купить USB флешку с симкой и реализовать расылку смс.
USB-флэшка вам мало чем поможет. Вот USB-модем - совсем другое дело.

Puzan_aga
Сообщения: 105
Зарегистрирован: Чт сен 11, 2008 10:43

Сообщение Puzan_aga »

gil писал(а):
Puzan_aga писал(а):Хотим купить USB флешку с симкой и реализовать расылку смс.
USB-флэшка вам мало чем поможет. Вот USB-модем - совсем другое дело.
Я просто описался :oops:

lancelot
Сообщения: 248
Зарегистрирован: Вс янв 23, 2005 16:28

Сообщение lancelot »

Arti возьметесь ли за внедрение подобной системы уведомления, за вознаграждение на нашем биллинге?

если да, пишите

sany_k @ mail.ru

Arti
Сообщения: 266
Зарегистрирован: Пн окт 01, 2007 02:44

Сообщение Arti »

Нет. Не возмусь.

lancelot
Сообщения: 248
Зарегистрирован: Вс янв 23, 2005 16:28

Сообщение lancelot »

жаль

денег не надо или времени нет или ответственность на себя не берете?

Ответить