使用 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"
    }
  ]
}