Вовлечение пользователей во взаимодействие с вашим блогом очень важно. И это легко сделать с помощью Twilio. В этой статье вы узнаете, как написать плагин для WordPress, который будет отправлять вашим пользователям текстовое сообщение, когда кто-то отвечает на их комментарий. Если вы хотите пойти еще дальше, вы можете позволить пользователю комментировать запись с помощью текстового сообщения, создав веб-сервис REST на Java.
Вам понадобится самостоятельный (self-hosted) сайт на WordPress, чтобы вы могли создать и установить плагин. Вам также нужно будет загрузить Twilio SDK и настроить номер Twilio.
Мы создадим плагин целиком вне WordPress, а затем установим и активируем его. Сначала создайте каталог в вашей файловой системе разработки с именем `sms-twilio-comment-notifier`
и в этом каталоге создайте файл `sms-twilio-comment-notifier.php`
. Это ваш главный файл плагина. Вам нужно добавить метаданные, чтобы определить этот класс как файл плагина, а после этого будет идти сам код.
Далее укажите плагину, где найти ранее загруженный Twilio SDK. Распакуйте SDK в папку и добавьте следующее в `sms-twilio-comment-notifier.php`
:
Теперь мы можем получить доступ к Twilio API. Для аутентификации в Twilio нам нужно знать несколько ключевых элементов. Мы будем хранить их в пользовательской таблице базы данных. При активации плагина он проверит, есть ли таблица, и если нет, то создаст ее. Следующий код будет выполнен при активации плагина для создания таблицы, в которой будут храниться Account SID, Auth Token и номер Twilio, настроенные вами ранее, снова в `sms-twilio-comment-notifier.php`
:
Нам понадобится способ очистки таблицы при ее удалении, так что давайте позаботимся об этом сейчас.
Создайте файл с именем `uninstall.php`
и добавьте следующее:
Этот класс будет вызван при удалении плагина, он удалит таблицу из базы данных и удалит опцию версии базы данных из WordPress.
Как данные попадут в нашу новую таблицу? Нам нужно создать для этого страницу администратора. Добавьте следующее в `sms-twilio-comment-notifier.php`
:
Мы добавляем страницу меню, которую смогут видеть только пользователи с ролью `edit_pages`
. Теперь давайте поместим что-нибудь на страницу. Сделайте это просто и разрешите только одну строку таблицы, чтобы у нас была очень базовая форма для сбора трех элементов данных. Зарегистрируйте действие для перехвата отправки формы и получите содержимое из таблицы, чтобы мы могли предварительно заполнить поля текущими значениями из таблицы. Установите поле `nonce`
для проверки отправки формы. Добавьте следующее в `sms-twilio-comment-notifier.php`
:
Вот готовая страница:
После того как пользователь сохранит значения своего аккаунта Twilio, сохраните их в таблице. Сначала мы проверим `nonce`
, чтобы убедиться, что запрос не подделан. Нам нужно очистить входные данные для безопасности, затем мы можем сохранить их в нашей таблице и обновить страницу. Добавьте форму ниже в `sms-twilio-comment-notifier.php`
:
Теперь, когда у нас настроена возможность общаться с Twilio, нам нужно иметь возможность хранить номер мобильного телефона пользователя. Добавьте поле на страницу профиля пользователя, чтобы пользователь мог ввести свой номер и сохранить поля в метаданных пользователя. Все еще в `sms-twilio-comment-notifier.php`
, добавьте:
Вот что теперь будет на вашей странице профиля:
Мы почти у цели! Мы можем аутентифицироваться в Twilio, и у нас есть номер, на который мы можем отправить сообщение. Нам нужно добавить несколько хуков в функции комментариев. Когда комментарий публикуется или обновляется, сначала проверьте, является ли этот комментарий ответом на другой комментарий. Если это так, убедитесь, что пользователь не отвечает самому себе. Если он отвечает кому-то другому, отправьте пользователю этого родительского комментария уведомление. Добавьте следующее в `sms-twilio-comment-notifier.php`
:
Время для самой интересной части — использования Twilio для отправки сообщения. Сначала получите поля аутентификации Twilio из созданной нами таблицы, затем получите номер мобильного телефона из родительского комментария, чтобы отправить этому пользователю сообщение. Мы отправим сообщение, включающее ссылку на комментарий, чтобы сделать его полезным. Вы можете остановиться на этом и получить удобный маленький плагин для уведомлений.
Если вы хотите пойти еще дальше, мы позволим пользователю ответить на это текстовое сообщение и опубликовать комментарий в блоге от имени этого пользователя. В `sms-twilio-comment-notifier.php`
добавьте:
Если вы не хотите позволять пользователю отвечать на текст для публикации комментария, просто измените текст сообщения.
Если вы хотите позволить пользователю отправлять комментарий к записи с помощью SMS, все становится немного сложнее. В WordPress наконец-то появился REST API, с которым вы можете взаимодействовать с помощью REST веб-сервисов, включая создание записей или комментариев. Однако, чтобы опубликовать комментарий от имени пользователя, вы должны *аутентифицироваться* как этот пользователь. Чтобы сделать *это*, вам нужно настроить OAuth или что-то подобное, чтобы позволить пользователю использовать токен для аутентификации в WordPress. Что усложняет ситуацию, так это то, что WordPress не имеет встроенной поддержки OAuth. Есть плагины, которые помогают, но весь смысл ответа через текстовое сообщение заключается в том, чтобы войти и выйти, не преодолевая слишком много препятствий. В противном случае вы могли бы просто использовать приложение WordPress или войти в систему через браузер. Чтобы предложить быстрый способ комментирования записи в блоге, мы собираемся настроить промежуточный («tweener») сервис, который будет публиковать комментарии анонимно в WordPress от имени вашего пользователя. Поскольку пользователь не входит в систему и не публикует комментарий сам, мы добавим отображаемое имя пользователя в конец комментария, чтобы было понятно, кто написал комментарий.
Для этого включите анонимное комментирование. Добавьте этот фильтр в `sms-twilio-comment-notifier.php`
:
Нажмите «Загрузить плагин».
Загрузите ваш заархивированный файл плагина и активируйте его.
Все готово!
Вот как может выглядеть ваше текстовое сообщение, если кто-то ответит на ваш комментарий:
А как насчет функции ответа?
Для следующей части вам нужно будет установить Java веб-сервис на сервере приложений. Вы можете установить его локально и использовать ngrok для тестирования, пока не будете готовы опубликовать его для всеобщего доступа.
Если у вас еще не настроена среда разработки Java, загрузите Eclipse и Tomcat и распакуйте их.
Создайте новый Dynamic Web Project в Eclipse и назовите его `SMSNotify`
. Создайте структуру пакета — я использую `com.company.sms.notify`
и ваш класс `SMSNotify.java`
в пакете. Чтобы ускорить процесс, создайте подпакет `dao`
и класс `SMSNotifyDAO.java`
в этом пакете. Мы доберемся до них чуть позже.
Мы собираемся использовать RESTEasy для предоставления наших REST веб-сервисов, но вы можете использовать ваш любимый фреймворк.
Нам нужен вебхук в Twilio, который будет вызывать ваш веб-сервис каждый раз, когда на ваш номер Twilio отправляется сообщение. Веб-сервис попытается извлечь идентификатор записи (post id) для ответа, сделает вызов к базе данных WordPress для получения метаданных пользователя, а затем отправит POST-запрос к WordPress REST API для фактической публикации комментария.
В вашем `web.xml`
вам нужно настроить RESTEasy, добавив следующее прямо перед закрывающим тегом.
Это позволит любому классу быть просканированным RESTEasy для предоставления REST-эндпоинта, который принимает только POST-запросы.
Сначала мы настроим веб-сервис, на который вебхук Twilio будет отправлять POST-запросы.
Настройте ваш `@Path`
в верхней части класса `SMSNotify.java`
и аннотируйте функцию для приема `POST`
.
Это просто отвечает сообщением 200 OK.
Установите ваш веб-сервис на tomcat и используйте ngrok, чтобы сделать вашу локальную среду публично доступной.
Настройте ваш вебхук в Twilio:
Теперь всякий раз, когда кто-то отправляет текстовое сообщение на ваш номер Twilio, оно будет отправляться в этот веб-сервис.
Twilio отправляет сообщения в определенном формате, поэтому нам нужно проанализировать отправленную информацию, чтобы понять сообщение. Мы установим несколько констант, которые сможем использовать для разбора строки. Мы хотим проверить входящее сообщение, поэтому нам также нужно будет получить наши учетные данные Twilio из нашей таблицы WordPress. Подготовьтесь к этому, создав константы для этих вызовов:
Это формат сообщения, которое мы получаем от Twilio:
Ключи, которые нам нужны — это AccountSid, Body, To и From. Мы собираемся убедиться, что `AccountSid`
и `To`
совпадают с нашим Twilio SID и номером Twilio, сохраненными ранее в WordPress. Итак, нам нужен класс DAO, чтобы получить их.
В вашем классе DAO создайте final-строки для хранения ваших SQL-запросов. Мы используем подготовленные выражения (prepared statements) и неизменяемые строки для предотвращения атак SQL-инъекций.
Обратите внимание, что мы вызываем ту же таблицу, которую наш плагин создал ранее, и извлекаем значения оттуда. Мы также подключаемся к таблицам users и usermeta в WordPress, чтобы сопоставить номер мобильного телефона, который вебхук Twilio отправляет нам, с именем пользователя, который отправил текст. Когда мы публикуем сообщение, мы можем добавить имя пользователя, чтобы публикация не была по-настоящему анонимной.
В зависимости от вашего веб-хостинга вам может понадобиться добавить IP-адрес вашего сервера Tomcat, чтобы разрешить внешнему серверу подключаться к размещенному серверу MySQL.
Нам нужно настроить соединение с базой данных. Вы можете настроить источник данных (datasource) в Tomcat, но поскольку это просто пример кода, подключитесь вручную и не беспокойтесь о пуле соединений, который вы бы хотели использовать в рабочей среде.
Теперь, когда у нас есть соединение с базой данных, мы можем вызвать его, чтобы получить наши учетные данные.
Обратите внимание на вызов close в методе finally. Нам нужно убедиться, что мы закрываем все наши соединения.
Пока мы здесь, мы можем написать наш метод для получения имени пользователя по его номеру мобильного телефона.
Давайте подведем итоги. У нас есть конечная точка веб-сервиса и класс DAO, который может читать все данные, необходимые нам в веб-сервисе. Пора погрузиться и завершить работу над веб-сервисом.
Мы уже создали константы, необходимые для нашего анализа, так что мы можем заполнить метод.
Получите ваши учетные данные из метода DAO, который мы только что сделали. Если мы не сможем их найти, нам нужно выдать ошибку, так как мы не сможем проверить входящее сообщение.
Если мы добрались до этого момента, учетные данные были найдены. Убедитесь, что Account SID, отправленный в веб-сервис, совпадает с вашим Twilio Account SID. Мы проанализируем строку, отправленную в веб-сервис, и найдем первое вхождение `AccountSid=`
. Извлеките все между этим местом в строке и первым вхождением после этого символа `&`
. Если он не совпадает с нашим Account SID, прервите выполнение с сообщением Unauthorized.
Сделайте в основном то же самое с номером Twilio. Когда сообщение отправляется нам, текст кодируется в HTML. Мы могли бы использовать сторонние утилиты для декодирования сообщения, но так же легко заменить текст, как мы это делаем здесь, изменив `%2B`
на ` +`
.
Теперь, когда сообщение проверено, нам нужно получить номер мобильного телефона пользователя, который его отправил. И снова мы заменим закодированные %2B на +.
Сохраните это, мы вернемся к этому через минуту.
Получите текстовое сообщение, отправленное пользователем, и извлеките из него идентификатор записи (post id). Мы сказали пользователю вводить `
. `::`
были закодированы при отправке нам, поэтому нам нужно вернуть двоеточия обратно, чтобы проанализировать наше сообщение:
У нас есть почти все необходимое для публикации комментария, поэтому добавьте это в конец вашего класса:
Теперь давайте создадим этот метод, чтобы вызов сработал. Возьмите номер мобильного телефона и вызовите метод в нашем DAO, который возвращает имя пользователя, и сформируйте наше новое сообщение. В нашем плагине мы сказали пользователю отвечать в формате `
. Если он сделал это, мы можем получить идентификатор записи из сообщения. Мы извлекаем число и обрезаем строку, чтобы `
фактически не появлялся в комментарии.
Сообщение приходит к нам с плюсами вместо пробелов, поэтому сделайте быструю замену всех, чтобы изменить их на пробелы, чтобы они не отображались в WordPress как `This+is+my+reply`
. Конечно, это не пуленепробиваемый подход, так как некоторые пользователи могут на самом деле поставить плюс в своем тексте, но для сейчас это сработает.
Последним шагом является вызов WordPress REST API для публикации сообщения. Нам нужен URL для его отправки. Вы можете хранить это в локальной таблице где-нибудь, но чтобы немного ускорить процесс, я жестко кодирую его в DAO, так как он вряд ли изменится в ближайшее время:
Давайте сделаем вызов к API. У нас есть идентификатор записи и текст комментария, которые мы добавляем в качестве параметров запроса к нашему URL WordPress. Используйте RESTEasy для отправки сообщения. Если есть ошибка, мы вернем false, чтобы наш веб-сервис знал, что нужно вернуть ошибку пользователю, в противном случае мы вернем успех.
Наконец, верните ответ в зависимости от того, сработал ли postComment или нет:
Разверните ваш готовый веб-сервис на Tomcat (см. полный пример на GitHub) и протестируйте его!
Теперь вы включили двустороннюю связь между вашим сайтом на WordPress и вашими конечными пользователями. Пользователь может ввести номер мобильного телефона в своем профиле, что позволит ему получать текстовое сообщение, когда кто-то отвечает на его комментарий. Если он хочет сразу же снова прокомментировать запись, он может отправить ответное текстовое сообщение. Ваш веб-сервис получит этот текст и оставит комментарий к той же записи, отметив, что он был отправлен от имени определенного пользователя.
Используйте это как отправную точку для расширения взаимодействия пользователей с вашим сайтом на WordPress!