API библиотека для Delphi

Скачать файл библиотеки: smsc_api.pas

Исходный код библиотеки: // BILLING.SMSTRAF.RU API для Delphi (billing.smstraf.ru) версия 3.1 (05.03.2015)
unit smsc_api;

interface

uses IdHTTP, IdURI, IdMessage, IdSMTP, IdStrings, IdGlobal, IdGlobalProtocols, StrUtils, SysUtils,
   
Forms, Classes, DateUtils, Types, Windows, IdMultipartFormData;

var
   
SMSC_POST: Boolean = False;                // использовать метод POST

const
   
// Константы с параметрами отправки
   
SMSC_LOGIN: String = 'login';            // логин клиента
   
SMSC_PASSWORD: String = 'password';        // пароль или MD5-хеш пароля в нижнем регистре
   
SMSC_CHARSET: String =    {$IFDEF UNICODE}// кодировка сообщения (utf-8 или koi8-r), по умолчанию используется windows-1251
                           
'utf-8'
                           
{$ELSE}
                           
'windows-1251'
                           
{$ENDIF};
   
SMSC_DEBUG: Boolean = False;            // флаг отладки

    // Константы для отправки SMS по SMTP
   
SMTP_FROM: String = 'api@billing.smstraf.ru';        // e-mail адрес отправителя
   
SMTP_SERVER: String = 'send.billing.smstraf.ru';    // адрес smtp сервера
   
SMTP_LOGIN: String = '';                // логин для smtp сервера
   
SMTP_PASSWORD: String = '';                // пароль для smtp сервера

type
    SMSC
= class
    public
       
D2Res: array of TStringDynArray;
       
// Общедоступные методы класса SMSС
       
function send_sms(phones: String; mes: String; translit: Integer = 0; time: String = ''; id: Integer = 0; format: Integer = 0; sender: String = ''; query: String = ''; files: TStringList = nil): TStringDynArray;
       
procedure send_sms_mail(phones: String; mes: String; translit: Integer = 0; time: String = ''; id: Integer = 0; format: Integer = 0; senderid: String = '');
        function
get_sms_cost(phones: String; mes: String; translit: Integer = 0; format: Integer = 0; sender: String = ''; query: String = ''): TStringDynArray;
        function
get_status(id: String; phone: String; all: Integer = 0): TStringDynArray;
        function
get_balance: String;

    private
       
// Приватные методы класса SMSС
       
function _smsc_send_cmd(cmd: String; arg: String; files: TStringList = nil): TStringDynArray;
        function
_urlencode(str: String): String;
       
procedure _print_debug(str: String);
        function
_ifs(cond: Boolean; val1: String; val2: String): String;
   
end;

var
   
formats: array[0..9] of String = ('', 'flash=1', 'push=1', 'hlr=1', 'bin=1', 'bin=2', 'ping=1', 'mms=1', 'mail=1', 'call=1');

implementation

// Метод отправки SMS
//
// обязательные параметры:
//
// phones - список телефонов через запятую или точку с запятой
// mes - отправляемое сообщение
//
// необязательные параметры:
//
// translit - переводить или нет в транслит
// time - необходимое время доставки в виде строки (DDMMYYhhmm, h1-h2, 0ts, +m)
// id - идентификатор сообщения. Представляет собой 32-битное число в диапазоне от 1 до 2147483647.
// format - формат сообщения (0 - обычное sms, 1 - flash-sms, 2 - wap-push, 3 - hlr, 4 - bin, 5 - bin-hex, 6 - ping-sms, 7 - mms, 8 - mail, 9 - call)
// sender - имя отправителя (Sender ID). Для отключения Sender ID по умолчанию необходимо в качестве имени
// передать пустую строку или точку.
// query - строка дополнительных параметров, добавляемая в URL-запрос ('valid=01:00&maxsms=3')
// files - массив путей к файлам при отправке mms или e-mail сообщений
//
// возвращает массив (<id>, <количество sms>, <стоимость>, <баланс>) в случае успешной отправки
// либо (<id>, -<код ошибки>) в случае ошибки

function SMSC.send_sms(phones: String; mes: String; translit: Integer = 0; time: String = ''; id: Integer = 0; format: Integer = 0; sender: String = ''; query: String = ''; files: TStringList = nil): TStringDynArray;
begin
   
if files <> nil then
        SMSC_POST
:= true;

   
Result := _smsc_send_cmd('send', 'cost=3&phones=' + _urlencode(phones) + '&mes=' + _urlencode(mes) + '&id=' + IntToStr(id) + '&translit=' + IntToStr(translit) +
                           
_ifs(format > 0, '&' + formats[format], '') + _ifs(sender <> '', '&sender=' + _urlencode(sender), '') + _ifs(time <> '', '&time=' +
                           
_urlencode(time), '') + _ifs(query <> '', '&' + query, ''), files);

   
// (id, cnt, cost, balance) или (id, -error)

   
if SMSC_DEBUG then
       
if StrToInt(Result[1]) > 0 then
            _print_debug
('Сообщение отправлено успешно. ID: ' + Result[0] + ', всего SMS: ' + Result[1]
                        +
', стоимость: ' + Result[2] + ', баланс: ' + Result[3])
        else
           
_print_debug('Ошибка №' + Result[1][2] + ', ID: ' + Result[0]);
end;

// SMTP версия метода отправки SMS

procedure SMSC.send_sms_mail(phones: String; mes: String; translit: Integer = 0; time: String = ''; id: Integer = 0; format: Integer = 0; senderid: String = '');
var
   
msg: TIdMessage;
begin
    msg
:= TIdMessage.Create(nil);

   
with TIdSMTP.Create(nil) do
   
begin
        Port
:= 25;
       
Host := SMTP_SERVER;

           if
SMTP_LOGIN <> '' then
        begin
            Username
:= SMTP_LOGIN;
           
Password := SMTP_PASSWORD;
       
end;

       
msg.Recipients.EMailAddresses := 'send@send.billing.smstraf.ru';
       
msg.From.Address := SMTP_FROM;
       
msg.ContentType := 'text/plain';
       
msg.CharSet := SMSC_CHARSET;
       
SysLocale.PriLangID := LANG_SYSTEM_DEFAULT; // если не поставить, то Indy будет оборачивать в koi8-r заголовки
       
msg.Body.Add(SMSC_LOGIN + ':' + SMSC_PASSWORD + ':' + IntToStr(id) + ':' + time + ':' + IntToStr(translit) + ',' + IntToStr(format) + ',' + senderid + ':' + phones + ':' + mes);

       
Connect;
       
Send(msg);
       
Disconnect;
       
Destroy;
   
end;

   
msg.Destroy;
end;

// Метод получения стоимости SMS
//
// обязательные параметры:
//
// phones - список телефонов через запятую или точку с запятой
// message - отправляемое сообщение
//
// необязательные параметры:
//
// translit - переводить или нет в транслит
// format - формат сообщения (0 - обычное sms, 1 - flash-sms, 2 - wap-push, 3 - hlr, 4 - bin, 5 - bin-hex, 6 - ping-sms, 7 - mms, 8 - mail, 9 - call)
// sender - имя отправителя (Sender ID)
// query - строка дополнительных параметров, добавляемая в URL-запрос ('list=79999999999:Ваш пароль: 123'#13#10 + '78888888888:Ваш пароль: 456')
//
// возвращает массив (<стоимость>, <количество sms>) либо (0, -<код ошибки>) в случае ошибки

function SMSC.get_sms_cost(phones: String; mes: String; translit: Integer = 0; format: Integer = 0; sender: String = ''; query: String = ''): TStringDynArray;
begin
    Result
:= _smsc_send_cmd('send', 'cost=1&phones=' + _urlencode(phones) + '&mes=' + _urlencode(mes) + '&translit=' + IntToStr(translit) +
                           
_ifs(format > 0, '&' + formats[format], '') + _ifs(sender <> '', '&sender=' + _urlencode(sender), '') + _ifs(query <> '', '&' + query, ''));

   
// (cost, cnt) или (0, -error)

   
if SMSC_DEBUG then
       
if StrToInt(Result[1]) > 0 then
            _print_debug
('Стоимость рассылки: ' + Result[0] + '. Всего SMS: ' + Result[1])
        else
           
_print_debug('Ошибка №' + Result[1][2]);
end;

// Метод проверки статуса отправленного SMS или HLR-запроса
//
// id - ID cообщения или список ID через запятую
// phone - номер телефона или список номеров через запятую
// all - вернуть все данные отправленного SMS, включая текст сообщения (0,1 или 2)
//
// возвращает массив (для множественного запроса возвращается массив с единственным элементом, равным 1. В этом случае статусы сохраняются в
//                    двумерном динамическом массиве класса D2Res):
//
// для одиночного SMS-сообщения:
// (<статус>, <время изменения>, <код ошибки доставки>)
//
// для HLR-запроса:
// (<статус>, <время изменения>, <код ошибки sms>, <код IMSI SIM-карты>, <номер сервис-центра>, <код страны регистрации>, <код оператора>,
// <название страны регистрации>, <название оператора>, <название роуминговой страны>, <название роумингового оператора>)
//
// при all = 1 дополнительно возвращаются элементы в конце массива:
// (<время отправки>, <номер телефона>, <стоимость>, <sender id>, <название статуса>, <текст сообщения>)
//
// при all = 2 дополнительно возвращаются элементы <страна>, <оператор> и <регион>
//
// при множественном запросе (данные по статусам сохраняются в двумерном массиве D2Res):
// если all = 0, то для каждого сообщения или HLR-запроса дополнительно возвращается <ID сообщения> и <номер телефона>
//
// если all = 1 или all = 2, то в ответ добавляется <ID сообщения>
//
// либо массив (0, -<код ошибки>) в случае ошибки

function SMSC.get_status(id: String; phone: String; all: Integer = 0): TStringDynArray;
var
   
ans: String;
   
TZInfo: TIME_ZONE_INFORMATION;
   
i, idx: Integer;
begin

    Result
:= _smsc_send_cmd('status', 'phone=' + _urlencode(phone) + '&id=' + _urlencode(id) + '&all=' + IntToStr(all));

   
// (status, time, err, ...) или (0, -error)

   
if Pos(',', id) = 0 then
    begin
       
if SMSC_DEBUG then
           
if (Result[1] <> '') and (StrToInt(Result[1]) >= 0) then
            begin
                ans
:= 'Статус SMS = ' + Result[0];
               
GetTimeZoneInformation(TZInfo);

                if
StrToInt(Result[1]) > 0 then
                    ans
:= ans + ', время изменения статуса - ' + DateTimeToStr(UnixToDateTime(StrToInt64(Result[1]) - TZInfo.Bias * 60));

               
_print_debug(ans);
           
end
           
else
               
_print_debug('Ошибка №' + Result[1][2]);

       
idx := StrToInt(_ifs(all = 1, '9', '12'));

        if (
all > 0) and (Length(Result) > idx) and ((Length(Result) < idx + 5) or (Result[idx + 5] <> 'HLR')) then
        begin
            ans
:= '';

            for
i := 0 to Length(Result) - 1 do
               
ans := ans + Result[i] + _ifs(i = Length(Result) - 1, '', ',');

           
SetLength(Result, idx);
            for
i := 0 to idx - 2 do
               
IdStrings.SplitString(ans, ',', Result[i], ans);

           
Result[idx - 1] := ans;
       
end;
   
end
   
else
   
begin
       
if (Length(Result) = 1) and (Pos('-', Result[0]) = 3) then
            Result
:= StrUtils.SplitString(Result[0], ',')
        else
       
begin
            SetLength
(D2Res, 0);
           
SetLength(D2Res, Length(Result));

            for
i := 0 to Length(D2Res) - 1 do
               
D2Res[i] := StrUtils.SplitString(Result[i], ',');

           
SetLength(Result, 1);
           
Result[0] := '1';
       
end;
   
end;
end;

// Метод получения баланса
//
// без параметров
//
// возвращает баланс в виде строки или пустую строку в случае ошибки

function SMSC.get_balance: String;
var
   
bal: TStringDynArray;
begin
    bal
:= _smsc_send_cmd('balance', ''); // (balance) или (0, -error)

   
if SMSC_DEBUG then
       
if Length(bal) = 1 then
            _print_debug
('Сумма на счете: ' + bal[0])
        else
           
_print_debug('Ошибка №' + bal[1][2]);

    if
Length(bal) = 1 then
        Result
:= bal[0]
    else
       
Result := '';
end;

// ПРИВАТНЫЕ МЕТОДЫ
//
// Метод вызова запроса. Формирует URL и делает 3 попытки чтения

function SMSC._smsc_send_cmd(cmd: String; arg: String; files: TStringList = nil): TStringDynArray;
var
   
par: TIdMultiPartFormDataStream;
   
params: TStringDynArray;
   
aurl, s, delim, VLeft, VRight: String;
   
cnt, i: Integer;
   
pf: TIdFormDataField;

begin
    arg
:= 'login=' + _urlencode(SMSC_LOGIN) + '&psw=' + _urlencode(SMSC_PASSWORD) + '&fmt=1&charset=' + SMSC_CHARSET + '&' + arg;
   
aurl := 'http://billing.smstraf.ru/sys/' + cmd + '.php';

   
with TIdHTTP.Create(nil) do
   
begin
        cnt
:= 0;

       
repeat
           
if cnt > 0 then Sleep(2000 + 1000 * cnt);

            if (
cnt = 2) then
            aurl
:= StringReplace(aurl, 'billing.smstraf.ru', 'www2.billing.smstraf.ru', [rfReplaceAll]);

            try
                if
SMSC_POST then
                begin
                    par
:= TIdMultiPartFormDataStream.Create;

                    for
i := 1 to files.Count do
                       
par.AddFile('File' + IntToStr(i), files.Strings[i-1], 'application/octet-stream');

                   
params := StrUtils.SplitString(arg, '&');

                    for
i := 1 to Length(params) do
                   
begin
                        IdStrings
.SplitString(params[i-1], '=', VLeft, VRight);
                       
pf := par.AddFormField(VLeft, VRight);
                       
pf.Charset := SMSC_CHARSET;
                       
pf.ContentTransfer := 'binary';
                   
end;

                   
s := Post(aurl, par);

                   
par.Destroy;
               
end
               
else
                     
s := Get(aurl + '?' + arg);
           
except
                s
:= '';
           
end;

           
Inc(cnt);
       
until (s <> '') or (cnt = 4);

        if
s = '' then
        begin
           
if SMSC_DEBUG then
                _print_debug
('Ошибка чтения адреса: ' + aurl + '?' + arg);

           
s := ','; // фиктивный ответ
       
end;

       
Destroy;
   
end;

   
delim := ',';

    if
cmd = 'status' then
    begin
        params
:= StrUtils.SplitString(arg, '&');

        for
i := 0 to Length(params) - 1 do
       
begin
            IdStrings
.SplitString(params[i], '=', VLeft, VRight);

            if (
VLeft = 'id') and (Pos('%2C', VRight) > 0) then // запятая в id - множественный запрос
               
delim := #10;
       
end;
   
end;

   
Result := StrUtils.SplitString(s, delim);
end;

// кодирование параметра в http-запросе

function SMSC._urlencode(str: String): String;
var
   
EncodeStr, UnsafeChars: String;
   
UStr: UTF8String;
   
i, j: Integer;

begin
    UnsafeChars
:= '!"#%&''*,:;<=>?[]^`{|} ';
   
EncodeStr := '';

    if
SMSC_POST then
        Result
:= str
   
else
   
begin
       
for i := 1 to Length(str) do
            if (
CharIsInSet(str, i, UnsafeChars) or not CharIsInSet(str, i, CharRange(Char(33), Char(126)))) then
            begin
                UStr
:= UTF8String(str[i]);

                for
j := 1 to Length(UStr) do
                   
EncodeStr := EncodeStr + '%' + IntToHex(Byte(UStr[j]), 2);
           
end
           
else
               
EncodeStr := EncodeStr + str[i];

       
Result := EncodeStr;
   
end;
end;

// вывод отладочной информации

procedure SMSC._print_debug(str: String);
begin
    with Application
do MessageBox(PChar(str), '');
end;

function
SMSC._ifs(cond: Boolean; val1: String; val2: String): String;
begin
   
if cond then
        Result
:= val1
   
else
       
Result := val2;
end;

end.

// Examples:
// var
// sms: SMSC;
// ret: TStringDynArray;
// balance: String;
// begin
// sms := SMSC.Create;
// ret := sms.send_sms('79999999999', 'Ваш пароль: 123', 1);
// ret := sms.send_sms('79999999999', 'http://billing.smstraf.ru'#13#10 + 'BILLING.SMSTRAF.RU', 0, '', 0, 0, '', 'maxsms=3');
// ret := sms.send_sms('79999999999', '0605040B8423F0DC0601AE02056A0045C60C036D79736974652E72750001036D7973697465000101', 0, '', 0, 5);
// ret := sms.send_sms('79999999999', '', 0, '', 0, 3);
// ret := sms.send_sms('dest@mysite.com', 'Ваш пароль: 123', 0, 0, 0, 8, 'source@mysite.com', 'subj=Confirmation');
// ret := sms.get_sms_cost('79999999999', 'Вы успешно зарегистрированы!');
// sms.send_sms_mail('79999999999', 'Ваш пароль: 123', 0, '0101121000', 0, 1);
// ret := sms.get_status(12345, '79999999999');
// balance := sms.get_balance;
// sms.Destroy;
// end;

Пример использования библиотеки: uses smsc_api;
...
var
sms: SMSC;
ret: TStringDynArray;
balance: String;
...
begin
...
sms := SMSC.Create;
...
ret := sms.send_sms('79999999999', 'Ваш пароль: 123', 1);
...
ret := sms.send_sms('79999999999', 'http://billing.smstraf.ru'#13#10 + 'BILLING.SMSTRAF.RU', 0, '', 0, 0, '', 'maxsms=3');
...
ret := sms.send_sms('79999999999', '0605040B8423F0DC0601AE02056A0045C60C036D79736974652E72750001036D7973697465000101', 0, '', 0, 5);
...
ret := sms.send_sms('79999999999', '', 0, '', 0, 3);
...
ret := sms.get_sms_cost('79999999999', 'Вы успешно зарегистрированы!');
...
ret := sms.get_status(12345, '79999999999');
...
balance := sms.get_balance;
...
// отправка SMS через e-mail
sms.send_sms_mail('79999999999', 'Ваш пароль: 123');
...
sms.Destroy;
...
end;




Добавлена новая услуга отправки цифровых кодов в номере телефонного звонка
06.06.2017
В нашем сервисе появилась новая услуга — Отправка кодов в телефонном номере, позволяющая осуществлять рассылку цифровых кодов для подтверждения определенных операций с помощью телефонного номера, что намного дешевле, чем отправка кодов в SMS-сообщениях. Передача кода при таком способе осуществляется в номере телефона входящего звонка и не требует прослушивания голосового сообщения абонентом.
подробнее