Статьи

Реализация двухсторонних SMS с PHP

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

Двусторонние SMS-приложения более сложны, чем односторонние. В двухсторонних приложениях SMS пользователь может начать разговор, отправив сообщения, а затем приложение отвечает в соответствии с командами пользователя.

В этой статье я объясню процесс двусторонних SMS-взаимодействий и покажу, как вы можете включить его в свои PHP-приложения. В мире существует множество популярных SMS-шлюзов, которые обеспечивают двустороннюю передачу сообщений; В моих объяснениях здесь я буду использовать Clickatell.

Двухсторонний жизненный цикл SMS

Жизненный цикл двусторонней СМС можно разделить на 4 основных этапа, как показано ниже:

  1. Пользователь отправляет запрос на SMS-шлюз
  2. SMS-шлюз пересылает запрос на сервер приложений
  3. Сервер приложений обрабатывает запрос и отвечает на SMS-шлюз
  4. SMS-шлюз пересылает запрос обратно пользователю

Шаг 1 — Пользователь к SMS-шлюзу

Пользователь инициирует разговор, отправив SMS-сообщение на шлюз. Первоначально он должен пройти через оператора мобильной связи пользователя. Эта часть не важна для нас, поскольку она находится в домене местного поставщика услуг. Через локального поставщика услуг сообщение принимается шлюзом SMS.

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

Выделенный длинный номер — это стандартный номер телефона, например +94112367899. Короткий код представляет собой 4-6-значный код. У каждого есть свои плюсы и минусы:

  • Короткие коды легче запомнить, чем выделенные длинные номера.
  • Выделенные номера могут использоваться во всем мире, в то время как шорткоды обычно ограничены одним поставщиком услуг в данной стране.
  • Выделенные длинные номера могут обрабатывать большее количество сообщений в течение заданного времени по сравнению с номерами короткого кода.

Выбор, использовать ли шорткод или выделенный длинный номер, остается за вами.

Как только SMS получено шлюзом, оно должно быть направлено в приложение для обработки. Перед маршрутизацией сообщения шлюз должен сделать две вещи:

  • Подготовьте данные сообщения так, чтобы приложение могло их понять.
  • Сопоставьте URL-адрес приложения с выделенным длинным номером или коротким кодом

Каждый шлюз имеет свои собственные методы для передачи данных на сервер приложений, хотя XML или SOAP через HTTP-соединение, как правило, наиболее популярны. Шлюз должен предоставлять какую-то документацию API, для которой когда-либо используется метод.

Разработчик приложения должен создать определенную точку входа в систему для обработки сообщений, полученных от шлюза; это называется URL приложения. Процесс сопоставления URL-адресов приложений с выделенным номером или шорткодом варьируется от одного шлюза к другому. Некоторые разрешают настройку напрямую через интерфейс учетной записи пользователя, как, например, Clickatell. Если этот параметр недоступен, мы должны связаться с ресурсом технической поддержки для шлюза и предоставить им URL-адрес приложения для настройки.

Этап 2 — SMS-шлюз на сервер приложений

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

В следующем примере кода показано, как Clickatell отправляет данные с помощью метода HTTP GET, и теперь вы можете получить их. Другие шлюзы также предоставляют аналогичный метод.

  https://www.example.com/sms/sms.php?api_id=12345&from=279991235642&to=27123456789&timestamp=2008-08-0609:43:50&text=Hereisthe%20messagetext&charset=ISO-8859-1&udh=&moMsgId=b2aee337abd962489b123fda9c3480fa 
<?php $fromNo = $_GET["from"]; $toNo = $_GET["to"]; $message = $_GET["text"]; $msgID = $_GET["moMsgId"]; // Process the user command and generate output ... 

И вот пример, где данные размещены в виде XML-документа.

 <?xml version="1.0"?> <clickmo> <api_id>xxx</api_id> <moMsgId>fa6ba35b330ce1bc7e2008e5d92d57aa</moMsgId> <from>handset_number_here</from> <to>mo_number_here</to> <timestamp>2007-02-26 14:36:50</timestamp> <text>xxx</text> <charset>ISO-8859-1</charset> <udh></udh> </clickmo> 
 <?php $data = $_POST["data"]; $xmlDoc = new DOMDocument(); $xmlDoc->loadXML($data); $fromNo = $xmlDoc->getElementsByTagName("from"); $fromNo = $fromNo->item(0)->nodeValue; $toNo = $xmlDoc->getElementsByTagName("to"); $toNo = $toNo->item(0)->nodeValue; $message = $xmlDoc->getElementsByTagName("text"); $message = $message->item(0)->nodeValue; // Process User Message and Generate Response ... 

Приложение должно захватывать входящие данные с помощью одного из доступных методов и обрабатывать команды пользователя. В простом сценарии, когда сообщение пользователя содержит менее 160 символов, этот код работает отлично. Но что будет, если в сообщении будет более 160 символов?

Давайте предположим, что телевизионная станция запускает рекламную кампанию, где пользователи могут отправлять рекламу в виде SMS. После отправки SMS пользователь получит период времени с сервера, на котором будет отображаться реклама. Рекламные объявления только текстовые и будут отображаться в нижней части экрана. Давайте также предположим, что у нас есть предопределенный формат для отправки сообщений, как показано ниже.

  реклама спорт название вашей рекламы название сообщения содержание вашей рекламы 

Все содержимое сообщения отображается в виде пар значений. advertisement будет меткой, а спорт будет значением, представляющим категорию рекламы. Затем title — это следующий ярлык, а его значением будет заголовок рекламы. message является окончательной меткой и будет тем контентом, который пользователь хочет отобразить в рекламе.

В зависимости от длины заголовка и сообщения, это SMS может содержать более 160 символов. Каждый раз, когда получено длинное сообщение, шлюз разбивает его на несколько частей по 160 символов. Но все же мы должны обрабатывать эти две части как одно сообщение.

Если мы используем предыдущие примеры кода для разбора сообщений, части 1 и 2 одного и того же сообщения будут обрабатываться как два разных сообщения. И поскольку обе части не имеют полной команды, приложение отправит обратно ошибку пользователю. UDH является решением этой проблемы.

Что такое UDH?

UDH означает заголовок пользовательских данных. Когда мы отправляем длинное сообщение, отправляющее устройство (мобильный телефон) разделяет сообщение и отправляет его как отдельные сообщения. Значения UDH будут назначаться в начале каждой части сообщения, чтобы принимающее устройство могло идентифицировать их как принадлежащие одному сообщению и рекомбинировать их.

Значения UDH для более раннего сценария будут выглядеть так:

  Часть 1 - 05 00 03 CC 02 01
 Часть 2 - 05 00 03 CC 02 02 

Последние два шестнадцатеричных значения будут самыми важными значениями в UDH. Цифра от второго до последнего — 02 в приведенных выше кодах и определяет количество частей в сообщении. Итак, это сообщение было разделено на две части. Если доступны три части, то это значение должно быть 03 и т. Д. Следующая цифра определяет номер части сообщения. 01 означает первую часть, 02 означает вторую часть и т. Д.

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

 <?php $fromNo = $_GET["from"]; $toNo = $_GET["to"]; $message = $_GET["text"]; $msgID = $_GET["moMsgId"]; $udh = $_GET["udh"]; $total = 1; $count = 1; if ($udh) { $tmp = str_split($udh, 2); $total = hexdec($tmp[4]); $count = hexdec($tmp[5]); } if ($count != $total) { // Save the message fragment in database saveMessagePart($db, $from, $message, $udh); } else if ($total != 1) { $prevParts = getMessageParts($db, $from); $message = $prevParts . $message; } // process $message ... 

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

Этап 3 и 4 — сервер приложений к шлюзу SMS, шлюз к пользователю

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

Как правило, SMS-шлюзы предоставляют URL-адрес обратного вызова для передачи данных ответа. Обычно вам необходимо указать номер получателя, номер отправителя, содержание сообщения и некоторую информацию для аутентификации. Точные параметры будут варьироваться в зависимости от шлюза, но для Clickatell они должны, from , text , и api_id , username и password .

 <?php $message = array( "to" => 942288345, "from" => 944488345, "text" => "sample message", "api_id" => API_KEY, "user" => "myUsername", "password" => "secret" ); $apiUrl = "http://api.clickatell.com/http/sendmsg?"; foreach ($message as $parameter => $value ) { $apiUrl .= $parameter . "=" . urlencode($value) . "&"; } $apiUrl = rtrim($apiUrl, "&"); $ch = curl_init(); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_URL, $apiUrl); curl_exec($ch); curl_close($ch); 

Приведенный выше пример кода кодирует все параметры с помощью функции urlencode() и добавляет их к URL-адресу обратного вызова API. Затем мы инициализируем запрос cURL и вызываем URL. Ответное сообщение теперь отправлено шлюзу, что завершает шаг 3.

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

Резюме

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

Изображение через Fotolia