Webhook是发生某种情况时发生的HTTP回调。 通过HTTP POST的简单事件通知系统,开发人员可以轻松访问付款活动的通知,例如付款状态更新或经常性费用。 在处理每个通知后,您可以在后端执行操作,例如:
- 通过电子邮件将购买确认发送给您的客户。
- 启用数字媒体下载。
- 发出退款。
- 跟踪哪些订阅处于活动状态。
要创建Webhook,请导航至PayPal 信息中心 ,然后点击我的应用和凭据 。 然后选择要在其中设置Webhooks的应用程序。
您可以查看有关您的应用程序的详细信息。 请注意,在右上角有两个按钮(沙盒,实时),在本教程中我将使用沙盒 ,但是在进入实时之前,您需要设置实时设置。 要为此应用程序配置Webhooks,请单击“ 添加Webhook”,如屏幕快照所示:
选择您想要得到通知的事件类型,然后输入将Webhooks发送到的URL(必须为HTTPS)。 为了处理Webhook调用,我将向HomeController添加一个名为'Webhook'的新操作方法:
public IActionResult Webhook()
{
// TODO: Handle Webhook call
}
因此,在这种情况下,Webhook网址为: https ://pedroalonso.localtunnel.me/home/webhook。 我将在下一部分中解释“ localtunnel”部分。
保存Webhook时,将看到以下确认屏幕:
现在已经设置了Webhook,您可以在“ Webhooks Simulator”下的左侧菜单中看到,这里您可以将“ test” webhook事件发送到URL以测试代码是否正常。 另外,在“ Webhooks事件”下,您可以查看PayPal为该应用程序发送的所有事件。 您可以验证自己是否正确处理了这些事件,如果要进行进一步的测试,请重新发送它们。
为了查看Webhooks的工作方式,我运行了我们在上一个教程中构建的项目,并创建了一个“授权付款并稍后捕获”,以便PayPal发送事件。 运行示例后,单击“ Webhooks事件”,可以看到事件已发送:
如您所见,如果要调试代码并查看如何正确实现处理程序,则在右侧有一个“ 重新发送”按钮。 另外,如果您单击该事件,则可以看到所有详细信息:
这是Webhook事件的完整JSON:
{
"id": "WH-9U51749144910293K-8LX80763BC1567402",
"create_time": "2016-01-19T17:50:30Z",
"resource_type": "sale",
"event_type": "PAYMENT.SALE.COMPLETED",
"summary": "Payment completed for $ 100.0 USD",
"resource": {
"amount": {
"total": "100.00",
"currency": "USD",
"details": {
"subtotal": "100.00",
"tax": "15.00",
"shipping": "10.00"
}
},
"id": "73G8209522783053E",
"parent_payment": "PAY-7MB27930V5981832YK2PHN7Q",
"update_time": "2016-01-19T17:49:05Z",
"create_time": "2016-01-19T17:49:05Z",
"payment_mode": "INSTANT_TRANSFER",
"state": "completed",
"links": [
{
"href": "https://api.sandbox.paypal.com/v1/payments/sale/73G8209522783053E",
"rel": "self",
"method": "GET"
},
{
"href": "https://api.sandbox.paypal.com/v1/payments/sale/73G8209522783053E/refund",
"rel": "refund",
"method": "POST"
},
{
"href": "https://api.sandbox.paypal.com/v1/payments/payment/PAY-7MB27930V5981832YK2PHN7Q",
"rel": "parent_payment",
"method": "GET"
}
],
"protection_eligibility_type": "ITEM_NOT_RECEIVED_ELIGIBLE,UNAUTHORIZED_PAYMENT_ELIGIBLE",
"transaction_fee": {
"value": "3.20",
"currency": "USD"
},
"protection_eligibility": "ELIGIBLE"
},
"status": "PENDING",
"transmissions": [
{
"webhook_url": "https://pedroalonso.localtunnel.me/home/webhook",
"response_headers": {
"Date": "Wed, 20 Jan 2016 12:53:51 GMT",
"Content-Length": "53",
"HTTP/1.1 502 Bad Gateway": "",
"SERVER_INFO": "",
"Connection": "keep-alive",
"Server": "nginx/1.7.8"
},
"transmission_id": "218dc9c0-bed5-11e5-927f-6b62a8a99ac4",
"status": "PENDING",
"timestamp": "2016-01-19T17:50:30Z"
}
],
"links": [
{
"href": "https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-9U51749144910293K-8LX80763BC1567402",
"rel": "self",
"method": "GET",
"encType": "application/json"
},
{
"href": "https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-9U51749144910293K-8LX80763BC1567402/resend",
"rel": "resend",
"method": "POST",
"encType": "application/json"
}
]
}
如您在图片中所见,事件详细信息以JSON编码,并将它们作为请求的正文发送到Webhook URL处理程序。 另外,我们需要在处理程序中使用几个重要的属性:
- id :这是webhook事件的ID,如果要检索特定的webhook事件,则需要将此参数发送到PayPal。
- event_type :用于了解我们正在接收的事件的类型,因为我们可能需要以不同的方式处理不同的事件类型。
- resource.parent_payment :这是与此事件相关的付款的ID。 我们可能将此ID存储在数据库中,并且可以向我们的客户发送电子邮件或运送客户购买的商品。
根据前面的解释,这是处理Webhook的动作控制器的代码:
public IActionResult Webhook()
{
// The APIContext object can contain an optional override for the trusted certificate.
var apiContext = PayPalConfiguration.GetAPIContext();
// Get the received request's headers
var requestheaders = HttpContext.Request.Headers;
// Get the received request's body
var requestBody = string.Empty;
using (var reader = new System.IO.StreamReader(HttpContext.Request.Body))
{
requestBody = reader.ReadToEnd();
}
dynamic jsonBody = JObject.Parse(requestBody);
string webhookId = jsonBody.id;
var ev = WebhookEvent.Get(apiContext, webhookId);
// We have all the information the SDK needs, so perform the validation.
// Note: at least on Sandbox environment this returns false.
// var isValid = WebhookEvent.ValidateReceivedEvent(apiContext, ToNameValueCollection(requestheaders), requestBody, webhookId);
switch (ev.event_type)
{
case "PAYMENT.CAPTURE.COMPLETED":
// Handle payment completed
break;
case "PAYMENT.CAPTURE.DENIED":
// Handle payment denied
break;
// Handle other webhooks
default:
break;
}
return new HttpStatusCodeResult(200);
}
前一个功能需要解释的几件事。 从第10-16行,我仅读取请求的主体并将JSON对象解析为动态C#对象。 在第18行(可选)上,我正在使用事件ID调用PayPal API以获取完整的事件详细信息。 这样做是为了确保我使用的是有效的PayPal对象。 在第24行上,我创建了一个开关来评估要处理的Webhooks的类型,并根据需要编写自定义代码。
您还可以看到,第22行已被注释掉。 显然,该方法可验证请求中的SSL证书有效且属于PayPal,但在沙盒模式下不起作用。 它可能可以在Live中运行,但是我不希望Live中的代码未经测试,尤其是在与支付网关打交道的情况下,因此我选择删除该代码并使用其他方法。 如果您使用PHP版本的PayPal SDK库,请记住,甚至没有“ ValidateReceivedEvent”函数。
测试Webhooks:安全隧道
如您先前所见,为了测试Webhooks,我们需要配置一个公共URL,PayPal可以使用该URL发送事件。 如果我们在本地工作,通常我们会使用“ localhost”进行开发,因此这将是一个小问题。 为了解决这个问题,我们需要配置一个到本地计算机的安全隧道。
Localtunnel是一小段软件,可在本地计算机和可公开访问的域之间创建安全隧道。 它对于测试Webhooks很有用,但您也可以使用它与开发计算机上运行的Web应用程序共享实时URL,以进行测试,反馈或其他任务。
您需要具有Node.js才能安装localtunnel。 然后只需打开控制台或终端,然后运行:
$ npm install -g localtunnel
要创建隧道,请运行:
$ lt --port 5000 --subdomain pedroalonso
这将网址“映射https://pedroalonso.localtunnel.me ”到“本地主机:5000”。 如果您在IIS Express上运行项目,则可能会使用其他端口,因此您需要在命令中反映出来。
设置localtunnel并运行我们的项目之后,我在Visual Studio中添加了一个断点以评估所获取的数据。 如您在此屏幕快照中所见,我已将JSON事件对象映射到C#动态对象。
使用事件ID从PayPal API检索事件,我们还获得事件详细信息,如下所示:
结论
Webhooks正在成为REST API通知应用程序事件的标准方法。 如您所见,它们非常易于操作,并且被Stripe,SendGrid,MailChimp等许多公司所使用。PayPal曾经具有即时付款通知,并且仍在使用中,但是他们建议在可能的情况下实施Webhooks 。
如果更多的消费者应用程序也提供Webhooks,我认为这将非常有趣。 根据事件在单独的应用程序中启动流程的功能非常有用,并且可以一窥实时Web的未来。
翻译自: https://code.tutsplus.com/articles/paypal-integration-part-3-paypal-webhooks--cms-22919