В этом кратком руководстве от Фила Леггеттера мы рассмотрим, как отправлять и получать SMS в приложении Laravel. Мы реализуем эту возможность, используя Nexmo — платформу облачных коммуникаций, которая предлагает API-интерфейсы для инициализации телефонных номеров, отправки и приема SMS (что мы и будем использовать), а так же для совершения звонков.
Предварительные требования
Нам понадобится учетная запись Nexmo, установленный Nexmo CLI (интерфейс командной строки), а так же ваше предустановленное приложение Laravel. Кроме того, понадобится локальное туннеллирование, что бы служба Nexmo могла сделать HTTP запрос на локальный веб-сервер. Мы рекомендуем ngrok.
Введение
Первым делом мы создадим наше приложение Laravel SMS:
composer create-project --prefer-dist laravel/laravel laravel-sms
cd laravel-sms
Далее, добавим пакет Nexmo Laravel в composer.json:
"require": {
...,
"nexmo/laravel": "dev-master as 1.0",
"nexmo/client": "dev-master as 1.0"
},
Примечание: когда эти пакеты выйдут из бета-версии, вам нужно всего лишь включить пакет
nexmo/laravel
, а nexmo/client
будет добавлен автоматически в качестве зависимости.Добавим сервис-провайдер Nexmo в ваш конфигурационный файл
app.php
:'providers' => [
...,
Nexmo\Laravel\NexmoServiceProvider::class
]
Примечание: вы так же можете добавить его в
aliases
, если хотите использовать фасад.Установим пакеты и скопируем конфигурационный файл Nexmo:
› composer update
php artisan vendor:publish
Наконец, добавьте Nexmo API Key и API Secret в
/config/nexmo.php
, обновите значения API_KEY и API_SECRET, основываясь на значениях, содержащихся в настройках API в Nexmo Dashboard.'api_key' => 'API_KEY',
'api_secret' => 'API_SECRET',
Примечание: при желании вы можете объявить значения в
.env
и env(...)
.Отправка SMS
Примечание: для простоты мы добавим весь функционал в
app/Http/routes.php
.Добавьте следующий маршрут в
app/Http/routes.php
:Route::get('/sms/send/{to}', function(\Nexmo\Client $nexmo, $to){
$message = $nexmo->message()->send([
'to' => $to,
'from' => '@leggetter',
'text' => 'Sending SMS from Laravel. Woohoo!'
]);
Log::info('sent message: ' . $message['message-id']);
});
Стоит отметить, что в приведенном коде
from
содержит значение @leggetter
. Это сработает в Великобритании, но не в других странах. Для тех из вас, кому нужно использовать реальный номер, давайте рассмотрим использование существующего номера, а так же его покупку.
Листинг, поиск и аренда номеров
Одной из предпосылок для этого урока был Nexmo CLI. Мы можем использовать его для множества действий, в том числе для работы с телефонными номерами (виртуальными номерами, если быть точным), которые связаны с нашей учетной записью. Если вы еще не сделали этого, вы должны установить и настроить CLI, где
API_KEY
и API_SECRET
должны быть заменены учетными данными API, которые использовались ранее:› npm install -g nexmo-cli
nexmo setup API_KEY API_SECRET
Теперь мы можем просмотреть доступные номера, которые мы уже арендовали, искать номера, доступные для аренды, а так же арендовать или отменить аренду определенного номера. Давайте начнем с того, что посмотрим на список номеров, которые уже доступны на нашей учетной записи:
› nexmo number:list
14155550123
В приведенном выше примере у меня есть номер. Если у вас нет номера, вы можете произвести поиск по номерам для аренды. Все, что вам необходимо для этого знать — это два символа кода страны в формате ISO 3166-1 alpha-2. На самом деле, это проще, чем кажется. Например, для Великобритании это GB, а для Соединенных Штатов — US (прим. пер.: а для России — RU). Давайте найдем номер для аренды в США:
› nexmo number:search US
14155550111
14155550222
14155550333
Если у вас нет номера, вы должны его купить, после чего вы сможете отправлять и получать SMS в тех странах, которые требуют реального исходящего номера.
› nexmo number:buy 14155550111 --confirm
Number purchased: 14155550111
Отправка SMS, наконец-то!
Теперь вам необходимо обновить код, что бы использовать только что купленный номер. Для этого нужно изменить значение
from
на env('NEXMO_NUMBER')
, как на примере ниже:Route::get('/sms/send/{to}', function(\Nexmo\Client $nexmo, $to){
$message = $nexmo->message()->send([
'to' => $to,
'from' => env('NEXMO_NUMBER'),
'text' => 'Sending SMS from Laravel. Woohoo!'
]);
Log::info('sent message: ' . $message['message-id']);
});
Затем запустите сервер:
› php artisan serve
Laravel development server started on http://localhost:8000/
И перейдите к
http://localhost:8000/sms/send/YOUR_NUMBER
, где YOUR_NUMBER
должен быть заменен на реальный номер, включая код страны, в формате E.164, т.е. в том же формате, который был показан во всех приведенных выше примерах.В файле
storage/logs/laravel.log
вы увидите запись лога, относящуюся к сообщению, которое только что было отправлено, включая уникальный идентификатор сообщения в конце записи, например:[2016-08-02 13:45:01] local.INFO: sent message: 03000000068F5D97
Приём входящего SMS
Для того, что бы наше приложение могло получать входящие SMS, нам необходимо выполнить несколько действий:
- Убедитесь, что приложение видно для Nexmo через локальный туннель
- Создайте маршрут для получения SMS
- Отключите CSRF для маршрута, получающего SMS
- Сообщите Nexmo, по какому маршруту вызывать вебхук при получении сообщения
Начнем с того, что дадим платформе Nexmo доступ к нашему приложению через локальный туннель. Если предположить, что вы используете ngrok и ваш веб-сервер Laravel прослушивает порт 8000, вы можете сделать это следующим образом:
› ngrok http 8000
ngrok by @inconshreveable (Ctrl+C to quit)
Tunnel Status online
Version 2.1.3
Region United States (us)
Web Interface http://127.0.0.1:4041
Forwarding http://814882e9.ngrok.io -> localhost:8000
Forwarding https://814882e9.ngrok.io -> localhost:8000
Connections ttl opn rt1 rt5 p50 p90
0 0 0.00 0.00 0.00 0.00
Выше вы можете увидеть, что поддомен на ngrok был успешно создан и теперь любые запросы к нему будут туннелироваться на наш локальный хост
localhost:8000
.Теперь необходимо создать маршрут для получения SMS в файле
routes.php
:Route::post('/sms/receive', function(\Nexmo\Client $nexmo){
});
По умолчанию Laravel не пропустит POST запросы на этот маршрут без CSRF токена. Так как запрос на этот маршрут будет сделан Nexmo, у которого нет токена, нам необходимо отключить CSRF для этого маршрута. Добавьте в
App/Http/Middleware/VerifyCsrfToken.php
следующее:protected $except = [
'/sms/receive'
];
И, наконец, давайте сообщим Nexmo, по какому маршруту сделать вызов вебхука, когда будет получено SMS. Мы можем сделать это с помощью Nexmo CLI. При выполнении следующей команды вы должны использовать номер телефона, который вы арендовали, а так же ваш поддомен ngrok:
› nexmo link:sms 14155550111 https://814882e9.ngrok.io/sms/receive
Number updated
При выполнении этой команды, служба Nexmo попытается вызвать ваш маршрут
/sms/receive
, и вы должны увидеть запрос в терминале ngrok:HTTP Requests
-------------
POST /sms/receive 200 OK
Клиентская библиотека Nexmo PHP предоставляет возможность с легкостью захватывать параметры HTTP, которые были отправлены от Nexmo приложению Laravel и создавать объект входящего сообщения
InboundMessage
, с которым мы можем работать. Обновите код маршрута /sms/receive
следующим образом:Route::post('/sms/receive', function(\Nexmo\Client $nexmo){
$message = \Nexmo\Message\InboundMessage::createFromGlobals();
Log::info('got text: ' . $message->getBody());
});
После этого отправьте SMS на арендованный номер и проверьте
storage/logs/laravel.log
, в логе должно находиться отправленное вами сообщение.[2016-08-02 13:45:01] local.INFO: sent message: 03000000068F5D97
[2016-08-02 14:20:50] local.INFO: sent message: 0300000006917797
[2016-08-02 14:21:17] local.INFO: got text: Sending one back.
Автоматический ответ на входящее SMS
И, наконец, давайте создадим автоответчик для входящего сообщения. Клиент Nexmo PHP обеспечивает хороший способ сделать это с помощью функции
InboundMessage->createReply
:Route::post('/sms/receive', function(\Nexmo\Client $nexmo){
$message = \Nexmo\Message\InboundMessage::createFromGlobals();
Log::info('got text: ' . $message->getBody());
$reply =$nexmo->message()->send($message->createReply('Laravel Auto-Reply FTW!'));
Log::info('sent reply: ' . $reply['message-id']);
});
Отправьте сообщение на арендованный номер и вы получите автоматический ответ. Это ведь почти магия!
Заключение
В этом уроке мы рассмотрели все, что вам нужно знать, чтобы реализовать отправку и получение SMS, и даже автоматический ответ на SMS, в приложении Laravel с использованием платформы облачных коммуникаций Nexmo.
Вы можете найти код этого урока на github.com/nexmo-community/laravel-sms.
Комментарии (18)
Shi
08.08.2016 07:57Теоретически, можно же разобрать текст входящего смс, и на его основе произвести некие действия?
mihmig
08.08.2016 09:23Все эти сервисы дороги и не надёжны. Сейчас проще купить пакет СМС (у всех операторов есть, цены примерно одинаковы) и отправлять через 3G-модем или смартфон на андроиде.
Пользуясь случаем хочу спросить — можно ли как-то поймать подтверждение доставки (статус доставлено в смартфоне) — это что — технологическое смс или что-то иное?
Сейчас конечно пользуемся сервисам web-шлюза, но веры им насчёт статуса особо нет.lopatoid
08.08.2016 09:43+1>и отправлять через 3G-модем или смартфон на андроиде.
На хабре была статья ребят, которые это делали, и их банили за рассылку.linakun
08.08.2016 11:55+1Подтверждаю. Мы рассылали через старый Sony Ericsson используя собственное ПО и тариф с большим кол-вом СМС. Через день СИМки банились оператором. В итоге перешли на один из сервисов рассылки.
MakarkinPRO
08.08.2016 09:47Операторы большой тройки API к смс + пакеты (с заключением договора) не предоставляют? Я знаю у Мегафона есть возможность отправлять. но хотелось что-то более официальное.
Для верификации нашел Twitter DIgits.palmich
08.08.2016 10:26операторы предоставляют, ценник не сильно гуманный.
например МТСMakarkinPRO
08.08.2016 10:38угу… Хотя есть почти или (возможно) вообще безлимитные тарифы для физ. лиц (ну они наверно и созданы, что из них не буду выжимать максимум).
Было бы круто, если у нас кто-то по 0,1 хотябы начал продавать СМС.
mihmig
08.08.2016 11:58У нас задача немного хитрее:
Сделать рассылку родителям учеников класса с номера председателя родительского комитета
Рассматриваем вариант отправки через ЛК (опсос МТС)
Плюсы: отправка идёт с номера председателя, в то время как симка в его телефоне (а не в GSM-шлюзе или 3G-свистке), он может сразу же принимать звонки от родителей, которые «ничего не поняли, что это за сообщение тут от вас пришло!»
Но у МТС используется CSRF-токен (сайт вообще номинант конкурса на самый тормознутость и антиюзабильность) — поэтому приходится городить костыли на phantomjs.
Есть ли ещё какие варианты?Rampages
09.08.2016 10:38Большинство шлюзов (например sms.ru или epochtasms.ru) предлагают прямые каналы от МТС, Билайн, Мегафон с буквенным идентификаторов (например SHKOLA.RU) вместо номера телефона. Вроде бы можно и номер телефона указать, если подтвердите что он вам принадлежит. Также для этого нужно Юр. лицо и соответственно если вы хотите отправлять от имени какого-то номера, то подозревая, что придется переоформить его на юр.лицо.
pavelklymenko
11.08.2016 12:24+1Спасибо автору за предоставленный материал. Для нашего проекта мы, для первой аналогичной интеграции, остановились на Twilio.
В процессе работы с Twilio мы столкнулись со следующими проблемами (доставка сообщений на локальные номера в Украине):
- не доставляются сообщения (решается вместе со службой технической поддержки в течение нескольких дней путем перемаршрутизации траффика через альтернативного провайдера, но раз в два/ три месяца проблема появляется снова — нужно мониторить)
- проблема с презентацией А-номера (в настоящий момент проблема так и не решена. Сообщения, отправленные с платформы Twilio, презентуются не корректно. Решение — ожидать, пока у Twilio появится локальный партнер в Украине, чего, судя по всему, в ближайшее время не предвидится)
Подскажите, если есть опыт работы, какого рода проблемы возникали с Nexmo? Интересно с точки зрения интеграции с их сервисом.
Заранее благодарю.
softshape
К сожалению, ценник от Nexmo (2 рубля за СМС) ставит крест на использовании их API.
Rampages
Да и что-то про подмену номера ничего не сказано или я пропустил…
Дорого и нет плюсов перед конкурентами, так и запишем.