29 сентября, 2026

Маппинг статусов SMS-провайдеров: единая модель DLR

1 мин
Время чтения

У SMS-провайдеров отличаются названия и детализация статусов. Один возвращает DELIVRD, другой delivered, третий числовой код. Временная ошибка у одного означает повтор маршрута, а похожее слово у другого — финальный отказ. Если бизнес-система напрямую использует внешний словарь, смена шлюза затрагивает отчёты, автоматические действия и поддержку.

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

Зачем два уровня статусов

Внутренний статус отвечает на общий вопрос: сообщение принято, обрабатывается, доставлено или завершилось ошибкой. Внешний код объясняет детали конкретного маршрута. Если оставить только общий статус, поддержка потеряет причину. Если оставить только внешний, бизнес-логика станет зависеть от провайдера.

Практичная запись содержит:

  • внутренний delivery_status;
  • исходные provider_status и provider_error_code;
  • признак финальности;
  • время события у провайдера и время получения;
  • provider message ID;
  • версию таблицы маппинга;
  • безопасное описание причины.

Базовая внутренняя модель

Набор зависит от продукта, но обычно достаточно состояний:

  • queued — задача создана внутри системы;
  • accepted — SMS API принял сообщение;
  • processing — провайдер или оператор продолжает обработку;
  • delivered — получен финальный положительный DLR;
  • failed_temporary — известна временная проблема, возможны дальнейшие действия;
  • failed_permanent — финальная недоставка;
  • expired — истёк срок жизни;
  • rejected — сообщение отклонено до доставки;
  • unknown — код пока не распознан.

Не объединяйте accepted и delivered. Успешный HTTP-ответ означает приём запроса, а не доставку на устройство. Общий жизненный цикл DLR описан в статье про статусы доставки SMS.

Финальность и переходы

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

Вместо правила «последний webhook всегда прав» используйте таблицу переходов. Например, processing → delivered допустим, а delivered → processing игнорируется как запоздавшее событие. Спорный финальный переход сохраняется в журнале и поднимает сигнал, но не переписывает историю молча.

Неизвестные коды

Новый код провайдера нельзя автоматически считать постоянной ошибкой. Сохраните его как unknown, добавьте метрику и уведомление владельцу интеграции. Затем документация сверяется, таблица маппинга обновляется и получает новую версию.

Fallback по строкам вроде «содержит fail» ненадёжен. Код и его смысл должны быть перечислены явно. Для числовых значений учитывайте тип: строка 001 не равна числу 1, если ведущие нули значимы в контракте.

Webhook и первичный ответ

Синхронный ответ SMS API и последующий webhook DLR проходят через один нормализатор, но имеют разные роли. Первый фиксирует приём или немедленный отказ. Webhook обновляет состояние позже.

Сохраняйте необработанный payload в защищённом ограниченном журнале только при необходимости и на заданный срок. Основная таблица должна содержать нормализованные поля, достаточные для работы продукта.

Причины для бизнеса и поддержки

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

Текст для клиента и внутреннее описание разделяются. Нельзя показывать пользователю непроверенный сырой комментарий внешней системы. Для поддержки сохраняют provider code и ссылку на актуальную документацию.

Аналитика без искажений

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

Долю доставки считают только по сообщениям, для которых прошло достаточное окно получения финального DLR. Иначе свежие processing временно ухудшат показатель. Скорость и SLA анализируют отдельно, как описано в материале про скорость доставки SMS.

Тестирование маппинга

Создайте набор fixtures из документированных и реально встреченных payload. Для каждого проверьте внутренний статус, финальность, причину и допустимый переход. Отдельные тесты нужны для дубликата события, неизвестного кода, нарушения порядка и webhook без message ID.

При подключении нового провайдера контракт считается готовым не после первой успешной SMS, а после прохождения всех значимых веток статусов. Недоступные в тесте случаи согласуются с поддержкой и помечаются как неподтверждённые.

Чек-лист

  • внутренний словарь мал и не зависит от названий провайдера;
  • исходный код и ошибка сохраняются рядом;
  • у каждого кода задана финальность;
  • переходы защищены от запоздавших событий;
  • неизвестный код заметен и не маскируется;
  • маппинг имеет версию и тестовые fixtures;
  • синхронный ответ не считается доставкой;
  • аналитика учитывает окно ожидания финального DLR;
  • бизнес-причины отделены от сырого текста провайдера.

Итог

Единая DLR-модель изолирует продукт от словаря конкретного SMS-шлюза. Она упрощает миграцию, отчёты и автоматические реакции, не уничтожая диагностические детали. Ключевые свойства — сохранение исходного кода, явная финальность, контролируемые переходы и заметное состояние unknown.

Обновлено 29 сентября, 2026

Общая учётная запись администратора удобна до...

7 октября, 2026

Интеграция может месяцами работать, а затем...

Подходит каждому
SMS-рассылка для любой сферы бизнеса
Узнайте как внедрить SMS-рассылку в ваш бизнес вместе с quicktel
Оставьте номер и вам перезвонит менеджер.