Интеграция с сервисом (API)

API позволяет рассылать сообщения через ваши проекты и сервисы по протоколам HTTP/HTTPS, SMTP и SMPP. Готовые библиотеки на разных языках программирования подключаются к вашему проекту и помогают отправлять сообщения из любого места с помощью одной команды. Для упрощенной авторизации вместо пары логин и пароль можно использовать специальный API-ключ.


HTTP/HTTPS SMTP SMPP SOAP OMS SMS-команды Библиотеки и примеры кода

Для Microsoft Visual C++

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

Исходный код библиотеки:
// M.SMSC.RU API для Microsoft Visual C++ (m.smsc.ru) версия 1.3 (03.07.2019)

#define _AFXDLL

#include <afxinet.h>
#include <vector>
#include <Shlwapi.h>
#include <Strsafe.h>

using namespace std;

// Константы с параметрами отправки
const CString SMSC_LOGIN = "";                // логин клиента
const CString SMSC_PASSWORD = "";            // пароль клиента. Если передан пустой логин, то SMSC_PASSWORD используется, как API ключ, вместо логина и пароля
const bool SMSC_HTTPS = false;                // использовать протокол HTTPS
const bool SMSC_POST = false;                // использовать метод POST
const CString SMSC_CHARSET =
                           
#if defined _UNICODE || defined UNICODE
                               
"utf-8";
                           
#else
                               
"windows-1251";
                           
#endif            // кодировка сообщения (utf-8 или koi8-r), по умолчанию используется windows-1251
const bool SMSC_DEBUG = false;                // флаг отладки

class SMSC {
public:
   
// Общедоступные методы класса SMSС
    //
    // Метод отправки SMS
    //
    // обязательные параметры:
    //
    // phones - список телефонов через запятую или точку с запятой
    // message - отправляемое сообщение
    //
    // необязательные параметры:
    //
    // 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")
    //
    // возвращает массив (<id>, <количество sms>, <стоимость>, <баланс>) в случае успешной отправки
    // либо (<id>, -<код ошибки>) в случае ошибки

   
vector<CString> send_sms(CString phones, CString message, int translit = 0, CString time = "", int id = 0, int format = 0, CString sender = "", CString query = "")
    {
       
CString tt, ir;
       
CString 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"};
       
ir.Format((CString)"%i", id);
       
tt.Format((CString)"%i", translit);

       
vector<CString> m = _smsc_send_cmd("send", "cost=3&phones=" + (CString)_urlencode(phones) +
           
"&mes=" + (CString)_urlencode(message) + "&id=" + ir + "&translit=" + tt + (format > 0 ? "&" + formats[format - 1] : "") +
            (
sender != "" ? "&sender=" + (CString)_urlencode(sender) : "") + (time != "" ? "&time=" + (CString)_urlencode(time) : "") +
            (
query != "" ? "&" + query : ""));

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

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

        return
m;
    };

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

   
vector<CString> get_sms_cost(CString phones, CString message, int translit = 0, int format = 0, CString sender = "", CString query = "")
    {
       
CString tt;

       
CString 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"};
       
tt.Format((CString)"%i", translit);

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

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

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

        return
m;
    };

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

   
vector<CString> get_status(int id, CString phone, int all = 0)
    {
       
CString ans, ir, tr;
       
int i;

       
ir.Format((CString)"%i", id);
       
tr.Format((CString)"%i", all);

       
vector<CString> m = _smsc_send_cmd("status", "phone=" + (CString)_urlencode(phone) + "&id=" + ir + (all > 0 ? "&all=" + tr : ""));

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

       
if (SMSC_DEBUG)
            if ((
m[1] != "") && (m[1] >= "0"))
            {
               
time_t tm = _ttoi(m[1]);

               
struct tm ltm;
               
TCHAR st[100] = {0};

               
localtime_s(&ltm, &tm);
               
_stprintf_s(st, 100, (CString)"%2d.%2d.%d %2d:%2d:%2d", ltm.tm_mday, (ltm.tm_mon) + 1, (ltm.tm_year) + 1900, ltm.tm_hour, ltm.tm_min, ltm.tm_sec);

               
_print_debug( "Статус SMS = " + m[0] + ", время изменения статуса - " + st);
            }
            else
               
_print_debug("Ошибка №" + m[1].Mid(1, 1));

        if (
all == 1 && m.size() > 9 && (m.size() < 14 || m[14] != "HLR"))
        {
           
ans = m[0];

            for (
i = 1; i < (int)m.size(); i++)
               
ans += "," + m[i];

           
m.clear();
           
int cp = 0;

            for (
i = 0; i < 8; i++)
               
m.push_back(ans.Tokenize((CString)",", cp));
           
m.push_back(ans.Mid(cp));
        }

        return
m;
    };

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

   
CString get_balance(void)
    {
       
vector<CString> m = _smsc_send_cmd("balance", ""); // (balance) или (0, -error)

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

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

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

   
vector<CString> _smsc_send_cmd(CString cmd, CString arg)
    {
       
vector<CString> m;
       
int cnt = 0;
       
CString url, _url;

       
arg = (SMSC_LOGIN != "" ? "login=" + (CString)_urlencode(SMSC_LOGIN) + "&psw=" : "apikey=") + (CString)_urlencode(SMSC_PASSWORD) + "&fmt=1&charset=" + SMSC_CHARSET + "&" + arg;
       
url = _url = (SMSC_HTTPS ? "https" : "http") + (CString)"://m.smsc.ru/sys/" + cmd + ".php";

       
CString sr, ot, res, strcnt;   
       
INTERNET_PORT pt;
       
DWORD st;
       
char sz[1024] = {0};

       
CInternetSession ses((CString)"Visual C++", PRE_CONFIG_INTERNET_ACCESS);
       
CHttpConnection *ds;

       
AfxParseURL(url + '?' + arg, st, sr, ot, pt);

       
ds = ses.GetHttpConnection(sr, NULL, pt);

        do
        {
            if (
cnt++) {
               
strcnt.Format((CString)"%i", cnt);
               
url = _url;
               
url.Replace((CString)"m.smsc.ru/", (CString)"www" + strcnt + ".m.smsc.ru/");

               
AfxParseURL(url + '?' + arg, st, sr, ot, pt);
               
ds = ses.GetHttpConnection(sr, NULL, pt);
            }

           
CHttpFile *pc;

            try {
                if (
SMSC_POST || arg.GetLength() > 2000)
                {
                   
pc = ds->OpenRequest(0, "/sys/" + cmd + ".php", NULL, 1, NULL, NULL, SMSC_HTTPS ? INTERNET_FLAG_SECURE : INTERNET_FLAG_EXISTING_CONNECT);
                   
pc->SendRequest((CString)"Content-Type: application/x-www-form-urlencoded", (LPVOID)(LPCSTR)(CStringA)arg, arg.GetLength());
                }
                else
                {
                   
pc = ds->OpenRequest(1, ot, NULL, 1, NULL, NULL, SMSC_HTTPS ? INTERNET_FLAG_SECURE : INTERNET_FLAG_EXISTING_CONNECT);
                   
pc->SendRequest();
                }

               
pc->Read(sz, 1024);
            }
            catch (
CInternetException* e) {
            }

           
res = sz;

           
pc->Close();
        }
        while ((
res == "") && (cnt < 5));

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

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

       
ds->Close();
       
ses.Close();

        return
_explode(res);
    };

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

   
CStringA _urlencode(CString s_in)
    {
       
#if defined _UNICODE || defined UNICODE
           
const WCHAR *pt_utf16 = s_in;
            const
size_t cch_utf16m = INT_MAX - 1;
           
size_t cch_utf16;
       
            ::
StringCchLengthW(pt_utf16, cch_utf16m, &cch_utf16);

            ++
cch_utf16;

           
int cb_utf8 = ::WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, pt_utf16, static_cast<int>(cch_utf16), NULL, 0, NULL, NULL);

           
CStringA s_utf8;
           
CHAR *pt_utf8 = s_utf8.GetBuffer(cb_utf8);

            ::
WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, pt_utf16, static_cast<int>(cch_utf16), pt_utf8, cb_utf8, NULL, NULL);

           
s_utf8.ReleaseBuffer();

            return
_encode(s_utf8);
       
#else
           
return _encode(s_in);
       
#endif
   
};

   
CStringA _encode(CStringA s_in)
    {
       
CStringA s_out;

        for (
int i = 0; i < s_in.GetLength(); i++)
        {
           
CHAR ch = s_in[i];

            if ((
ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'))
               
s_out.AppendChar(ch);
            else
            {
               
BYTE ccv = static_cast<BYTE>(ch);

               
CHAR eb[4];
               
sprintf_s(eb, sizeof(eb), "%%%02X", ccv);

               
s_out.Append(eb);
            }
        }

        return
s_out;
    };

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

   
void _print_debug(CString str)
    {
       
MessageBox(NULL, str, NULL, MB_OK);
    };

   
// разделение строки, возвращаемой сервером, на массив строк

   
vector<CString> _explode(CString str)
    {
       
int cp = 0;
       
vector<CString> m;

        do
        {
           
m.push_back(str.Tokenize((CString)",", cp));
        }
        while (
m.back() != "");

       
m.pop_back();

        return
m;
    };
};

// Examples:
// SMSC *sms = new SMSC();
// СString balance;
// vector<CString> ret;
//
// 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->get_sms_cost("79999999999", "Вы успешно зарегистрированы!");
// ret = sms->get_status(12345, "79999999999");
// balance = sms->get_balance();
//
// delete sms;

Пример использования библиотеки:
#include "smsc_api_vc.cpp"
...
SMSC *sms = new SMSC();
СString balance;
vector<CString> ret;
...
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->get_sms_cost("79999999999", "Вы успешно зарегистрированы!");
...
ret = sms->get_status(12345, "79999999999");
...
balance = sms->get_balance();
...
delete sms;