Create a webhook for payment event notifications

PayPal uses webhooks for notification. To create a webhook for payment event notifications, your app must:

  1. Configure a webhook listener.

    Set up a server to listen for incoming HTTP POST notification messages when events occur. Then, use ngrok to provide a tunnel to test webhook notifications in the sandbox. The tunnel runs between a Node HTTP listener that runs on localhost and the Internet.

  2. Subscribe your webhook listener to events.

To get started, use the PayPal Node SDK to configure a webhook listener. This example creates a webhook for payment events, such as a payment in progress. You can also use the other PayPal REST SDKs to create a webhook for notifications.

Configure a webhook listener

Configure a server to listen on localhost for incoming POST traffic from webhooks. Your listener is a simple route that uses Express. Listen for incoming POST traffic and echo the POST body to the console. Use this body to do whatever you like with the listener when it comes in.

  1. Create a listener.

    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');
    });
    

    You start with the listener because the ngrok live URL must provide the webhooks when you create or update them.

  2. With the listener set up on localhost:3001, use ngrok to create a tunnel from localhost to the Internet. In a Terminal window, run this command to open a live tunnel for localhost:3001:

    ngrok http 3001
    

    The live address that points the PayPal webhook to your running listener on localhost is a randomized name. Look for the forwarding URL. For more information, see Expose a local web server to the internet. PayPal posts notifications through this tunnel.

That's all you need to set up the listener.

Subscribe to notifications

Provide credentials to subscribe your app to webhook events. To do so, provide the public ngrok URI from the previous step.

Create webhooks for your application, which creates notifications when certain events happen with payments, refunds, and so on your app. You only need to create these webhooks one time to bind them to the app. You do not need to run them each time that you want to use them.

Before you start, set up your environment.

  1. Set up the JSON webhooks structure to define your listener. The webhooks object defines:

    • url. The URL to which to send all webhook events. The example sends events to the ngrok live URL.

    • event_types. The types of events for which to listen. The example listens for completed and denied payment events.

    After the code sets up the webhooks object, it passes it to the notification.webhook.create call:

    var webhooks = {
        "url": "https://436e4d13.ngrok.io", // Replace this url with your actual ngrok URL
        "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);
        }
    });
    

    If the call successfully creates the webhooks, PayPal sends notifications to the specified endpoint, which runs on localhost.

  2. After you issue a payment using those application credentials, information about the payment state is sent to the endpoint that you set up.

    An example of a POST body for a successful PayPal payment that PayPal sends as the notification might look like this:

    {
      "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"
          },
          {
            "...":"..."
          }
        ]
      }
    }
    

Next

Depending on the SDK, there are different ways to verify that the POSTed content actually came from PayPal rather than from a random POST of content to your endpoint. For more information, see Notification messages.

Additional information