Как принимать ответы на SMS через SMPP: MO-сообщения

Как принимать ответы на SMS через SMPP: MO-сообщения

Принимать ответы на SMS через SMPP можно в режиме receiver или через двунаправленный bind_transceiver. Вы отправляете вопрос как обычное SMS, а ответ абонента приходит от SMS-центра в виде MO-сообщения, обычно внутри команды deliver_sm. В статье разберём схему подключения, параметры receiver-режима, разбор текста и защиту от повторной обработки. В результате разработчик сможет связать входящий ответ с клиентом, заказом или конкретным вопросом без HTTP API.

Как работает двусторонняя SMS-связь через SMPP?

В двусторонней схеме участвуют три элемента: ваше приложение, SMPP-шлюз и сеть мобильного оператора. Приложение отправляет исходящее сообщение командой submit_sm. Когда абонент отвечает, шлюз передаёт входящий текст приложению командой deliver_sm. Такой входящий пакет называют MO, то есть Mobile Originated.

Для простого опроса можно отправить сообщение «Оцените обслуживание от 1 до 5. Ответьте одной цифрой». Абонент пишет SMS в ответ, шлюз передаёт номер отправителя и текст, а программа сохраняет результат. Если бизнесу нужно принять свободный комментарий, приложение может записать весь текст без классификации и передать его сотруднику на дальнейший разбор.

Отдельно нужно учитывать DLR-сообщения. Они подтверждают состояние исходящей SMS и тоже приходят через deliver_sm, поэтому обработчик обязан отличать отчёт о доставке от ответа абонента. Иначе система может ошибочно записать технический статус как ответ на опрос.

Тип сообщенияКоманда SMPPЧто делает приложение
Исходящее SMSsubmit_smПередаёт вопрос, уведомление или код
Ответ абонентаdeliver_smСохраняет текст MO и связывает его с диалогом
Отчёт о доставкеdeliver_smОбновляет статус исходящего сообщения
Проверка соединенияenquire_linkПоддерживает SMPP-сессию и контролирует доступность

Как выбрать receiver или transceiver?

Режим receiver подходит, когда приложение только принимает входящие SMS. Для полноценного диалога чаще используют bind_transceiver: одна SMPP-сессия позволяет отправлять вопросы через submit_sm и принимать ответы через deliver_sm. Выбор зависит от условий шлюза и того, как разделены исходящий и входящий трафик.

При настройке receiver приложение открывает TCP-соединение с SMPP-шлюзом и передаёт параметры учётной записи. После успешной авторизации шлюз начинает направлять входящие PDU. Программа должна регулярно отправлять enquire_link и отвечать на служебные запросы шлюза, иначе соединение прервётся даже при отсутствии сообщений.

Для малого бизнеса практичная схема выглядит так: отдельный процесс держит SMPP-сессию, отдельный обработчик разбирает входящие пакеты, а очередь сообщений временно хранит события до записи в рабочую систему. Если обработка текста занимает время, не стоит задерживать SMPP-ответ. Сначала подтвердите получение PDU, затем передайте содержимое в очередь.

При нестабильном интернете в офисе пригодятся повторное подключение, задержка между попытками и контроль состояния bind. Особенности восстановления SMPP-сессии разобраны в материале как настроить SMPP-bind при нестабильном интернете.

Какие поля нужно обработать в MO-сообщении?

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

  • source_addr помогает определить абонента, который отправил ответ;
  • destination_addr показывает номер или короткий номер, на который пришло SMS;
  • short_message содержит текст, если сообщение передано в основном поле;
  • message_payload может содержать текст длинного сообщения в дополнительном параметре;
  • esm_class помогает определить тип сообщения и наличие признаков отчёта о доставке;
  • data_coding подсказывает, как декодировать текст.

Не ограничивайтесь чтением только short_message. Длинное SMS может прийти несколькими частями, а содержимое иногда передаётся через TLV или message_payload. Приложение собирает сегменты по идентификатору и порядковому номеру, после чего передаёт готовую строку в бизнес-обработчик.

Кодировка требует отдельной проверки. Латинский текст часто передают в GSM 7-bit, а кириллица требует другой схемы кодирования и уменьшает доступную длину одного сегмента. Если приложение сохраняет «кракозябры», сначала проверьте data_coding, затем настройку декодера в SMPP-библиотеке.

Как связать ответ с конкретным вопросом?

Самый понятный способ для короткого опроса — использовать отдельный номер или короткий код в тексте исходящего SMS. Например, система отправляет вопрос с инструкцией «Ответьте 1, 2 или 3», а при отправке сохраняет запись с идентификатором кампании и номером получателя. Когда приходит MO, обработчик ищет активный диалог по отправителю и последнему ожидающему вопросу.

Если один абонент может участвовать сразу в нескольких опросах, одного номера недостаточно. Добавьте в сообщение короткий маркер: «Ответьте 1, если готовы получить заказ. Код заказа A17». Входящий обработчик отделяет код от ответа, проверяет допустимое значение и передаёт результат в нужный сценарий. Маркер лучше делать коротким, чтобы не увеличивать число SMS-сегментов.

Формат ответаПравило обработкиРезультат
Одна цифраПринять только значения из заданного спискаАвтоматическая оценка или выбор варианта
СловоПривести текст к единому регистру и сравнить с командамиЗапись действия клиента
Код и ответРазделить строку по пробелу или другому маркеруСвязь ответа с заказом или опросом
Свободный текстСохранить исходное сообщение без потери символовКомментарий для ручной обработки

Для каждого исходящего вопроса сохраните внутренний идентификатор, время отправки и ожидаемый формат ответа. В базе данных полезно иметь поля «получено», «обработано» и «ошибка разбора». Такая структура позволяет повторно запустить обработку после сбоя, не отправляя человеку новый вопрос.

Как защитить обработчик от повторов и ошибок?

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

  • Разделяйте MO-сообщения и DLR по признакам SMPP и содержимому.
  • Проверяйте обязательные поля до записи в рабочую базу.
  • Сохраняйте исходный текст вместе с нормализованным значением ответа.
  • Ограничивайте длину и набор допустимых команд для автоматических сценариев.
  • Пишите в журнал bind, отключение, повторное подключение и ошибки декодирования.

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

Как запустить SMS-опрос без HTTP API?

HTTP API не требуется, если приложение умеет работать с SMPP-библиотекой и поддерживает постоянную сессию. Разработчик настраивает bind, создаёт отправку через submit_sm, принимает deliver_sm в receiver или transceiver-режиме и передаёт данные во внутреннюю очередь. Такой подход подходит для напоминаний, подтверждения заказа, оценки обслуживания и коротких команд.

Перед запуском проверьте тестовый сценарий от начала до конца: отправка вопроса, ответ с телефона, приём MO, декодирование кириллицы, запись результата и повторная доставка того же сообщения. Для проекта с большим объёмом отдельно согласуйте пропускную способность, DLR, формат имени отправителя и правила маршрутизации с SMPP-шлюзом. Техническое подключение напрямую к SMS-шлюзу описывается как вариант для высокообъёмного трафика и управления доставкой на уровне инфраструктуры.

3 шага, которые можно сделать на этой неделе:

  1. Определить формат ответа и таблицу состояний диалога: вопрос отправлен, ответ получен, ответ обработан.
  2. Поднять тестовый bind_transceiver или receiver, вывести в журнал поля входящего deliver_sm и проверить кодировку.
  3. Добавить идемпотентность, обработку длинных SMS и отдельное распознавание DLR до подключения рабочего сценария.