
Содержание статьи
Стефан Дорн

Веб-хуки могут использоваться внешней системой для оповещения вашей системы об определенном событии или обновлении. Пожалуй, наиболее известным типом является тот, в котором поставщик платежных услуг (PSP) информирует вашу систему об обновлении статуса платежей.
Часто они поступают в форме, где вы прослушиваете заранее определенный URL-адрес. Например, тем временем другая система отправляет запрос POST с определенной полезной нагрузкой на этот URL (например, идентификатор платежа). Как только поступает запрос, вы получаете идентификатор платежа, запрашиваете у PSP последний статус через их API, а затем обновляете свою базу данных.
Другие примеры можно найти в этом замечательном пояснении о Webhooks. https://sendgrid.com/blog/whats-webhook/.
Тестирование этих веб-хуков проходит довольно гладко, пока система общедоступна в Интернете. Это может быть ваша производственная среда или общедоступная промежуточная среда. Это становится сложнее, когда вы разрабатываете локально на своем ноутбуке или внутри виртуальной машины (VM, например Vagrant box). В таких случаях локальные URL-адреса не являются общедоступными сторонам, отправляющим веб-хук. Кроме того, трудно следить за посылаемыми запросами, что может усложнить разработку и отладку.
Что решит этот пример:
- Тестирование веб-хуков из локальной среды разработки, которая недоступна через Интернет. Сервис, который посылает данные на вебхук со своих серверов, не может получить к нему доступ.
- Отслеживайте запросы и данные, а также ответ, который создает программа. Это облегчит отладку, а значит, сократит цикл разработки.
Предпосылки:
- Дополнительно: если вы разрабатываете с помощью виртуальной машины (VM), убедитесь, что она запущена, и убедитесь, что следующие шаги выполняются в VM.
- Для этого учебника мы предполагаем, что у вас есть vhost, определенный в
webhook.example.vagrant
. Я использовал Vagrant VM для этого учебника, но вы можете свободно выбирать имя своего виртуального хоста. - установить
ngrok
следуя инструкциям по установке. Внутри виртуальной машины я считаю ее версию Node тоже полезной: но смело используйте другие методы.
Я предполагаю, что в вашей среде не запущен SSL, но если есть, не стесняйтесь заменить порт 80 на порт 433 и http://
с https://
в приведенных ниже примерах.
Сделайте вебхук доступным для проверки
Предположим следующий пример кода. Я буду использовать PHP, но читаю его как псевдокод, поскольку я пропустил некоторые важные части (например, ключи API, проверку ввода и т.д.)
Первый файл: payment.php. Этот файл создает платежный объект, а затем регистрирует его в PSP. Затем он получает URL, который клиент должен посетить, чтобы оплатить, и перенаправляет пользователя к клиенту там.
Обратите внимание, что webhook.example.vagrant
В этом примере это локальный vhost, который мы определили для наших настроек разработки. Он недоступен из внешнего мира.
<?php
/*
* This file creates a payment and tells the PSP what webhook URL to use for updates
* After creating the payment, we get a URL to send the customer to in order to pay at the PSP
*/
$payment = [
'order_id' => 123,
'amount' => 25.00,
'description' => 'Test payment',
'redirect_url' => '
'webhook_url' => '
];
$payment = $paymentProvider->createPayment($payment);
header("Location: " . $payment->getPaymentUrl());
Второй файл: webhook.php. Этот файл ожидает вызов PSP для получения сообщения об обновлении.
<?php
/*
* This file gets called by the PSP and in the $_POST they submit an 'id'
* We can use this ID to get the latest status from the PSP and update our internal systems afterward
*/
$paymentId = $_POST['id'];
$paymentInfo = $paymentProvider->getPayment($paymentId);
$status = $paymentInfo->getStatus();
// Perform actions in here to update your system
if ($status === 'paid') {
..
}
elseif ($status === 'cancelled') {
..
}
Наш URL-адрес webhook недоступн в Интернете (помните: webhook.example.vagrant
). Таким образом, файл webhook.php никогда не будет вызываться PSP. Ваша система никогда не узнает статус платежа. Это в конечном итоге приводит к тому, что заказы никогда не посылаются клиентам.
К счастью, ngrok может решать эту проблему. ngrok описывает себя как:
ngrok открывает локальные серверы по NAT и брандмауэрам для общедоступного Интернета через безопасные туннели.
Давайте начнем базовый тоннель для нашего проекта. В вашей среде (или в вашей системе или на виртуальной машине) выполните следующую команду:
ngrok http -host-header=rewrite webhook.example.vagrant:80
Дополнительные параметры конфигурации см. в их документации: https://ngrok.com/docs.
Появится следующий экран:

Что мы только начали? В принципе, мы инструктировали ngrok
чтобы начать туннель до на порт 80. Этот же URL теперь можно получить через
или
https://39741ffc.ngrok.io
Они доступны в Интернете для всех, кто знает этот URL.
Примечание что вы получаете как HTTP, так и HTTPS, доступные из коробки. В документации приведены примеры того, как ограничить это только HTTPS: https://ngrok.com/docs#bind-tls.
Итак, как нам сделать так, чтобы наш вебхук теперь работал? обновление payment.php к следующему коду:
<?php
/*
* This file creates a payment and tells the PSP what webhook URL to use for updates
* After creating the payment, we get a URL to send the customer to in order to pay at the PSP
*/
$payment = [
'order_id' => 123,
'amount' => 25.00,
'description' => 'Test payment',
'redirect_url' => '
'webhook_url' => '
];
$payment = $paymentProvider->createPayment($payment);
header("Location: " . $payment->getPaymentUrl());
Теперь мы сказали PSP вызвать URL-адрес туннеля через HTTPS. ngrok обеспечит вызов вашего внутреннего URL-адреса с неизмененной полезной нагрузкой, как только PSP вызовет вебхук через туннель.
Как отслеживать звонки на вебхук?
Снимок экрана, который вы видели выше, дает обзор вызовов, совершаемых к хосту туннеля. Эти данные достаточно ограничены. к счастью ngrok
предлагает очень хорошую информационную панель, которая позволяет проверять все вызовы:

Я не буду вдаваться в это слишком глубоко, потому что это понятно, как только вы его запустите. Поэтому я объясню, как получить доступ к нему на окне Vagrant, поскольку это не работает из коробки.
Информационная панель позволит вам видеть все звонки, их коды состояния, заголовки и передаваемые данные. Вы также увидите ответ, созданный вашей заявкой.
Еще одна отличная функция информационной панели состоит в том, что она позволяет воспроизвести определенный вызов. Скажем, в вашем коде веб-хука произошла роковая ошибка, было бы утомительно начинать новый платеж и ждать, пока вызовется веб-хук. Воспроизведение предварительного вызова значительно ускоряет процесс разработки.
Информационная панель доступна по адресу http://localhost:4040.
Информационная панель в виртуальной машине
Чтобы это работало в виртуальной машине, необходимо выполнить несколько дополнительных шагов:
Сначала убедитесь, что к виртуальной машине можно получить доступ через порт 4040. Затем создайте файл внутри виртуальной машины, содержащей эту конфигурацию:
web_addr: 0.0.0.0:4040
Теперь убейте ngrok
все еще работающий процесс и запустите его с помощью этой несколько скорректированной команды:
ngrok http -config=/path/to/config/ngrok.conf -host-header=rewrite webhook.example.vagrant:80
Вы получите экран, похожий на предыдущий снимок, хотя идентификаторы изменились. Предыдущий URL-адрес больше не работает, но вы получили новый URL-адрес. Кроме того, Web Interface
URL изменен:

Теперь направьте свой браузер на :4040
доступ к информационной панели. Также позвоните в https://e65642b5.ngrok.io/webhook.php
.Вероятно, это приведет к ошибке в вашем браузере, но на информационной панели должен отображаться сделанный запрос.
Приведенные выше примеры представляют собой псевдокод. Причина в том, что каждая внешняя система использует веб-хуки по-разному. Я попытался привести пример, основанный на вымышленной реализации PSP, поскольку, вероятно, многим разработчикам приходится приходится иметь дело с платежами.
Имейте в виду, что URL-адрес вашего вебхука также может быть использован другими с плохими намерениями. Убедитесь, что проверяете любые передаваемые ему входящие данные.
Желательно также добавить маркер к URL-адресу, который является уникальным для каждого платежа. Этот маркер должен быть известен только вашей системе и системе, отправляющей вебхук.
Удачи в тестировании и настройке веб-хуков!
Примечание: Я не тестировал это руководство на Docker. Однако этот контейнер Docker выглядит как отличная точка и содержит четкие инструкции. https://github.com/wernight/docker-ngrok.
Стефан Дорн
https://github.com/stefandoorn
https://twitter.com/stefan_doorn
https://www.linkedin.com/in/stefandoorn