API библиотека для C++ Builder

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

Исходный код библиотеки: // BILLING.SMSTRAF.RU API для C++ Builder (billing.smstraf.ru) версия 1.9 (05.03.2015)

#include <vcl.h>
#include <IdHTTP.hpp>
#include <IdMessage.hpp>
#include <IdSMTP.hpp>
#include <DateUtils.hpp>
#include <IdStrings.hpp>
# include <System.StrUtils.hpp>

// Константы с параметрами отправки
const char* SMSC_LOGIN = "login";            // логин клиента
const char* SMSC_PASSWORD = "password";        // пароль или MD5-хеш пароля в нижнем регистре
Boolean SMSC_POST = false;                    // использовать метод POST
const char* SMSC_CHARSET =
                           
#ifdef _DELPHI_STRING_UNICODE
                           
"utf-8";
                           
#else
                           
"windows-1251";
                           
#endif            // кодировка сообщения (utf-8 или koi8-r), по умолчанию используется windows-1251
const Boolean SMSC_DEBUG = false;            // флаг отладки

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

typedef DynamicArray < DynamicArray < String > > T2DStringDynArray;

class
SMSC {
public:
   
// Динамический двумерный строковый массив
   
T2DStringDynArray D2Res;

   
// Общедоступные методы класса SMSС
    //
    // Метод отправки 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>, -<код ошибки>) в случае ошибки

   
TStringDynArray send_sms(String phones, String mes, int translit = 0, String time = "", int id = 0, int format = 0, String sender = "", String query = "", TStringList *files = NULL)
    {
       
TStringDynArray m;

        if (
files != NULL)
           
SMSC_POST = true;

       
String formats[9] = {"flash=1", "push=1", "hlr=1", "bin=1", "bin=2", "ping=1", "mms=1", "mail=1", "call=1"};

       
m = _smsc_send_cmd("send", "cost=3&phones=" + _urlencode(phones) + "&mes=" + _urlencode(mes) + "&id=" + IntToStr(id) + "&translit=" + IntToStr(translit) +
                            (
format > 0 ? "&" + formats[format-1] : String("")) + (sender != "" ? "&sender=" + _urlencode(sender) : String("")) + (time != "" ? "&time=" +
                           
_urlencode(time) : String("")) + (query != "" ? "&" + query : String("")), files);

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

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

        return
m;
    }

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

   
void send_sms_mail(String phones, String mes, int translit = 0, String time = "", int id = 0, int format = 0, String senderid = "")
    {
       
TIdMessage* msg = new TIdMessage(0);
       
TIdSMTP* idsmtp = new TIdSMTP(0);

       
idsmtp->Port = 25;
       
idsmtp->Host = SMTP_SERVER;

        if (
SMTP_LOGIN != "") {
           
idsmtp->Username = SMTP_LOGIN;
           
idsmtp->Password = SMTP_PASSWORD;
        }

       
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 + String(':') + SMSC_PASSWORD + String(':') + IntToStr(id) + String(':') + time + String(':') + IntToStr(translit) + String(',') + IntToStr(format) + String(',') + senderid + String(':') + phones + String(':') + mes);

       
idsmtp->Connect();
       
idsmtp->Send(msg);
       
idsmtp->Disconnect();
       
idsmtp->Free();

       
msg->Free();
    }

   
// Метод получения стоимости 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\n78888888888:Ваш пароль: 456")
    //
    // возвращает массив (<стоимость>, <количество sms>) либо (0, -<код ошибки>) в случае ошибки

   
TStringDynArray get_sms_cost(String phones, String mes, int translit = 0, int format = 0, String sender = "", String query = "")
    {
       
TStringDynArray m;

       
String formats[9] = {"flash=1", "push=1", "hlr=1", "bin=1", "bin=2", "ping=1", "mms=1", "mail=1", "call=1"};

       
m = _smsc_send_cmd("send", "cost=1&phones=" + _urlencode(phones) + "&mes=" + _urlencode(mes) + "&translit=" + IntToStr(translit) +
                            (
format > 0 ? "&" + formats[format-1] : String("")) + (sender != "" ? "&sender=" + _urlencode(sender) : String("")) + (query != "" ? "&" + query : String("")));

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

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

        return
m;
    }

   
// Метод проверки статуса отправленного 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, -<код ошибки>) в случае ошибки

   
TStringDynArray get_status(String id, String phone, int all = 0)
    {
       
TIME_ZONE_INFORMATION TZInfo;
       
TStringDynArray m;
       
String ans;
       
int i;

       
m = _smsc_send_cmd("status", "phone=" + _urlencode(phone) + "&id=" + _urlencode(id) + "&all=" + IntToStr(all));

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

       
if (id.Pos(",") == 0) {
            if (
SMSC_DEBUG)
                if ((
m[1] != "") && (StrToInt(m[1]) >= 0))
                {
                   
String ans = "Статус SMS = " + m[0];
                   
GetTimeZoneInformation(&TZInfo);

                    if (
StrToInt(m[1]) > 0)
                       
ans = ans + ", время изменения статуса - " + DateTimeToStr(UnixToDateTime(StrToInt64(m[1]) - TZInfo.Bias * 60));
                   
_print_debug(ans);
                }
                else
                   
_print_debug("Ошибка №" + m[1].SubString(2, 1));

           
int idx = all == 1 ? 9 : 12;

            if (
all > 0 && m.Length > idx && (m.Length < idx + 5 || m[idx + 5] != "HLR"))
            {
               
ans = "";

                for (
i = 0; i < m.Length; i++)
                   
ans += m[i] + (i == m.Length - 1 ? "" : ",");

               
m.Length = idx;

                for (
i = 0; i < idx - 1; i++)
                   
SplitString(ans, ",", m[i], ans);

               
m[idx - 1] = ans;
            }
        }
        else {
            if (
m.Length == 1 && m[0].Pos("-") == 3)
                return
SplitString(m[0], ",");

           
D2Res.Length = 0;
           
D2Res.Length = m.Length;

            for (
i = 0; i < D2Res.Length; i++)
               
D2Res[i] = SplitString(m[i], ",");

           
m.Length = 1;
           
m[0] = "1";
        }

        return
m;
    }

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

   
String get_balance(void)
    {
       
TStringDynArray m;

       
m = _smsc_send_cmd("balance", ""); // (balance) или (0, -error)

       
if (SMSC_DEBUG)
            if (
m.Length == 1)
               
_print_debug("Сумма на счете: " + m[0]);
            else
               
_print_debug("Ошибка №" + m[1].SubString(2, 1));

        return
m.Length == 1 ? m[0] : String("");
    }

private:
   
// Приватные методы класса SMSС
    //
    // Метод вызова запроса. Формирует URL и делает 3 попытки чтения

   
TStringDynArray _smsc_send_cmd(String cmd, String arg, TStringList *files = NULL)
    {
       
TIdHTTP* idhttp = new TIdHTTP(0);
       
String s, delim, pl, pr;
       
int i, cnt = 0;

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

        do
        {
            if (
cnt > 0) Sleep(2000 + 1000 * cnt);

            if (
cnt == 2)
               
url = StringReplace(url, "billing.smstraf.ru", "www2.billing.smstraf.ru", TReplaceFlags() << rfReplaceAll);

            try {
                if (
SMSC_POST) {
                       
TIdMultiPartFormDataStream *par = new TIdMultiPartFormDataStream();

                        for (
i = 0; i < files->Count; i++)
                           
par->AddFile("File" + IntToStr(i), files->Strings[i], "application/octet-stream");

                       
TStringDynArray params = SplitString(arg, "&");
                       
String VLeft, VRight;
                       
TIdFormDataField *pf;

                        for (
i = 0; i < params.Length; i++) {
                           
SplitString(params[i], "=", VLeft, VRight);
                           
pf = par->AddFormField(VLeft, VRight);
                           
pf->Charset = SMSC_CHARSET;
                           
pf->ContentTransfer = "binary";
                        }

                       
s = idhttp->Post(url, par);

                       
delete par;
                       
par = NULL;
                    }
                else
                   
s = idhttp->Get(url + "?" + arg);
            }
            catch (...) {
               
s = "";
            }

           
cnt++;
        }
        while ((
s == "") && (cnt != 4));

        if (
s == "") {
            if (
SMSC_DEBUG)
               
_print_debug("Ошибка чтения адреса: " + url + "?" + arg);

           
s = ","; // фиктивный ответ
       
}

       
delete idhttp;
       
idhttp = NULL;

       
delim = ",";

        if (
cmd == "status") {
           
TStringDynArray par = SplitString(arg, "&");

            for (
i = 0; i < par.Length; i++) {
               
SplitString(par[i], "=", pl, pr);

                if (
pl == "id" && pr.Pos("%2C") > 1) // запятая в id - множественный запрос
                   
delim = "\n";
            }
        }

        return
SplitString(s, delim);
    }

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

   
String _urlencode(String str)
    {
        if (
SMSC_POST)
            return
str;

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

       
String EncodeStr = "";
       
UTF8String UStr;
       
int i, j;

        for (
i = 1; i <= str.Length(); i++)
            if (
CharIsInSet(str, i, UnsafeChars) || !CharIsInSet(str, i, CharRange(Char(33), Char(126)))) {
               
UStr = str[i];

                for (
j = 1; j <= UStr.Length(); j++)
                   
EncodeStr += "%" + IntToHex(Byte(UStr[j]), 2);
            }
            else
               
EncodeStr += str[i];

        return
EncodeStr;
    }

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

   
void _print_debug(String str)
    {
       
ShowMessage(str);
    }

};

// Examples:
// TStringDynArray ret;
// SMSC* sms = new SMSC;
// String balance;
//
// ret = sms->send_sms("79999999999", "Ваш пароль: 123", 1);
// ret = sms->send_sms("79999999999", "http://billing.smstraf.ru\nBILLING.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");
// ret = sms->get_status(12345, "79999999999");
// balance = sms->get_balance();
//
// delete sms;

Пример использования библиотеки: #include <smsc_api.cpp>
...
TStringDynArray ret;
SMSC* sms = new SMSC;
String balance;
...
ret = sms->send_sms("79999999999", "Ваш пароль: 123", 1);
...
ret = sms->send_sms("79999999999", "http://billing.smstraf.ru\nBILLING.SMSTRAF.RU", 0, "", 0, 0, "", "maxsms=3");
...
ret = sms->send_sms("79999999999", "0605040B8423F0DC0601AE02056A0045C60C036D79736974652E72750001036D7973697465000101", 0, "", 0, 5);
...
ret = sms->send_sms("79999999999", "", 0, "", 0, 3);
...
sms->send_sms_mail("79999999999", "Ваш пароль: 123", 0, "0101121000");
...
ret = sms->get_status(12345, "79999999999");
...
balance = sms->get_balance();
...
ret = sms->get_sms_cost("79999999999", "Вы успешно зарегистрированы!");
...
delete sms;




Переход на новую программу SMPP-сервера
27.06.2017
Сегодня на наших серверах было произведено обновление программной части SMPP-сервера, из-за чего в течение дня могли происходить кратковременные обрывы связи, вызванные несколькими перезапусками новой программы для выполнения последней стадии тестирования и настройки под большой нагрузкой. Новый сервер полностью переписан под текущие требования сервиса, максимально оптимизирован по скорости и доработан необходимым функционалом.
подробнее