В процессе интеграции решений на платформе 1С с внешними СМС-провайдерами разработчики часто сталкиваются с ситуацией, когда отправленный HTTP-запрос возвращает стандартный успешный код состояния 200 OK, однако сами сообщения до получателей не доходят. В этой статье мы подробно разберем, как правильно реализовать отправку СМС через шлюз сервиса ИнфоСМС (api.infosmska.ru), научимся детально анализировать ответы сервера для локализации ошибок и рассмотрим расширенные возможности API, которые помогут сделать рассылку безопасной и экономичной.
Рассмотрим типичную ситуацию. Разработчик пишет код для отправки GET-запроса к API сервиса рассылки:
НомерТелефонаОтправка = "7" + СокрЛП(Объект.НомерТелефона);
ТекстСообщения = "test";
СтрокаЗапроса = "interfaces/SendMessages.ashx?login="+ЛогинНаСервис+"&pwd="+ПарольНаСервис+"&phones="+НомерТелефонаОтправка+"&message="+ТекстСообщения+"&sender=sms";
HTTPСоединение = Новый HTTPСоединение("api.infosmska.ru", 80);
ЗапросApi = Новый HTTPЗапрос(СтрокаЗапроса);
ОтветApi = HTTPСоединение.Получить(ЗапросApi);
При выполнении этого кода свойство КодСостояния возвращаемого объекта HTTPОтвет равно 200. Согласно спецификации протокола HTTP, это означает лишь то, что веб-сервер успешно принял ваш запрос и вернул ответ. Однако это абсолютно не означает, что СМС-шлюз успешно обработал параметры внутри этого запроса и поставил сообщение в очередь на отправку. Сам шлюз может вернуть текстовое описание ошибки (например, неверный баланс, неверный логин или заблокированное имя отправителя) непосредственно внутри тела ответа, сохранив при этом стандартный HTTP-статус 200.
Для того чтобы понять реальный результат выполнения операции, нам необходимо проанализировать не только заголовки и код состояния, но и само тело ответа, которое присылает сервер.
Для детальной диагностики воспользуемся возможностями объекта HTTPОтвет. Платформа 1С предоставляет несколько методов для работы с содержимым ответа. Самым удобным и простым в данном случае является метод ПолучитьТелоКакСтроку(). Он позволяет прочитать текстовый ответ сервера напрямую в переменную без необходимости сохранения во временные файлы.
Модернизируем наш код, добавив вывод содержимого ответа в окно сообщений или в лог:
HTTPСоединение = Новый HTTPСоединение("api.infosmska.ru", 80);
ЗапросApi = Новый HTTPЗапрос(СтрокаЗапроса);
ОтветApi = HTTPСоединение.Получить(ЗапросApi);
Если ОтветApi.КодСостояния = 200 Тогда
ТекстОтвета = ОтветApi.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
Сообщить("Ответ сервера: " + ТекстОтвета);
Иначе
Сообщить("Ошибка соединения! Код состояния HTTP: " + ОтветApi.КодСостояния);
КонецЕсли;
После запуска обновленного кода мы увидим реальную причину проблемы, которую вернул шлюз в теле ответа. В нашем случае это будет строка:
Error: Имя отправителя 'sms' недоступно
Проанализируем причину возникновения этой ошибки. По умолчанию СМС-сервис ИнфоСМС требует точного соблюдения регистра символов при указании системного имени отправителя. Значение sms (в нижнем регистре) воспринимается системой как попытка использовать незарегистрированное имя, что приводит к ошибке.
Для исправления этой проблемы достаточно заменить значение параметра sender в строке запроса на SMS (в верхнем регистре):
&sender=SMS
Обратите внимание, что системная подпись SMS доступна всем зарегистрированным пользователям по умолчанию. Если вы планируете отправлять сообщения от лица своего бренда (например, MyShop), такое имя отправителя необходимо предварительно зарегистрировать и пройти модерацию в личном кабинете сервиса ИнфоСМС. До завершения модерации использование брендового имени также будет приводить к аналогичной ошибке.
Для построения надежного и безопасного механизма СМС-рассылок из 1С крайне рекомендуется учитывать ряд важных технических особенностей шлюза ИнфоСМС, которые не всегда лежат на поверхности.
1. Безопасность учетных данных (MD5-хеширование)
Передача пароля в открытом виде в параметре запроса pwd небезопасна, особенно если вы используете стандартное HTTP-соединение без шифрования (порт 80). Шлюз позволяет повысить безопасность, принимая вместо открытого пароля его MD5-хеш. Перед формированием строки запроса рекомендуется вычислить MD5-хеш вашего пароля и передавать его в параметре pwd в нижнем регистре.
2. Форматирование номеров телефонов
Номера телефонов в параметре phones должны передаваться строго в международном формате и обязательно без знака плюс (+) на стыке. Например: 79001234567. При необходимости отправить сообщение нескольким получателям вы можете передать список номеров через запятую (в рамках одного запроса поддерживается отправка до 1000 номеров одновременно).
3. Кодирование текста сообщения (URL Encode)
Передача кириллического текста в GET-запросе без предварительного кодирования — частая причина появления "кракозябр" или знаков вопроса у получателя. Текст сообщения обязательно должен быть закодирован в формат URL-encoded (UTF-8). В платформе 1С для этого используется встроенная функция КодироватьСтроку().
Пример подготовки текста сообщения в 1С:
ТекстЗапросаКодированный = КодироватьСтроку(ТекстСообщения, СпособКодированияСтроки.КодироватьИменаПровайдеров);
4. Использование полезных параметров API
Для расширения бизнес-логики вашей конфигурации 1С вы можете задействовать дополнительные параметры в GET-запросе:
translit — если передать значение 1, сервис автоматически переведет кириллический текст сообщения в транслит. Это позволяет значительно снизить стоимость рассылки, так как лимит символов для одного СМС-сегмента увеличивается с 70 (для кириллицы) до 160 (для латиницы).getcost — при указании этого параметра реальная отправка СМС не производится, но сервер возвращает точную стоимость планируемой рассылки. Это очень полезно для реализации функции предварительного расчета стоимости прямо в интерфейсе 1С перед отправкой крупной партии сообщений.msglife — позволяет ограничить время жизни СМС (в минутах). Если получатель находится вне зоны действия сети дольше указанного времени, сообщение будет отменено шлюзом, что убережет клиента от получения неактуальной информации (например, кодов авторизации) спустя сутки.Объединим все вышеперечисленные правила в готовый программный модуль, который можно использовать в ваших обработках или общих модулях:
Функция ОтправитьСМС_ИнфоСМС(Логин, Пароль, НомерТелефона, ТекстСообщения, ИмяОтправителя = "SMS") Экспорт
// 1. Очищаем номер телефона от лишних символов (оставляем только цифры)
ЧистыйНомер = "";
Для Индекс = 1 По СтрДлина(НомерТелефона) Цикл
Символ = Сред(НомерТелефона, Индекс, 1);
Если Найти("0123456789", Символ) > 0 Тогда
ЧистыйНомер = ЧистыйНомер + Символ;
КонецЕсли;
КонецЦикла;
// Если номер начинается с +, убираем его. Если с 8, заменяем на 7 для международного формата
Если Лев(ЧистыйНомер, 1) = "8" Тогда
ЧистыйНомер = "7" + Сред(ЧистыйНомер, 2);
КонецЕсли;
// 2. Кодируем текст сообщения в формат UTF-8 URL
КодированныйТекст = КодироватьСтроку(ТекстСообщения, СпособКодированияСтроки.КодироватьИменаПровайдеров);
// 3. Формируем строку запроса с параметрами
// Вместо открытого пароля рекомендуется передавать MD5-хеш (если реализовано в вашей конфигурации)
ПараметрыЗапроса = "interfaces/SendMessages.ashx"
+ "?login=" + Логин
+ "&pwd=" + Пароль
+ "&phones=" + ЧистыйНомер
+ "&message=" + КодированныйТекст
+ "&sender=" + ИмяОтправителя;
// 4. Отправляем запрос на сервер
HTTPСоединение = Новый HTTPСоединение("api.infosmska.ru", 80);
HTTPЗапрос = Новый HTTPЗапрос(ПараметрыЗапроса);
Попытка
HTTPОтвет = HTTPСоединение.Получить(HTTPЗапрос);
Если HTTPОтвет.КодСостояния = 200 Тогда
ТекстОтвета = HTTPОтвет.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
// Успешный ответ сервера начинается с префикса "Ok:"
Если Лев(ТекстОтвета, 3) = "Ok:" Тогда
Возврат Новый Структура("Успех, Описание", Истина, "Сообщение успешно отправлено. ID: " + Сред(ТекстОтвета, 4));
Иначе
Возврат Новый Структура("Успех, Описание", Ложь, "Ошибка сервиса: " + ТекстОтвета);
КонецЕсли;
Иначе
Возврат Новый Структура("Успех, Описание", Ложь, "Ошибка сети HTTP. Код состояния: " + HTTPОтвет.КодСостояния);
КонецЕсли;
Исключение
Возврат Новый Структура("Успех, Описание", Ложь, "Критическая ошибка отправки: " + ОписаниеОшибки());
КонецПопытки;
КонецФункции
Если вам сложно работать с ручным кодированием параметров GET-запросов и вы хотите иметь строго типизированный интерфейс интеграции, у сервиса ИнфоСМС есть веб-сервис, работающий по протоколу SOAP. Вы можете подключить его в вашей конфигурации через объект WS-ссылки.
Адрес WSDL-описания веб-сервиса:
http://api.infosmska.ru/Interfaces/SmsServiceV2.asmx?WSDL
Преимуществом работы через WS-ссылки является автоматическое преобразование типов 1С в XML-пакеты. Метод веб-сервиса SendMessage самостоятельно закодирует текст и передаст его на шлюз. Кроме того, этот интерфейс предоставляет удобные методы для запроса текущего баланса (GetBalance) и проверки актуального статуса доставки отправленного сообщения (GetMessageState).
Таким образом, мы детально разобрали особенности работы со шлюзом ИнфоСМС, выявили важность разбора тела HTTP-ответа и научились обходить типовые ошибки интеграции в 1С.