Дублирование SMS-уведомлений возникает при сбоях сети, таймаутах вебхуков или повторных кликах покупателя на кнопку оплаты. Чтобы клиент не получал два одинаковых сообщения об одном заказе, разработчики настраивают идемпотентность запросов, блокировку повторных триггеров на стороне CRM и ведут локальный журнал отправленных сообщений с уникальными ключами транзакций. Ниже разберем технические причины задвоения SMS, логику работы ключей идемпотентности и пошаговый алгоритм защиты интернет-магазина от лишних списаний за дублирующие сообщения.
Почему интернет-магазин отправляет клиенту две одинаковые SMS?
В типовой схеме онлайн-торговли уведомления запускаются автоматически. Когда покупатель оформляет заказ на сайте, CMS передает событие в CRM, а та отправляет команду в шлюз рассылок. Если на любом этапе цепочки происходит сетевая задержка, система считает отправку неуспешной и запускает повторную попытку.
Чаще всего дубли возникают из-за вебхуков платежных систем. Банк или платежный сервис отправляет вебхук об успешной оплате, но сервер интернет-магазина отвечает с задержкой более 5 секунд. Платежный шлюз расценивает это как сбой и присылает тот же вебхук снова. Если на бэкенде нет проверки уникальности события, скрипт дважды ставит задачу на отправку сервисного SMS.
Вторая причина связана с таймаутами HTTP-запросов между вашей CRM и API сервиса рассылок. CRM отправляет запрос, SMS-шлюз принимает его и передает оператору связи, но ответ со статусом «Принято» теряется из-за кратковременного разрыва соединения. CRM фиксирует ошибку таймаута и автоматически делает повторный вызов API. В итоге оператор отправляет покупателю два одинаковых текста с разницей в несколько секунд.
Третья причина — параллельная работа триггеров. Когда статус заказа меняется одновременно из двух мест (например, администратор вручную нажал кнопку в панели управления, а через секунду пришел статус от курьерской службы), срабатывают две независимые цепочки. Грамотно выстроенная SMS-цепочка статуса заказа в интернет-магазине должна учитывать подобные наложения и блокировать дубликаты на уровне очереди сообщений.
Что такое ключ идемпотентности и как он работает в SMS API?
Идемпотентность — это свойство API, при котором повторный вызов с одинаковыми параметрами дает точно такой же результат, как и первый, не создавая повторных действий. В контексте SMS-рассылок это означает: сколько бы раз CRM ни отправляла один и тот же запрос, шлюз отправит клиенту только одно сообщение, а за последующие запросы просто вернет сохраненный результат.
Для реализации этой схемы используется специальный параметр — ключ идемпотентности (idempotency key). В качестве ключа обычно выступает составной идентификатор: номер заказа вместе с типом события (например, order_58421_paid) или сгенерированный UUID транзакции.
Когда SMS-шлюз получает запрос, он проверяет наличие ключа в своей базе активных транзакций за последние 24 часа. Если ключ новый, сервис регистрирует его, отправляет сообщение и сохраняет ответ. Если ключ уже существует, шлюз мгновенно отдает предыдущий ответ без реальной отправки в сотовую сеть и без списания средств с баланса интернет-магазина.
Сравнение методов защиты от повторных SMS
Выбор способа защиты зависит от используемого стека и архитектуры интернет-магазина. В таблице приведены основные подходы, их сложность и надежность.
| Метод защиты | Где настраивается | Сложность внедрения | Надежность |
|---|---|---|---|
| Ключи идемпотентности в API | На стороне SMS-шлюза | Низкая | Высокая |
| Блокировка по статусу заказа в базе | В CMS интернет-магазина | Средняя | Высокая |
| Очередь сообщений с дедупликацией | На бэкенд-сервере / в CRM | Высокая | Максимальная |
| Ограничение интервала повтора (Throttle) | В скрипте отправки | Низкая | Средняя |
Для небольших интернет-магазинов оптимальна комбинация двух методов: проверка флага отправки в базе данных сайта и передача уникального внешнего ID заказа в шлюз рассылок. Для мониторинга доставки полезно изучить, как настроить интеграцию API для статуса доставки SMS в CRM, чтобы отслеживать реальный путь каждого уведомления.
Как настроить защиту на уровне CRM и CMS: практическая схема
Чтобы исключить дублирование сообщений до момента обращения к внешним сервисам, настройте обработку событий внутри магазина по следующему алгоритму:
- Атомарные транзакции при смене статуса. Записывайте флаг отправки уведомления в той же транзакции базы данных, которая обновляет статус заказа. Если флаг
sms_sentуже равенtrue, скрипт пропускает шаг отправки. - Асинхронная очередь с уникальным идентификатором задачи. Передавайте задачи на отправку в очередь (например, RabbitMQ или Redis) с уникальным task ID. Если задача с таким ID уже стоит в очереди или выполнена, повторное добавление игнорируется.
- Проверка тайм-аута между однотипными событиями. Установите жесткий лимит: на один номер телефона нельзя отправлять сервисные SMS чаще одного раза в 60 секунд по одному и тому же заказу, если это не код подтверждения.
- Логирование внешних вебхуков. При получении уведомления от банка сохраняйте ID банковской транзакции в отдельную таблицу с уникальным индексом. Повторный вебхук с тем же ID вызовет ошибку уникальности ключа и сразу завершит работу скрипта с кодом 200 OK без повторной отправки SMS.
Такая схема гарантирует, что даже при сбое каналов связи клиент получит ровно одно сообщение с правильными данными, а интернет-магазин сбережет бюджет на рассылки. Дополнительно рекомендуем узнать, как настроить персонализацию SMS для интернет-магазина в 2026 году, чтобы сообщения оставались полезными и содержательными.
Типичные ошибки при настройке транзакционных сообщений
- Отсутствие ответа 200 OK на вебхуки платежных систем. Если сервер интернет-магазина сначала выполняет долгую отправку SMS, а только потом отвечает банку, платежный шлюз разрывает соединение по тайм-ауту и присылает уведомление повторно.
- Генерация нового UUID при каждой повторной попытке (Retry). Если при сетевом сбое CRM генерирует новый ключ транзакции для той же операции, SMS-шлюз воспринимает запрос как новую рассылку.
- Игнорирование статусов доставки от сотовых операторов. Без разбора DLR-отчетов невозможно понять, доставлено ли первое сообщение или номер временно недоступен.
- Слишком короткий таймаут ожидания HTTP-ответа. Установка времени ожидания менее 2 секунд приводит к ложным повторам запросов при временных задержках на магистральных каналах.
3 шага, которые можно сделать на этой неделе:
- Проверьте журнал системных событий CRM и найдите случаи, когда по одному заказу ушло больше одного SMS за 5 минут.
- Добавьте в код интеграции с SMS-шлюзом передачу внешнего ID заказа в качестве ключа дедупликации.
- Настройте мгновенный возврат HTTP-статуса 200 для входящих платежных вебхуков до запуска триггерных скриптов.



