SMS - уведомления, smpp
если поможет, то вот основная идея
триггеры не умею и боюсь
хотя триггером было бы правильней
Код: Выделить всё
#!/usr/local/bin/php
<?php
//ini_set('display_errors',1);
$mysqlserver="localhost";
$mysqluser="****";
$mysqlpass="****";
$mysqldb="UTM5";
$time_min=15;
$link = mysql_connect ($mysqlserver, $mysqluser, $mysqlpass) or die("Can't connect: " . mysql_error());
mysql_select_db($mysqldb, $link);
//$set=mysql_query("SET NAMES latin1");
$nowdate=date("U");
$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($query) or trigger_error(mysql_error().$query);
while ($row = mysql_fetch_array($res, MYSQL_NUM)) {
//echo $row[1];
$a=$row[1];
$a=iconv('UTF-8', 'KOI8-R//IGNORE',$row[1]); // $row[0] - user_id $row[1] - строка сообщения, конвертируем её
//echo $a;
$tmp_str=explode(" осталось ",$a);// делим строку относительно \" осталось \"
$tmp_str2=explode(" ",$tmp_str[1]);// первую часть делим по пробелам
$uid=$row[0];
$balance=round($tmp_str2[0],2);
//$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($query2) or trigger_error(mysql_error().$query);
$row2 = mysql_fetch_array($res2, MYSQL_NUM);
$phone=$row2[0];
if ((isset($phone))&&($phone!==FALSE)) {
echo " user_id $uid balance $balance phone $phone\n";
system("/root/sms/sms-smpp.pl $phone $balance $uid");
}
}
//print_r($res);
?>

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

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

Код: Выделить всё
#!/usr/local/bin/perl -w
use DBI();
use HTML::Entities;
use URI::Escape;
use LWP::Simple;
$GLOBAL_CONFIG{'LOG_FILE'}= "/var/log/sms-" . time();
$GLOBAL_CONFIG{'DB_HOST'} = 'localhost';
$GLOBAL_CONFIG{'UTM_MAIN_DB'} = 'UTM5';
$GLOBAL_CONFIG{'DB_USER'} = 'XXXXXXXXXXXX';
$GLOBAL_CONFIG{'DB_PASS'} = 'YYYYYYYYYYYYYY';
$GLOBAL_CONFIG{'BALANCE_MIN'} = '20'; #нижняя граница баланса пользователя
$GLOBAL_CONFIG{'BALANCE_MAX'} = '160'; #верхняя --//--
$GLOBAL_CONFIG{'DAY_TO_BLOCK'}= '4'; #расчетное время до блокировки (дни)
$GLOBAL_CONFIG{'LAST_REMINDER'}='5'; #передичность отправки SMS (дни)
$GLOBAL_CONFIG{'SMS_SEND_PAUSE'}='5'; #пауза между попытками отправки SMS
$GLOBAL_CONFIG{'SMS_SEND_TRY'}= '5'; #количество попыток отправки
$GLOBAL_CONFIG{'KANNEL_USER'} = 'XXXXXXXXXXX'; #пользователь для отправки SMS
$GLOBAL_CONFIG{'KANNEL_PASS'}= 'YYYYYYYYYYYY'; #пароль
$GLOBAL_CONFIG{'KANNEL_HOST'}= '192.168.XX.XX:YYYY';#
$GLOBAL_CONFIG{'SMS_FROM'} = '=ПОДПИСЬ='; #подпись SMS
%DAYS = (
'0' => 'в течении дня',
'1' => 'через один день',
'2' => 'через два дня',
'3' => 'через три дня',
'4' => 'через четыре дня',
'5' => 'через пять дней',
'6' => 'через шесть дней');
#$GLOBAL_CONFIG{'SMS_TEXT'}="Товарищ _USER_NAME_!\nБаланс Вашего счета номер _ACCOUNT_ID_ равен\n_BALANCE_\nБлокировка лицевого счёта ожидается _DAY_BLOCK_";
#$GLOBAL_CONFIG{'SMS_TEXT'}="Уважаемый абонент, сообщаем, что баланс Вашего счета номер _ACCOUNT_ID_ равен\n_BALANCE_\nБлокировка доступа в Интернет ожидается _DAY_BLOCK_";
$GLOBAL_CONFIG{'SMS_TEXT'}="Баланс Вашего лицевого счета номер _ACCOUNT_ID_ равен _BALANCE_. Блокировка доступа в Интернет ожидается _DAY_BLOCK_";
sub DO_SELECT;
sub GET_FIELDS;
sub ADDITIONAL_ATR_SYNC;
sub ACCOUNTS_SELECT;
sub SMS_SEND;
#!!!проверить!!!
$DB = DBI->connect("DBI:mysql:$GLOBAL_CONFIG{'UTM_MAIN_DB'}:$GLOBAL_CONFIG{'DB_HOST'}",
$GLOBAL_CONFIG{'DB_USER'}, $GLOBAL_CONFIG{'DB_PASS'});
$DB->do("SET NAMES koi8r");
open(LOG,"> $GLOBAL_CONFIG{'LOG_FILE'}");
ADDITIONAL_ATR_SYNC(\$DB);
ACCOUNTS_SELECT(\$DB);
$DB->disconnect;
close (LOG);
exit;
#выбирает строку из таблицы
sub DO_SELECT {
my ($DataBase, $Result, $Query) = @_;
my $Sth;
# print "$Query\n";
$Sth=$$DataBase->prepare($Query);
$Sth->execute();
if (!($Sth->rows)) {
$Sth->finish;
return;
}
%{$Result} = %{$Sth->fetchrow_hashref};
$Sth->finish;
}
#выбирает множество строк из таблицы
sub GET_FIELDS {
my ($DataBase, $Result, $Query) = @_;
my ($Sth, $Line);
# print "$Query\n";
$Sth = $$DataBase->prepare($Query);
$Sth->execute();
while ($Line = $Sth->fetchrow_hashref ) {
push @{$Result}, $Line;
}
$Sth->finish;
}
#Синхронизвция "дополнительных параметров пользователя" параметры содержащие пустую строку - удаляются
sub ADDITIONAL_ATR_SYNC {
my ($DataBase) = @_;
my ($Query);
#Помечаем ЛС владельцы которых хотят получать SMS уведомления
$Query="UPDATE users_accounts SET last_reminder=1 WHERE uid IN
(select userid FROM user_additional_params WHERE paramid=1 AND value = '');";
$$DataBase->do($Query);
#Удаляем пустые дополнительные параметры
$Query="DELETE FROM user_additional_params WHERE value = '';";
$$DataBase->do($Query);
#Помечаем ЛС владельцы которых НЕ хотят получать SMS уведомления
$Query="UPDATE users_accounts SET last_reminder=0 WHERE uid IN
(select userid FROM user_additional_params WHERE paramid=1);";
$$DataBase->do($Query);
}
#Выборка данных для отправки SMS оповещения и вызов процедуры оправки SMS
sub ACCOUNTS_SELECT {
my ($DataBase) = @_;
my ($Query, %Time, %Last, $DayToBlock, $CountSMS, $ThresholdDate, @BalanceInfoList, $UserBalance, %UserId, %UserInfo) = ();
$CountSMS = 0;
$Query = "SELECT DAYOFMONTH(LAST_DAY(NOW())) AS day;";
DO_SELECT($DataBase, \%Last, $Query);
$Query = "SELECT UNIX_TIMESTAMP(NOW() - INTERVAL ".$GLOBAL_CONFIG{'LAST_REMINDER'}." DAY) AS threshold,
UNIX_TIMESTAMP() AS now;";
DO_SELECT($DataBase, \%Time, $Query);
$Query = "SELECT id, balance FROM accounts WHERE is_deleted=0 AND is_blocked=0 AND balance<".
$GLOBAL_CONFIG{'BALANCE_MAX'}." AND balance>".$GLOBAL_CONFIG{'BALANCE_MIN'};
#print $Query;
GET_FIELDS ($DataBase, \@BalanceInfoList, $Query);
foreach $UserBalance (@BalanceInfoList){
%PeriodServSum = ();
%UserId = ();
%UserInfo = ();
$Query = "SELECT uid FROM users_accounts WHERE account_id=".$$UserBalance{'id'}.
" AND last_reminder > 0 AND last_reminder <" . $Time{'threshold'};
DO_SELECT($DataBase, \%UserId, $Query);
if (!($UserId{'uid'})){
next;
}
$Query = "SELECT sum(cost) AS summ FROM periodic_services_data WHERE id IN" .
"(select service_id from service_links WHERE account_id = ".$$UserBalance{'id'}." AND is_deleted = 0);";
DO_SELECT($DataBase, \%PeriodServSum, $Query);
if ( !($PeriodServSum{'summ'})){
print (LOG "\tEE! BalanceID $$UserBalance{'id'}: Сумма переодических услуг равна нулю\n");
next;
}
$DayToBlock = ( ($$UserBalance{'balance'} * $Last{'day'}) / $PeriodServSum{'summ'} );
if ($DayToBlock > $GLOBAL_CONFIG{'DAY_TO_BLOCK'}){
next;
}
$Query = "SELECT full_name, mobile_telephone FROM users WHERE id=".$UserId{'uid'};
DO_SELECT($DataBase, \%UserInfo, $Query);
$UserInfo{'BalanceId'} = $$UserBalance{'id'};
$UserInfo{'balance'} = $$UserBalance{'balance'};
$UserInfo{'DayToBlock'}= $DayToBlock;
if ($SendFlag = SMS_SEND(\%UserInfo)){
if ($SendFlag < 0){
print (LOG "\tEE! KANNEL лежит. Не буду ничего больше слать\n");
last;
}
next;
}
$CountSMS++;
#Записываем дату отправки уведомления
$Query = "UPDATE users_accounts SET last_reminder=" . $Time{'now'} .
" WHERE account_id=" . $UserInfo{'BalanceId'};
$$DataBase->do($Query);
}
printf (LOG "\tОтправлено собщенией: %d\n", $CountSMS);
}
#отправка SMS
sub SMS_SEND {
my ($Info) = @_;
my ($TelNum, $Msg, $Balance, $Day, $DayToBlock, $EncodMsg, $Url, $Content);
if ( $$Info{'mobile_telephone'} =~ m/8[-_\s](9\d{2})[-_\s](\d{3})[-_\s](\d{2})[-_\s](\d{2})/){
$TelNum = "7$1$2$3$4";
} else {
print (LOG "\tEE! Не нравится мне этот номер $$Info{'mobile_telephone'}\n");
return 1 ;
}
$Day = int($$Info{'DayToBlock'});
$DayToBlock = $DAYS{"$Day"};
$Balance = sprintf("%.2f руб", $$Info{'balance'});
$Msg = $GLOBAL_CONFIG{'SMS_TEXT'};
$Msg =~ s/_USER_NAME_/$$Info{'full_name'}/;
$Msg =~ s/_ACCOUNT_ID_/$$Info{'BalanceId'}/;
$Msg =~ s/_BALANCE_/$Balance/;
$Msg =~ s/_DAY_BLOCK_/$DayToBlock/;
# print "--------------------SMS--------------------------\n";
# print "$Msg\n";
$EncodMsg = uri_escape( $Msg );
$Url='http://' . $GLOBAL_CONFIG{'KANNEL_HOST'} . '/cgi-bin/sendsms?user=' . $GLOBAL_CONFIG{'KANNEL_USER'} .
'&pass=' . $GLOBAL_CONFIG{'KANNEL_PASS'} . '&from=' . $GLOBAL_CONFIG{'SMS_FROM'} .
'&to=' . $TelNum . '&coding=2&charset=KOI8-R' . '&text=' . $EncodMsg;
# print "-------------------------------------------------\n";
$SendCount = $GLOBAL_CONFIG{'SMS_SEND_TRY'};
while ( $SendCount > 0) {
if ( ($Content = get $Url)){
last;
}
$SendCount--;
printf (LOG "\tEE! Не отправляется однако. %s, попытка %d\n", $TelNum, $GLOBAL_CONFIG{'SMS_SEND_TRY'} - $SendCount);
sleep (1);
}
sleep ($GLOBAL_CONFIG{'SMS_SEND_PAUSE'} + rand(2));
if ( $SendCount <=0){
return -1 ;
}
print (LOG "BalanceID: $$Info{'BalanceId'} tel.$TelNum уведомление отослано\n");
return 0;
}