使用 ngrok 和 Express(节点)测试 Sandbox Webhooks

在这个例子中,我们将讨论在沙盒中测试 webhook 通知,使用 ngrok 为我们的 Node HTTP 侦听器提供隧道,在 localhost 上运行到 Internet。对于此示例,我们将使用 Node 为付款事件设置通知 webhook(例如正在进行付款),然后设置服务器以侦听来自 webhook 事件的传入 HTTP POST 消息。

我们将在此处执行以下几个步骤来实现此目的:

  1. 设置一个简单的服务器来监听来自 webhooks 的传入 POST 流量,这将是来自 PayPal 的通知,并开始侦听 localhost。
  2. 然后使用 ngrok 提供从 localhost 到 Internet 的隧道,以便 PayPal 可以发布通知。
  3. 最后,将我们的应用程序(基于提供的凭据)订阅到我们要跟踪的 webhook 事件,从步骤 2 提供公共 ngrok URI。

创建 Webhooks 监听器

我们需要做的第一件事就是创建监听器。我们开始使用监听器的原因是因为我们需要 ngrok 实时 URL 在创建或更新时提供给 webhook。

var bodyParser = require('body-parser'),
    http = require('http'),
    app = require('express')();

app.use(bodyParser.json());

app.post('/', function(req, res){
    console.log(JSON.stringify(req.body));
});

//create server
http.createServer(app).listen(3001, function () {
   console.log('Server started: Listening on port 3001');
});

我们的听众是使用 Express 的简单路线。我们监听任何传入的 POST 流量,然后将 POST 主体吐出到控制台。我们可以使用它来做任何我们喜欢的听众。

当我们在最后创建 HTTP 服务器时,我们将其设置为侦听 localhost 端口 3001.现在运行该脚本以开始侦听流量。

使用 ngrok 将监听器暴露给 Internet

在 localhost:3001 上设置监听器,我们的下一个工作是将该脚本暴露给互联网,以便可以将流量发送给它,这是 ngrok 的工作。

从终端窗口运行以下命令:

ngrok http 3001

这将启动在端口 3001 上为 localhost 提供实时隧道的过程,并在运行后提供以下信息:

http://i.stack.imgur.com/UVwad.jpg

我们可以看到,我们可以用来将 PayPal webhook 指向我们在 localhost 上运行的监听器的实时地址是 http(s)://055b3480.ngrok.io。这就是我们设置监听器所需要知道的全部内容。

订阅通知

我们的最后一步是为我们的应用程序创建 webhooks,当我们的应用程序上的付款,退款等发生某些事件时,它会创建通知。我们只需创建一次这些 webhook 就可以将它们绑定到应用程序,因此每次要使用它们时都不需要运行它们。

首先,我们通过添加 PayPal Node SDK 的要求,创建应用程序的客户端 ID /机密,然后为沙箱配置环境来设置 PayPal 环境。

var paypal = require('paypal-rest-sdk');

var clientId = 'YOUR APPLICATION CLIENT ID';
var secret = 'YOUR APPLICATION SECRET';

paypal.configure({
  'mode': 'sandbox', //sandbox or live
  'client_id': clientId,
  'client_secret': secret
});

接下来,我们为 webhooks 设置 JSON 结构。webhooks 包含两条信息,即应该发送所有 webhook 事件的 url,以及我们想要订阅的 event_types

对于此示例,url 设置为我们的 ngrok 实时 URL,我们正在侦听的事件是完成或拒绝付款的情况。

有关潜在事件的完整列表,请参阅 https://developer.paypal.com/docs/integration/direct/rest-webhooks-overview/#event-type-support

最后,我们将 webhooks 对象传递给调用以创建 webhooks,notification.webhook.create。如果成功,PayPal 将向我们指定的端点发送通知,该端点在 localhost 上运行。

var webhooks = {
    "url": "https://436e4d13.ngrok.io",
    "event_types": [{
        "name": "PAYMENT.SALE.COMPLETED"
    },{
        "name": "PAYMENT.SALE.DENIED"
    }
]};

paypal.notification.webhook.create(webhooks, function (err, webhook) {
    if (err) {
        console.log(err.response);
        throw error;
    } else {
        console.log("Create webhook Response");
        console.log(webhook);
    }
});

一旦我们使用这些应用程序凭据发出付款,有关付款状态的信息将发送到我们设置的端点。

PayPal 作为通知发送的 POST 正文的示例可能如下所示,这是在成功支付 PayPal 后发送的:

{
  "id": "WH-9FE9644311463722U-6TR22899JY792883B",
  "create_time": "2016-04-20T16:51:12Z",
  "resource_type": "sale",
  "event_type": "PAYMENT.SALE.COMPLETED",
  "summary": "Payment completed for $ 7.47 USD",
  "resource": {
    "id": "18169707V5310210W",
    "state": "completed",
    "amount": {
      "total": "7.47",
      "currency": "USD",
      "details": {
        "subtotal": "7.47"
      }
    },
    "payment_mode": "INSTANT_TRANSFER",
    "protection_eligibility": "ELIGIBLE",
    "protection_eligibility_type": "ITEM_NOT_RECEIVED_ELIGIBLE,UNAUTHORIZED_PAYMENT_ELIGIBLE",
    "transaction_fee": {
      "value": "0.52",
      "currency": "USD"
    },
    "invoice_number": "",
    "custom": "",
    "parent_payment": "PAY-809936371M327284GK4L3FHA",
    "create_time": "2016-04-20T16:47:36Z",
    "update_time": "2016-04-20T16:50:07Z",
    "links": [
      {
        "href": "https:\/\/api.sandbox.paypal.com\/v1\/payments\/sale\/18169707V5310210W",
        "rel": "self",
        "method": "GET"
      },
      {
        "href": "https:\/\/api.sandbox.paypal.com\/v1\/payments\/sale\/18169707V5310210W\/refund",
        "rel": "refund",
        "method": "POST"
      },
      {
        "href": "https:\/\/api.sandbox.paypal.com\/v1\/payments\/payment\/PAY-809936371M327284GK4L3FHA",
        "rel": "parent_payment",
        "method": "GET"
      }
    ]
  },
  "links": [
    {
      "href": "https:\/\/api.sandbox.paypal.com\/v1\/notifications\/webhooks-events\/WH-9FE9644311463722U-6TR22899JY792883B",
      "rel": "self",
      "method": "GET"
    },
    {
      "href": "https:\/\/api.sandbox.paypal.com\/v1\/notifications\/webhooks-events\/WH-9FE9644311463722U-6TR22899JY792883B\/resend",
      "rel": "resend",
      "method": "POST"
    }
  ]
}