Как исключить повторные SMS при сбоях связи со шлюзом

Как исключить повторные SMS при сбоях связи со шлюзом

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

Почему клиент получает одинаковые SMS?

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

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

Сначала найдите точку, где система принимает решение отправить SMS. Для уведомления «заказ готов» это должен быть переход заказа в нужный статус. Обычное сохранение карточки заказа не должно заново запускать тот же сценарий. Отдельно проверьте ручную кнопку отправки: она тоже должна учитывать уже созданное уведомление.

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

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

Событие лучше привязывать к конкретному изменению. Например, запись на услугу перенесли, и клиенту нужно сообщить новое время. Если запись позже перенесут снова, появится другое событие и новое уведомление. Проверка только по номеру заказа или записи заблокирует полезные сообщения вместе с дублями.

  1. Определите событие для отправки: например, переход заказа в статус «готов к выдаче».
  2. Создайте для него запись уведомления с постоянным идентификатором.
  3. Запретите системе создавать ещё одну запись с тем же идентификатором события и типом уведомления.
  4. Перед повторной попыткой проверьте состояние существующей записи.

Запрет дублей должен работать на уровне базы данных. Простая проверка «есть ли такая запись» оставляет промежуток: параллельные процессы могут одновременно получить ответ «нет» и оба начать отправку. Разработчику нужно предусмотреть ограничение уникальности и механизм, который позволяет только одному процессу забрать уведомление в работу.

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

Что делать, если шлюз не ответил на запрос?

Введите состояние «результат неизвестен». Оно нужно для ситуации, когда сайт отправил запрос, но не получил однозначного ответа. Немедленно возвращать такое уведомление в общую очередь рискованно: шлюз уже мог принять его в обработку.

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

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

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

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

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

Как проверить защиту от дублей до запуска?

Тестируйте всю цепочку: событие на сайте, запись уведомления, обращение к шлюзу и отчёт о результате. Успешный ответ API проверяет только часть сценария. Основной тест — шлюз принимает запрос, но сайт не получает ответ и пытается продолжить работу.

  • Повторите одно событие. В системе должна остаться одна запись уведомления для этого события.
  • Запустите обработку одной записи параллельно. Только один процесс должен получить право на отправку.
  • Воспроизведите потерю ответа после приёма запроса шлюзом. Проверьте поиск результата или повтор с тем же ключом идемпотентности.
  • Передайте одинаковый отчёт о доставке повторно. Он должен обновить состояние, не создавая новую SMS.
  • Создайте новое событие для того же заказа. Убедитесь, что защита от дублей пропускает новое уведомление.

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

Уведомление о доставке тоже может прийти повторно. Его обработчик должен менять состояние существующей отправки, без повторного запуска исходного события. Иначе подтверждение доставки само станет причиной новой SMS.

Для статусов заказа полезно отделить SMS от актуальных сведений на сайте. В сообщении можно дать переход к странице, где клиент увидит текущее состояние заявки. Принцип разобран в статье о том, как дать клиенту проверить статус заявки по ссылке из SMS. Такая страница не заменяет защиту от дублей, зато позволяет проверить статус без запроса нового сообщения.

Типичные ошибки при защите сервисных SMS от повторов

  • Считать тайм-аут подтверждением отказа. Исправление: сохранять неопределённый результат и проверять, принял ли шлюз запрос.
  • Выдавать новый идентификатор при каждой попытке. Исправление: сохранять идентификатор отправки до первого обращения к API и использовать его повторно.
  • Искать дубли только по тексту и номеру телефона. Исправление: учитывать конкретное бизнес-событие, иначе одинаковые по тексту законные уведомления будут блокироваться.
  • Снимать защиту после перезапуска сайта. Исправление: сохранять состояние отправки в базе, чтобы оно переживало остановку приложения.
  • Разрешать ручную отправку в обход общей проверки. Исправление: направлять действия сотрудника через тот же механизм уведомлений.

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

Сейчас за минуту отправьте разработчику один вопрос: «Что делает наша система, если SMS-шлюз принял сообщение, но ответ на запрос потерялся?»