Webhooks可以被外部系统用来通知您的系统事件或更新。可能最著名的webhook类型是支付服务提供商(PSP),它通知您的系统支付状态更新。它们通常以预定义的URL形式出现,例如http://example.com/webhooks/payment-update。同时,另一个系统向该URL发送一个带有特定负载(例如支付ID)的POST请求。收到请求后,您将获得支付ID,您可以使用该ID通过PSP的API向他们询问最新状态,然后更新您的数据库。其他示例可以在这个对webhook的出色解释中找到:https://sendgrid.com/blog/whats-webhook/。只要系统可通过互联网公开访问(这可能是您的生产环境或可公开访问的暂存环境),测试这些webhook应该会相当顺利。当您在笔记本电脑或虚拟机(例如Vagrant虚拟机)中进行本地开发时,这会变得很困难。在这些情况下,发送webhook的一方无法公开访问您的本地URL。此外,可能很难监视正在发送的请求,这会使开发和调试变得困难。因此,此示例将解决:从无法通过Internet访问的本地开发环境测试webhook。将数据从服务器发送到webhook的服务无法访问它。监控发送的请求和数据,以及应用程序生成的响应。这使得调试更容易,从而缩短了开发周期。先决条件:可选:如果您使用虚拟机(VM)进行开发,请确保它正在运行,并确保在VM中完成后续步骤。对于本教程,我们假设您定义了一个虚拟主机:webhook.example.vagrant。我在本教程中使用了VagrantVM,但您可以自由选择虚拟主机。按照此安装说明安装ngrok。在VM中,我发现它的Node版本也很有用:https://www.npmjs.com/package/ngrok,但您可以随意使用其他方法。我假设您没有在您的环境中运行SSL,但如果是,请在下面的示例中将端口80替换为端口433,将http://替换为https://。为了使webhook可测试,我们假设以下示例代码。我将使用PHP,但请将其视为伪代码,因为我没有编写一些关键部分(例如API密钥、输入验证等)。第一个文件:payment.php。该文件创建一个$payment对象,将其注册到PSP。然后它会获取客户需要访问的URL以便付款并将用户重定向到那里。请注意,此示例中的webhook.example.vagrant是我们为开发设置定义的本地虚拟主机。它不能从外部世界访问。123,'amount'=>25.00,'description'=>'测试支付','redirect_url'=>'http://webhook.example.vagrant/redirect.php','webhook_url'=>'http://webhook.example.vagrant/webhook.php',];$payment=$paymentProvider->createPayment($payment);header("Location:".$payment->getPaymentUrl());第二个文件:webhook.php。此文件等待来自PSP的调用以通知更新。getPayment($paymentId);$status=$paymentInfo->getStatus();//在此处执行操作以更新您的系统if($status==='paid'){..}elseif($status==='cancelled'){..}我们的webhookURL无法通过互联网访问(记住:webhook.example.vagrant)。因此,PSP将永远无法调用webhook.php文件,您的系统将永远不知道付款状态,最终导致订单永远不会发货给客户。幸运的是,ngrok可以解决这个问题。ngrok将自己描述为:ngrok通过安全隧道将NAT和防火墙后面的本地服务器暴露给公共互联网。让我们为我们的项目开始一个基本的隧道。在您的环境中(在您的系统或VM上)运行以下命令:ngrokhttp-host-header=rewritewebhook.example.vagrant:80阅读其文档以了解更多配置选项:https://ngrok.com/docs。将出现这样的屏幕:ngrokoutputWhatdidwejustdo?基本上,我们指示ngrok在端口80上建立到http://webhook.example.vagrant的隧道。同样的URL也可以通过http://39741ffc.ngrok.io或https://39741ffc.ngrok.io访问,任何知道URL的人都可以通过Internet公开访问。请注意,您可以获得HTTP和HTTPS服务。此文档提供了如何将其限制为HTTPS的示例:https://ngrok.com/docs#bind-tls。那么,我们现在如何让我们的webhooks工作呢?将payment.php更新为以下代码:123,'amount'=>25.00,'description'=>'Testpayment','redirect_url'=>'http://webhook.example.vagrant/redirect.php','webhook_url'=>'https://39741ffc.ngrok.io/webhook.php',];$payment=$paymentProvider->createPayment($payment);header("位置:".$payment->getPaymentUrl());现在我们告诉PSP通过HTTPS调用这个隧道URL。每当PSP通过隧道调用webhook时,ngrok将确保使用未修改的有效负载调用内部URL。如何监控对webhook的调用?您在上面看到的屏幕截图概述了对隧道主机的调用,这是相当有限的数据。幸运的是,ngrok提供了一个非常好的仪表板,允许您检查所有调用:我不会深入研究它,因为它不言自明,您只需运行它。所以我将解释如何在VagrantVM上访问它,因为它不是开箱即用的。仪表板将允许您查看所有呼叫、它们的状态代码、标头和发送的数据。您将看到应用程序生成的响应。仪表板的另一个优点是它允许您重播某个呼叫。假设你的webhook代码遇到致命错误,开始新的支付并等待webhook被调用将会很乏味。重放上次调用可以使您的开发过程更快。默认情况下,可以通过http://localhost:4040访问仪表板。虚拟机中的仪表板为了让它在VM中工作,您必须执行一些额外的步骤:首先,确保VM可以在端口4040上访问。然后,在VM中创建一个包含此配置的文件:web_addr:0.0.0.0:4040现在,终止仍在运行的ngrok进程,并使用稍微调整的命令启动它:ngrokhttp-config=/path/to/config/ngrok.conf-host-header=rewritewebhook.example.vagrant:80尽管ID已更改,但您会看到与之前的屏幕截图类似的屏幕。以前的URL不再有效,但您有一个新的URL。此外,Web界面URL已更改:现在将浏览器指向http://webhook.example.vagrant:4040以访问仪表板。另外,调用https://e65642b5.ngrok.io/webhook.php。这可能会导致您的浏览器出错,但仪表板应该会显示有请求。结语上面的例子是伪代码。原因是每个外部系统使用webhook的方式不同。我试图给出一个基于虚构的PSP实现的示例,因为可能许多开发人员肯定会在某个时候处理付款。请注意,您的webhookURL也可能被其他人恶意使用。确保验证发送给它的任何输入。更好的是,可以将令牌添加到URL,这对于每次支付都是唯一的。只有您的系统和发送webhook的系统会知道此令牌。祝你测试和调试你的webhooks好运!注意:我还没有在Docker上测试过本教程。但是,这个Docker容器看起来是一个很好的起点,并且包含清晰的说明:https://github.com/wernight/docker-ngrok。
