| Для C++ Builder
Скачать файл библиотеки:
smsc_api.cpp
Исходный код библиотеки:
// M.SMSC.RU API для C++ Builder (m.smsc.ru) версия 2.1 (03.07.2019)
#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 = ""; // логин клиента
const char* SMSC_PASSWORD = ""; // пароль клиента. Если передан пустой логин, то SMSC_PASSWORD используется, как API ключ, вместо логина и пароля
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@m.smsc.ru"; // e-mail адрес отправителя
const char* SMTP_SERVER = "send.m.smsc.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, 10 - viber, 11 - soc, 13 - telegram)
// sender - имя отправителя (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[13] = {"flash=1", "push=1", "hlr=1", "bin=1", "bin=2", "ping=1", "mms=1", "mail=1", "call=1", "viber=1", "soc=1", "", "tg=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.m.smsc.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, 10 - viber, 11 - soc, 13 - telegram)
// 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[13] = {"flash=1", "push=1", "hlr=1", "bin=1", "bin=2", "ping=1", "mms=1", "mail=1", "call=1", "viber=1", "soc=1", "", "tg=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, url, _url;
int i, cnt = 0;
arg = (String(SMSC_LOGIN) != "" ? "login=" + _urlencode(SMSC_LOGIN) + "&psw=" : "apikey=") + _urlencode(SMSC_PASSWORD) + "&fmt=1&charset=" + String(SMSC_CHARSET) + "&" + arg;
url = _url = "http://m.smsc.ru/sys/" + cmd + ".php";
do
{
if (cnt++)
url = StringReplace(_url, "m.smsc.ru", "www" + IntToStr(cnt) + ".m.smsc.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 = "";
}
}
while ((s == "") && (cnt < 5));
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://m.smsc.ru\nM.SMSC.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://m.smsc.ru\nM.SMSC.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;
|