Как отправить OTP-код через SMPP: DLR и повторы

Как отправить OTP-код через SMPP: DLR и повторы

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

Как выглядит отправка OTP через SMPP?

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

Шлюз возвращает приложению message_id. Это значение нужно сохранить вместе с внутренним идентификатором операции: по нему позже связывают ответ шлюза с конкретной попыткой отправки. Отдельно приходит DLR, то есть Delivery Receipt. Он показывает, доставлено сообщение, отклонено, просрочено или ещё находится в обработке.

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

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

Какие параметры SubmitSM нужны для OTP?

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

Параметр Зачем нужен Что проверить
source_addr Имя или номер отправителя Разрешён ли такой Sender ID для маршрута
destination_addr Номер получателя Формат номера и отсутствие лишних символов
short_message Текст с одноразовым кодом Кодировка и длина сообщения
data_coding Указывает кодировку текста Совпадает ли значение с фактическим текстом
registered_delivery Запрашивает отчёт о доставке Возвращает ли шлюз DLR и в каком формате
validity_period Ограничивает время жизни SMS Не остаётся ли устаревший код в очереди
service_type Передаёт назначение сообщения, если это поддерживает шлюз Соответствует ли значение договорённой схеме

Отдельно проверьте TON и NPI. Эти поля определяют тип и план нумерации адреса. Ошибка в них иногда выглядит как проблема маршрута: соединение установлено, SubmitSM принят, но сообщение не уходит дальше. Для белорусских номеров полезно заранее проверить параметры в руководстве по настройке TON/NPI в SMPP.

Текст OTP лучше сделать коротким: название сервиса, код и краткое ограничение по использованию. Не добавляйте в одно сообщение несколько действий. Например, приложение может сформировать строку вида: «Код для входа: 481927». Сам код должен быть связан с конкретной попыткой и иметь ограниченный срок действия.

Как обрабатывать ответ шлюза и DLR?

Ответ на SubmitSM подтверждает приём запроса шлюзом. Он не равен подтверждению доставки на телефон. Поэтому в базе или журнале интеграции нужны как минимум два события: результат постановки SMS в шлюз и итоговый статус из DLR.

Событие Что оно означает Действие приложения
SubmitSM accepted Шлюз принял запрос и вернул идентификатор Сохранить message_id и ждать DLR
Delivery success Шлюз получил подтверждение доставки Закрыть попытку как доставленную
Temporary failure Временная ошибка маршрута или сети Запланировать повтор по правилам
Permanent failure Шлюз отклонил сообщение окончательно Остановить повторы и показать понятную ошибку
Expired SMS не доставили до окончания срока жизни Не отправлять устаревший код без нового запроса

Формат DLR различается у шлюзов. Один провайдер передаёт отдельные поля, другой возвращает строку с кодом статуса, идентификатором и текстовым описанием. Поэтому обработчик должен сначала разобрать формат конкретного шлюза, затем привести статусы к единому внутреннему набору: delivered, temporary_failure, permanent_failure, expired и unknown.

Статус unknown нельзя автоматически считать успешным. Его лучше отправить в журнал для проверки. Если DLR пришёл с другим написанием идентификатора, система не найдёт сообщение и начнёт повторять отправку без необходимости. На тестовом стенде проверьте регистр символов, длину message_id и наличие дополнительных пробелов.

Для контроля соединения используйте Enquire Link. Этот служебный обмен помогает понять, отвечает ли SMPP-сессия, пока в очереди нет сообщений. Практическая настройка описана в материале про Enquire Link на SMPP-шлюзе.

Как настроить повторные попытки без дублирования?

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

Каждая попытка должна иметь свой внутренний идентификатор, время создания и причину повтора. При повторной отправке приложение обычно создаёт новую запись попытки, но связывает её с одной OTP-сессией. Так в журнале видно, сколько раз система обращалась к шлюзу и чем закончилась каждая попытка.

  1. Получите ответ SubmitSM и сохраните message_id.
  2. Дождитесь DLR в течение заданного приложением срока.
  3. Если статус временный, поставьте повтор в очередь с паузой.
  4. Перед повтором проверьте, не подтвердил ли шлюз доставку по первой попытке.
  5. После лимита повторов завершите OTP-сессию и предложите пользователю запросить новый код.

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

Если приложение не получило ответ на SubmitSM, ситуация неоднозначна: запрос мог не дойти до шлюза или шлюз мог принять его, но ответ потерялся. В таком случае повторная отправка создаёт риск двух одинаковых SMS. Для решения используют корреляцию запросов, журнал соединения и правила провайдера для повторной передачи. Без этих данных безопаснее завершить попытку технической ошибкой и попросить пользователя запросить новый код.

Как защитить SMPP-соединение и проверить интеграцию?

Учётные данные SMPP не стоит хранить в исходном коде. Их выносят в настройки окружения или защищённое хранилище конфигурации. Доступ к шлюзу ограничивают адресами сервера приложения, а журнал не должен содержать полный OTP-код.

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

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

Какие ошибки чаще всего ломают OTP?

  • Приложение считает ответ SubmitSM подтверждением доставки и не ждёт DLR.
  • Обработчик не умеет сопоставлять DLR с message_id.
  • Повтор запускается после любого сбоя, включая окончательный отказ.
  • Для текста на кириллице выбрана неподходящая кодировка.
  • Срок жизни SMS больше срока действия OTP, поэтому старый код приходит поздно.
  • При переподключении система создаёт несколько SMPP-сессий и дублирует отправку.

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