Как TLVs в SMPP помогают разбирать отчеты о доставке и экономить

TLV — это дополнительные поля в пакетах SMPP, которые переносят служебные данные помимо текста и адреса. Если заполнять их при отправке, каждый отчет о доставке приходит с меткой: какая это кампания, какой филиал, какой тип сообщения. Вы видите, где именно теряются SMS, и убираете из маршрута направления с плохой доставляемостью. Ниже — как это настроить на практике, не переписывая всю интеграцию.
Что такое TLV и почему без них отчеты слепые
Пакет submit_sm состоит из обязательных полей: адрес отправителя, адрес получателя, текст, кодировка. Остальное — опциональные параметры, они и называются TLV, то есть tag-length-value. У каждого свой числовой тег, длина и значение. Шлюз передает их оператору, а часть возвращается обратно в отчете о доставке.
Без TLV аналитика держится на тексте сообщения и времени отправки. Выгружаете лог, сопоставляете по номеру и дате. Это работает, пока кампаний две. Когда их двадцать, а часть SMS уходит по расписанию, ручное сопоставление съедает время, и отчеты все равно путаются.
Как связать отчет о доставке с конкретной рассылкой
Механизм простой. В submit_sm вы кладете TLV user_message_reference с тегом 0x0204 — произвольное число, которое назначаете сами. Например, 1001 для напоминаний о записи, 2001 для акции в Гомеле, 2002 для акции в Бресте. SMSC хранит это значение и возвращает его в deliver_sm вместе с receipted_message_id (тег 0x001E) — идентификатором исходного сообщения.
В итоге каждая запись в таблице отчетов несет два признака: ваш внутренний код и системный id. Первый читает маркетолог, второй нужен разработчику при разборе инцидентов.
Провайдеры поддерживают user_message_reference не всегда. Тогда остается receipted_message_id: message_id из ответа submit_sm_resp сопоставляется с полем receipted_message_id в отчете о доставке. Метку кампании в этом случае хранят у себя в базе, а связь строят по id. Вариант рабочий, но требует своей таблицы соответствия.
Как сегментировать отчеты и где здесь экономия
Сегментация начинается с группировки. Разбейте поток по коду кампании, оператору, диапазону номеров и времени суток. Дальше считайте delivery rate по каждой группе отдельно. Общая доставляемость по всей базе скрывает провал: сводная цифра выглядит нормально, пока один сегмент сыпется наполовину.
Отдельно смотрите коды ошибок. В отчете приходит stat со значениями вроде UNDELIV, EXPIRED, REJECTD, и поле err с причиной. Если один и тот же код повторяется на конкретном сегменте, дело чаще в маршруте или в содержании текста. Такой сегмент выводят из основного потока и отправляют по резервному маршруту — техническую сторону этого разобрали в статье про fallback-маршрутизацию SMS при сбоях SMPP.
Экономия складывается из двух частей. Первая — вы не платите за повторные попытки на сегментах, которые стабильно не доставляются. Вторая — тариф. Стоимость одного SMS собирается из тарифа оператора-агрегатора, комиссии шлюза и надбавок за отдельные направления (smsblog.ru). Когда видно, какой сегмент дает 99% доставки, а какой 60%, разговор с провайдером идет предметно, а не про «дорого».
Какие TLV стоит использовать в первую очередь
Список короткий. Микробизнесу хватает четырех-пяти параметров, остальное подключают по мере надобности.
| TLV | Тег | Что дает |
|---|---|---|
| user_message_reference | 0x0204 | свой код кампании, возвращается в отчет о доставке |
| receipted_message_id | 0x001E | id исходного сообщения в отчете |
| message_payload | 0x0424 | текст отдельно от обязательных полей, удобно для длинных сообщений |
| sar_msg_ref_num | 0x020C | склейка сегментов длинной SMS на стороне получателя |
| dest_addr_subunit | 0x0005 | подсказка для маршрутизации на стороне SMSC |
Поддержку конкретных тегов подтверждают у провайдера: набор отличается даже у шлюзов с похожим набором услуг. Два-три письма в поддержку экономят неделю отладки.
Почему живая сессия важнее самих полей
Отчеты о доставке приходят по открытому соединению. Если оно оборвалось и никто этого не заметил, метки TLV не помогут — данных просто не будет. Документация Devino требует отправлять enquire_link, только если в течение 60 секунд не пришло ни одного PDU от SMSC. У Exolve указание другое: enquire_link каждые 15 минут независимо от трафика. Разница принципиальная — один шлюз считает молчание признаком обрыва, второй ждет регулярного heartbeat.
Настройку берут из документации конкретного провайдера. Общий шаблон тут не работает, а неверный интервал приводит к разрыву сессии и потерянным отчетам.
Если рассылки запускаются из CRM, метку кампании удобнее ставить прямо в триггере. Схема описана в разборе про интеграцию CRM и SMPP для SMS-уведомлений. Тем, кто работает в 1С, логика подойдет та же — есть отдельный материал про отправку SMS из 1С через SMPP-шлюз.
Типичные ошибки
- Один код кампании на все рассылки. Отчеты есть, а разложить их по источникам нельзя.
- Соответствие «код — кампания» хранится только в логах шлюза. Логи ротируются, история теряется.
- Коды кампаний и message_id пишут в одно поле. Разбирать такой отчет руками почти невозможно.
- Коды ошибок смотрят сводно по всей базе. Проблемный сегмент растворяется в общей статистике.
- Сессия не мониторится. Отчеты перестают приходить, а узнают об этом через неделю.
- Теги TLV выбираются наугад, без проверки поддержки у провайдера.
3 шага, которые можно сделать на этой неделе:
- Заведите реестр кодов кампаний и назначьте код каждой активной рассылке.
- Уточните у провайдера, какие TLV он возвращает в отчетах о доставке, и добавьте их в submit_sm.
- Разложите отчеты по сегментам и найдите группу с самой низкой доставляемостью — с нее и начинайте оптимизацию.


