Интеграция SMS-рассылки в мобильное приложение
SMS-рассылка в мобильном приложении — это серверная задача. Клиент только инициирует запрос: «отправить уведомление пользователям X, Y, Z». Всё остальное — HTTP-запрос на бэкенд или напрямую к SMS-шлюзу. Поэтому мобильная часть интеграции небольшая, зато серверная требует аккуратного проектирования.
Выбор шлюза
Самые распространённые варианты:
| Шлюз | Плюсы | Минусы |
|---|---|---|
| Twilio | REST API, webhooks, глобальный охват | Дороже аналогов для СНГ |
| SMSC.ru / SMS-шлюз.ру | Дёшево для РФ/СНГ | Нет webhook-уведомлений о статусе у ряда тарифов |
| Infobip | Multichannel (SMS + Viber + WhatsApp) | Сложный onboarding |
| Vonage (Nexmo) | SDK для мобильных, верификация номеров | Ограниченный охват по СНГ |
Для типичного B2C-приложения с аудиторией в СНГ — SMSC или аналогичный локальный шлюз. Для международного — Twilio или Infobip.
Серверная часть: что важно реализовать
Отправка SMS через Twilio — один HTTP-запрос:
POST https://api.twilio.com/2010-04-01/Accounts/{AccountSid}/Messages
Authorization: Basic {base64(AccountSid:AuthToken)}
Content-Type: application/x-www-form-urlencoded
To=%2B380991234567&From=%2B14155551234&Body=Ваш+заказ+готов
Но bulk-рассылка — это очередь, не прямые вызовы в цикле. Одновременная отправка 10 000 сообщений через синхронные HTTP-запросы убьёт и бэкенд, и бюджет (rate limiting шлюза). Правильная схема: очередь задач (RabbitMQ, Redis + BullMQ, SQS), воркеры с throttling по rate limit шлюза.
Twilio rate limit — до 100 SMS/сек на коротком номере (Short Code), 1 SMS/сек на обычном (Long Code). Если шлёте на обычный номер — воркеры должны соблюдать это ограничение.
Мобильный клиент: что реализуется
На мобильной стороне нужно:
- Форма составления сообщения — с подсчётом символов (160 для Latin, 70 для Cyrillic, concatenation при превышении).
- Выбор сегмента получателей — через готовый API бэкенда.
- Запуск рассылки — POST-запрос с параметрами.
- Отслеживание статуса — polling или WebSocket/SSE для real-time прогресса.
// iOS — отправка запроса на рассылку
struct BulkSmsRequest: Codable {
let segmentId: String
let message: String
let scheduledAt: Date?
}
func sendBulkSms(_ request: BulkSmsRequest) async throws -> BulkSmsJob {
let response = try await apiClient.post("/admin/sms/bulk", body: request)
return try response.decode(BulkSmsJob.self)
}
Символьный счётчик — важная деталь UX. SMS разбивается на части при превышении лимита, каждая часть тарифицируется отдельно:
fun countSmsPartsAndChars(text: String): SmsInfo {
val isGsm7 = text.all { it.isGsm7Char() }
val maxPerPart = if (isGsm7) 160 else 70
val maxConcatenated = if (isGsm7) 153 else 67
return if (text.length <= maxPerPart) {
SmsInfo(parts = 1, charsUsed = text.length, charsPerPart = maxPerPart)
} else {
val parts = ceil(text.length.toDouble() / maxConcatenated).toInt()
SmsInfo(parts = parts, charsUsed = text.length, charsPerPart = maxConcatenated)
}
}
Статусы доставки
Twilio отправляет webhook на ваш сервер при изменении статуса каждого сообщения: queued → sending → sent → delivered или undelivered / failed. Бэкенд агрегирует статусы, мобильный клиент запрашивает сводку:
GET /admin/sms/jobs/{jobId}/stats
→ { "total": 5000, "sent": 4823, "delivered": 4601, "failed": 177 }
Сроки
Интеграция SMS-шлюза (Twilio или SMSC), реализация очереди рассылки, мобильный UI с счётчиком символов, выбором сегмента и отслеживанием прогресса — 5–8 рабочих дней.







