Настройка SMS-шлюза Kannel. Технические подробности прямой интеграции

  • Tutorial

Несколько раз были упоминания такого замечательного софта как kannel, однако почему-то нет конкретных описаний примеров его интеграции. приводится пример сервиса, который можно реализовать при договоренности с оператором сотовой связи (опсосом), однако до сих пор не понятно каким образом это сделать. Попробую исправить эту ситуацию.

Оффтопик. Зачем это мне понадобилось?

Я давно работаю над одним проектом , суть которого заключается в проведении реальных городских игр под флагом Мегафона. Сначала это были игры, для которых был создан простенький онлайн-сервис на Zend Framework, в котором можно было регистрироваться, формировать команды, участвовать в играх, получать задания, вводить ответы. Однако, мы с организаторами задумались, каким образом этот процесс можно было бы сделать более доступным для масс и более мобильным. Решили переделать данную платформу для работы с SMS. Сказано – сделано, я связался с технарями Мегафона, узнал каким образом мы могли бы принимать и отправлять SMS (естественно, значительно более предпочтительно было использовать http, т.к. никаких усилий для его интеграции не требовалось и многие sms-сервисы предоставляют такую возможность), в Мегафоне дали лишь голый SMPP. Делать нечего, пришлось выкручиваться.

Долго искал хороший вариант для шлюза, таким вариантом стал Kannel - опенсорсный SMS, WAP шлюз. WAP-составляющая меня не интересовала, однако он оказался действительно очень качественным решением для SMPP-HTTP шлюза (так же его можно использовать для отправки и приема SMS с помощью SMPP в качестве сервера, MySQL для приема и отправки сообщений в виде строк БД).

Перейдем к практике.

Во многом конфиги дублируют то что я приводил в своей статье про интеграцию с Мультифоном , однако здесь именно приводится пример работы с SMPP оператора сотовой связи.

Я пропущу часть установки и первичной настройки, вы с ними можете ознакомиться в ранее упомянутой статье.

Немного теории. Эта система немного нестандартна. Она состоит из нескольких отдельно стоящих демонов. Есть демон, который надзирает над остальными, и, если вдруг процесс умирает, то он его запускает заново. Этот демон прописан при запуске из rc.d или init.d, можете в пусковых скриптах ознакомиться с его параметрами.

bearerbox – главный демон, который держит связь по SMPP в качестве клиента, работает с 3g-донглами, слушает порт для подключения других демонов.
smsbox – демон, отвечающий за прием сообщений из веб-сервиса и передающий их в bearerbox для отправки
opensmppbox – демон, который работает как SMPP сервер для подключения других клиентов. Тоже подключается к bearerbox и работает через него.
wapbox – демон, работающий как wap-гейт. Честно говоря, я толком не разбирался с ним.
sqlbox – отличный интересный демон, который может записывать приходящие сообщения в MySQL БД определенной структуры, а так же отправлять SMS, которые добавляются в MySQL БД. Это дает возможность интегрировать sms непосредственно в модель по MVC. То есть, отправка - это всего лишь создание и сохранение объекта sms внутри вашего MVC приложения, круто, да? И аналогично приём, однако, в таком случае вы не получите callback о том что у вас пришло sms, придется запускать скрипт по крону и это уже будет не realtime.
За каждым из этих демонов должен быть привязан свой run_kannel_box . Это демон-надзиратель, для которого нужно дополнительно прописать в стартовые сценарии, если вы хотите в вашей конфигурации запустить больше одного bearerbox/smsbox/wapbox или присоединить другие демоны. Либо написать собственные сценарии с использованием параметра командной строки --parachute (-P), как предложил в комментариях zerkms .

Конфиг с комментариями
group = core admin-port = 13000 #порт, на котором вы сможете проверить состояние подключений и производить некоторые сервисные действия admin-password = pass #админ-пароль, никогда им не пользовался (т.к. всегда через консоль перезапускаю) log-file = "/var/log/kannel/bearerbox.log" log-level = 1 #если будут глюки, то устанавливайте в 0. 1 чтобы не превращать логи в помойку. access-log = "/var/log/kannel/access_kannel.log" store-file = "/var/log/kannel/store_sms" smsbox-port = 13001 #порт, к которому будут подключаться смс-боксы dlr-storage = internal sms-resend-retry = 1 #всего 1 попытка при отправке. group = smsc smsc-id = povoljye smsc = smpp host = xxx.xxx.xxx.xxx #параметры, которые получаем у ОПСОСА port = xxxx smsc-username = "name" smsc-password = "pass" source-addr-ton = 0 #эти 4 параметра вы должны получить у ОПСОСА. Без них ничего не будет работать. source-addr-npi = 1 #в данном случае - параметры Мегафона. dest-addr-ton = 1 dest-addr-npi = 1 system-type = VMA #по-моему ни на что не влияет) throughput = 1000 #макс. пропускная способность reconnect-delay = 5 #переподключение после дисконнекта connection-timeout = 120 #считать разрывом, если другая сторона не отвечает в течение N сек. transceiver-mode = true #Внимание, обязательно указывайте этот параметр! Вызывает дикие неуловимые глюки, если вы будете использовать единый порт для приема-передачи без этого параметра. Мне пришлось писать главному коммитеру данного ПО, чтобы найти этот косяк, не повторяйте моих ошибок. denied-smsc-id = kemerovo #в данном случае - необходимо для того чтобы разграничить куда будут идти SMS при явном указании SMSC. Иначе SMS будут уходить round-robin, что будет нежелательно, если ваши центры неравнозначны, не могут отправлять SMS одним и тем же номерам. allowed-smsc-id = povoljye preferred-smsc-id = povoljye group = smsc #пример сочетания двух smsc для одного приложения. В данном случае - один для поволжья, а другой для сибири. smsc-id = kemerovo smsc = smpp host = xxx.xxx.xxx.xxx #все аналогично port = xxxx receive-port = xxxx smsc-username = "kemerovo" smsc-password = "pass" source-addr-ton = 0 source-addr-npi = 1 dest-addr-ton = 1 dest-addr-npi = 1 reconnect-delay = 5 system-type = VMA throughput = 1000 connection-timeout = 120 transceiver-mode = true denied-smsc-id = povoljye allowed-smsc-id = kemerovo preferred-smsc-id = kemerovo group = smsbox bearerbox-host = localhost sendsms-port = 13003 #порт, на котором smsbox слушает http для отправки сообщений global-sender = 000037 #номер телефона отправителя по умолчанию log-file = /var/log/kannel/smsbox.log log-level = 0 access-log = /var/log/kannel/access_smsbox.log group = sendsms-user username = "user1" #пользователь, которого вы должны указывать при отправке SMS в вашем http запросе password = "pass" concatenation = true #включить склейку сообщений max-messages = 20 #максимальное число склеенных сообщений default-smsc = povoljye group = sendsms-user username = "user2" password = "pass" concatenation = true max-messages = 20 default-smsc = kemerovo #ENGINE group = sms-service keyword = default #любые sms будут приходить сюда. Можно их отделить с помощью ключевого слова. post-url = "http://example.com:8080/controller/action/tel/%p/time/%t/coding/%c/smsc/%i" #зендовский url с параметрами concatenation = true max-messages = 0 #по умолчанию kannel отправляет ответ, который приходит в теле http response. Мне это не надо, т.к. я предпочитаю управлять исходящими сообщениями из приложения.

Итак, в данном случае мы рассмотрели подключение к 2м sms-центрам Мегафона с раздельной отправкой в зависимости от параметра smsc.

Так мы отправляем SMS (см.

Многие считают, что SMS - одна из причин того, что Твиттер так хорошо «выстрелил» на Западе. В США и ряде стран Европы твиты можно как публиковать, так и получать через SMS, при этом цена исходящего твита равна цене обыкновенной SMS, а входящие сообщения - бесплатны. Для пользователей без смартфонов (коих большинство) это значительно снижает порог на вход.

В этой статье я поделюсь опытом прямой интеграции с крупным российским сотовым оператором (обратите внимание: именно напрямую, а не через шлюзы), а также на вводном уровне порассуждаю об околоSMS-ных технологиях и протоколе SMPP - без скучных таблиц и спецификаций, в стиле короткой детективной истории.

Завязка сюжета

Однажды мы (Рутвит) обратились с предложением к крупнейшему оператору связи - компании МТС. Мы понимали: чтобы сделать цену твита неотличимой от цены обычного SMS, нужна прямая интеграция с ОПСОС-ом (кстати, это слово расшифровывается как «Оператор Сотовой Связи»). МТС - огромная компания, заточенная на сотрудничество с крупными партнерами, поэтому я полагал, что наше предложение рассмотрят нескоро, и не особенно рассчитывал на успех. Какова же была наша радость, когда МТС не только быстро ответила, но и в результате конструктивных переговоров приняла решение запустить совместный проект с Рутвитом.

Все мы знаем, что крупные компании зачастую медлительны и неповоротливы, однако это, похоже, не относится к МТС. Рабочая группа, с которой мы контактировали в процессе интеграции, быстро реагировала на наши вопросы, и мы продвигались вперед. Это было особенно ценно в той связи, что прямая интеграция с сотовым оператором оказалась на порядок сложнее, чем подключение какого-нибудь популярного SMS-шлюза: я еще расскажу о технических подробностях ближе к концу статьи.

И вот мы сначала запустили альфа-версию SMS-сервиса на Рутвите (читать совместный с МТС пресс-релиз на сайте ПРАЙМ-ТАСС), а сегодня заменяем в этом сервисе значок «альфа» на «бету», о чем и сообщаем в данной статье. Сервис, помимо прочего, позволяет отправлять твиты с помощью SMS по обычной стоимости (согласно тарифного плана абонента) не только в Рутвит, но и в большой Твиттер - через механизм экспорта.

Итак, отправлять твиты по SMS можно ровно за те же деньги, за которые вы отправляете любую другую SMS. Для этой же цели мы решили использовать не короткий номер, а более привычный, длинный: +7 916 140-0-140 . Люди часто не доверяют коротким номерам, т.к. не уверены, сколько денег с них снимут за SMS: с длинным номером такой проблемы как будто бы нет.

Как начать писать твиты по SMS?

Чтобы начать писать твиты по SMS, введите номер своего телефона на сайте Рутвита:

Затем отправьте слово «да» (регистр не важен) на номер Рутвита +7 916 140-0-140 . Как только робот увидит это сообщение, он привяжет ваш номер к вашему аккаунту, и все последующие SMS на номер +7 916 140-0-140 будут восприниматься как твиты от вашего имени.

А еще можно писать SMS по себестоимости в Твиттер, FriendFeed, Facebook, LiveJournal, Buzz

Если вы поклонник Твиттера, настройте экспорт сообщений Рутвит -> Твиттер (или FriendFeed, Facebook, LiveJournal, Buzz) и пишите в Твиттер (FriendFeed, Facebook, LiveJournal, Buzz) SMS по себестоимости, используя Рутвит в качестве шлюза:

(Для справедливости стоит отметить, что в Twitter можно отправлять SMS и через зарубежные шлюзы, однако в России это получается сильно дороже: ведь SMS на британский номер +44xxxx, предоставляемый Твиттером, дороже SMS на российский номер Рутвита +7 916 140-0-140.)

Теперь ложка дегтя, присутствующая в бета-версии. Одна из наших целей - сделать так, чтобы пользователь мог не только отправлять SMS в Рутвит по цене обычного SMS, но также и бесплатно получать по SMS твиты на мобильный телефон. Некоторые сервисы микроблогов просто покупают GSM-модем (или смартфон с Linux) и принимают/отправляют SMS через него, однако этот способ работает только на небольших объемах трафика: он плохо масштабируется. Тем не менее, мы хотим избавить пользователей социальных сетей от дополнительных затрат при активации и пользовании данным сервисом. Но только техническая интеграция и заключение договора напрямую с оператором позволит этого добиться. А пока идут переговоры, в бета-версии не реализована возможность приема SMS на телефон: можно только отправлять твиты в систему. В этом вопросе мы делаем ставку на будущее.

Технические подробности прямой интеграции

Мы раньше никогда не работали с SMS и протоколом SMPP . И, когда мы подписали договор с МТС, мы столкнулись с выбором:
  • либо сделать SMPP-клиента вручную (с использованием модулей для Perl, например);
  • либо использовать готовый SMPP-сервер промышленного масштаба (самый популярный из них - Kannel).
В итоге было решено остановиться на втором варианте, и мы не пожалели об этом, потому что в процессе интеграции мы наступили на массу подводных граблей, многие из которых были успешно разрешены Kannel-ом.

Немного о SMPP, протоколе передачи SMS-сообщений

Протокол SMPP (расшифровывается как «Short Message Peer to Peer») сам по себе весьма сложен. Он очень низкоуровневый (спецификации занимают 170 страниц). Сложность обусловлена, главным образом, историческими причинами. Группа протоколов для передачи голоса разрабатывалась в 1975 г. В те времена никаких SMS еще не было (не было даже ЖК-дисплеев для сотовых телефонов, как и самих мобильников). И вот, в 1985 г. в стандартные пакеты протокола передачи голоса решили «упихать» поддержку текстовых сообщений. Но полезного места в этих пакетах было мало, поэтому сообщения получились короткими, всего 160 символов - Short Messages.

Полезный объем данных, который можно передать в SMPP-пакете, составляет 140 байт. Это не опечатка. Как же в них поместилось 160 символов? Вы, наверное, уже догадались: 1 символ ASCII можно закодировать 7 битами. Таким образом, получается 160 * 7 = 1120 бит, или 140 байт.

Если бы мы жили в США, где кодировки ASCII «должно быть достаточно каждому», то мы бы спокойно писали твиты размером 160 символов. Однако при передаче русских букв по SMS они упаковываются в кодировку UTF-16, т.е. 2 байта на 1 русскую букву. Поэтому в 1 сообщении может поместиться не более 140/2 = 70 символов русского алфавита. Если текст длиннее, он упаковывается в 2 и более SMS-сообщения, которые затем «склеиваются» при отображении на телефоне.

Но это еще не все. В 2 SMS-сообщениях можно доставить вовсе не 70 * 2 = 140 русских букв, а всего только 134. Дополнительное место требуется для кодирования служебной информации, в частности, информации о числе SMS в цепочке и номере текущей SMS в ней.

Kannel сотоварищи

Сервер Kannel, который мы использовали, на самом деле имеет более широкую область применимости. Он предназначен для контент-провайдинга, когда запрос представляет собой SMS, а ответ - некоторый SMS-контент: мелодии, картинки и т.д. Мы используем только ту часть, которая организует прием и трансляцию SMS: Kannel принимает SMPP-сообщение, распаковывает/расшифровывает его и передает нам HTTP-запросом номер телефона и текст. В ответ же мы не посылаем никакого контента.

Правда, не обошлось без сюрпризов. У МТС весьма скурпулезная схема тестирования: мы не только должны корректно принимать сообщения, но и укладываться во всевозможные тайм-ауты при постановке запросов в очередь, поддерживать throttling, вовремя отправлять сообщения-подтверждения доставки при взрывном росте нагрузки. На тестовом стенде мы столкнулись с проблемой, для решения которой нам пришлось немного пропатчить Kannel (он написан на Си). Вкратце ее можно описать так: предположим, на Kannel пришли 2 SMPP-пакета, а третий - уперся в ограничение пропускной скособности, заданной МТС, а поэтому - застрял в очереди. Если теперь ограничение снялось, но тут же пришло 4-е сообщение, то в стандартном варианте Kannel поставит это 4-е сообщение перед всеми ранее застрявшими. Поэтому 3-е сообщение опять окажется в конце очереди и будет отодвигаться все дальше и дальше по мере поступления новых SMS. Оказывается, для нагрузочных тестов МТС это поведение имеет значение - как и многие другие аспекты, которые пришлось учесть при прямой интеграции.

Мы не имели опыта работы с SMPP ранее, но Kannel позволил нам выкарабкаться. На наше счастье, Kannel даже в базовой конфигурации обрабатывает очень многое из того, что было нужно ОПСОС-у. Но, положа руку на сердце, сейчас, уже «съев собаку» на SMPP, мы бы стали все делать с использованием Perl и модулей с CPAN, а не Kannel. Но это было бы возможно только благодаря тому опыту, который мы получили с Kannel. Без этого опыта программирование прямой интеграции с ОПСОС-ом на Perl - все равно, что учить человека плавать, бросив его в воду с обрыва: может, и научится, а может, утонет. МТС особенно скурпулезен при тестировании обработки ошибок, выдерживания разнообразных тайм-аутов. Например, четко регламентируется время отправки подтверждений *_resp на SMPP-сообщения: задержки должны укладываться в заданные МТС временные интервалы. Если вы решите работать с SMPP напрямую, изучите вначале Kannel: я бы рекомендовал делать вам собственное решение, повторяя архитектуру Kannel-а, особенно - аспектов буферизации сообщений.

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

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

Решающим моментом стало наличие хорошей документации к API и наличие готовых решений для распространенных CMS. Мой первый выбор пал на сервис интернет рассылок от ButeHand . Стоимость одного смс в 40коп. для меня не играла роли. В общем все очень быстро завелось на joomshopping и функционирует, по крайней мере особых нареканий небыло.

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

А оказалось что моему собеседнику захотелось построить собственный шлюз смс рассылок. Причем с внушительной пропускной способностью. Вопросы которые он задавал были вполне логичны и с недурным любопытством. Минимальный ценник за 1 смс который мне удалось в стретить в интернете - это 7 коп. , но чаще ценник начинался от ометки 40 коп. Мне дали понять что и 6 коп. если количество смсок начинается от миллиона, - это дорого и что возможно собрать сервер рассылки самостоятельно.

Итак постараемся разобраться что такое смс шлюз и какие варианты его реализации есть.

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

Применяется sms шлюз чаще всего в следующих целях:

  • уведомление владельца банковского счета о транзакциях;
  • подтверждение регистрации на сайте или в системе;
  • информирование о состоянии выполнения заказа;
  • информирование о новых акциях, услугах компаний;

Шлюз , в данном контексте, это система которая позволяет отправлять и принимать смс. Собственно, использование API другого шлюза для отправки и создание своего API для приема смс превращает написанное в шлюз.

Если же интересует как работают большие шлюзы, которые обрабатывают миллионы смс в день, то нужно смотреть в сторону протокола SMPP или, если есть желание копать еще глубже, то SS7 .

SMPP Short message peer-to-peer protocol - протокол, описывающий взаимодействие конечного клиента с SMS-сервером (SMSC). Используется для передачи SMS и USSD сообщений.

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

Можно арендовать короткий номер у всех операторов, или у агрегаторов (дешевле будет даже не номер, а отдельный префикс, при этом принимать сообщения будете по HTTP от агрегатора, а отправлять сможете как через агрегатора, так и через внешние шлюзы)

Если рассматривать собственный сервер , например чтобы преодолеть лимит в 500 смс/день, как вариант мы можем приобрести несколько сим-карт с красивыми номерами от разных провайдеров и собрать все сами, например на GSM модемах, как советует пользователь блога Subnets . Для приема сообщений кроме как модемом, можно арендовать и промышленный сервис (есть у многих поставщиков, гуглить по словосочетанию Sim hosting)

Если достаточно готового интернет шлюза, то также придется платить:

http://sms.ru/ - от 25 коп. входная цена до 7 коп. оптом.

http://www.smscourier.ru/ - от 20 коп. до 7 коп. оптом. Есть также единый тариф 14 коп. без зависимостей от кол-ва смс .

http://sms.gt/ - 1 доставленное смс - 7 копеек, по заверению разработчиков - никаких пакетов, никаких скрытых платежей .

http://smsaero.ru/ - Низкие цены от 19 до 4 копеек за 1 SMS-сообщение. Понравилось что есть 100 бесплатных смс и заявленная скорость отправки - 300смс в секунду . Так же у сайта оказался очень понятный и приятный интерфейс.

Итак мы выяснили, что сам сервис изначально должен создавться опираясь на бюджет и количество времени которое мы готовы уделять его администрированию. Либо это будет готовый интернет шлюз, либо нам необходимо будет ставить свое оборудование и искать специалистов. Немаловажным фактором является возможность прямого выхода на провайдеров своего города, так как от их техподдержки и качества каналов связи напрямую зависит качество нашего проектируемого сервиса.

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