DEV Community

Cover image for PayPal Has Updated Its Webhook Verification Endpoint
Arit Developer for PayPal Developer

Posted on • Edited on • Originally published at Medium

PayPal Has Updated Its Webhook Verification Endpoint

TL;DR;

PayPal requires that all the webhook notification messages it sends be verified by the webhook listener receiving these messages.
This requirement enhances security by ensuring that your webhook listener is receiving authentic PayPal webhook messages.
PayPal has updated its endpoint for verifying PayPal webhook notification messages, and its old webhook verification method is now deprecated. The updated endpoint simplifies the process of verifying PayPal webhook messages, which improves the developer experience.
The update also incorporates a lot more of our REST APIs (such as the Orders API). You may learn more about the update rationale here.


A webhook is an automated HTTP request sent from an application when triggered by an event. This request carries a message (called a payload) to a unique destination URL (called a webhook listener), and the receiving application can take further actions based on the payload content. Webhooks allow applications to communicate seamlessly with each other and enable speed in processing and service delivery.

PayPal’s REST APIs use webhooks to notify your application that an event has occurred; for example, a new order has been placed, or a payment has been processed. You can create a webhook associated with an event in your PayPal Developer Portal account. PayPal webhooks support an extensive list of event types.

An unscrupulous player could spoof a webhook notification message and attempt to make the message appear as it originated from PayPal. Therefore, to ensure security, PayPal requires that applications verify all webhook notifications received from PayPal.

To verify the PayPal webhook message, your application sends a POST request to PayPal’s verify-webhook-signature endpoint with a payload containing several required parameters:

  • auth_algo extracted from the PAYPAL-AUTH-ALGO value in the webhook response header.
  • cert_url extracted from the PAYPAL-CERT-URL value in the webhook response header.
  • transmission_id extracted from the PAYPAL-TRANSMISSION-ID value in the webhook response header.
  • transmission_sig extracted from the PAYPAL-TRANSMISSION-SIG value in the webhook response header.
  • transmission_time extracted from the PAYPAL-TRANSMISSION-TIME value in the webhook response header.
  • webhook_id The ID of the webhook as configured in your PayPal Developer Portal account.
  • webhook_event This is the webhook notification response received from PayPal, which you are now verifying.

Here is a sample webhook verification payload:



{ 
"auth_algo": "SHA256withRSA", 
"cert_url": "cert_url", 
"transmission_id": "69cd13f0-d67a-11e5-baa3-778b53f4ae55", 
"transmission_sig": 
"lmI95Jx3Y9nhR5SJWlHVIWpg4AgFk7n9bCHSRxbrd8A9zrhdu2rMyFrmz+Zjh3s3boXB07VXCXUZy/UFzUlnGJn0wDugt7FlSvdKeIJenLRemUxYCPVoEZzg9VFNqOa48gMkvF+XTpxBeUx/kWy6B5cp7GkT2+pOowfRK7OaynuxUoKW3JcMWw272VKjLTtTAShncla7tGF+55rxyt2KNZIIqxNMJ48RDZheGU5w1npu9dZHnPgTXB9iomeVRoD8O/jhRpnKsGrDschyNdkeh81BJJMH4Ctc6lnCCquoP/GzCzz33MMsNdid7vL/NIWaCsekQpW26FpWPi/tfj8nLA==", 
"transmission_time": "2016-02-18T20:01:35Z", 
"webhook_id": "1JE4291016473214C", 
"webhook_event": {
   "id": "8PT597110X687430LKGECATA",
   "create_time": "2013-06-25T21:41:28Z",
   "resource_type": "authorization",
   "event_type": "PAYMENT.AUTHORIZATION.CREATED",
   "summary": "A payment authorization was created",
   "resource": {
      "id": "2DC87612EK520411B",
      "create_time": "2013-06-25T21:39:15Z",
      "update_time": "2013-06-25T21:39:17Z",
      "state": "authorized",
      "amount": {
         "total": "7.47",
         "currency": "USD",
         "details": {
            "subtotal": "7.47"
         }
      },
      "parent_payment": "PAY-36246664YD343335CKHFA4AY",
      "valid_until": "2013-07-24T21:39:15Z",
      "links": [
         {
            "href": "https://api-m.paypal.com/v1/payments/authorization/2DC87612EK520411B",
            "rel": "self",
            "method": "GET"
         },
         {
            "href": "https://api-m.paypal.com/v1/payments/authorization/2DC87612EK520411B/capture",
            "rel": "capture",
            "method": "POST"
         },
         {
            "href": "https://api-m.paypal.com/v1/payments/authorization/2DC87612EK520411B/void",
            "rel": "void",
            "method": "POST"
         },
         {
            "href": "https://api-m.paypal.com/v1/payments/payment/PAY-36246664YD343335CKHFA4AY",
            "rel": "parent_payment",
            "method": "GET"
         }
      ]
   }
}
} 


Enter fullscreen mode Exit fullscreen mode

Here is a sample POST request verifying a PayPal webhook notification, sent from a NodeJS application:



var fetch = require('node-fetch'); 
fetch('https://api-m.sandbox.paypal.com/v1/notifications/verify-webhook-signature', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer ECvJ_yBNz_UfMmCvWEbT_2ZWXdzbFFQZ-1Y5K2NGgeHn' 
    },
    body: JSON.stringify({ "transmission_id": "69cd13f0-d67a-11e5-baa3-778b53f4ae55", "transmission_time": "2016-02-18T20:01:35Z", "cert_url": "cert_url", "auth_algo": "SHA256withRSA", "transmission_sig": "lmI95Jx3Y9nhR5SJWlHVIWpg4AgFk7n9bCHSRxbrd8A9zrhdu2rMyFrmz+Zjh3s3boXB07VXCXUZy/UFzUlnGJn0wDugt7FlSvdKeIJenLRemUxYCPVoEZzg9VFNqOa48gMkvF+XTpxBeUx/kWy6B5cp7GkT2+pOowfRK7OaynuxUoKW3JcMWw272VKjLTtTAShncla7tGF+55rxyt2KNZIIqxNMJ48RDZheGU5w1npu9dZHnPgTXB9iomeVRoD8O/jhRpnKsGrDschyNdkeh81BJJMH4Ctc6lnCCquoP/GzCzz33MMsNdid7vL/NIWaCsekQpW26FpWPi/tfj8nLA==", "webhook_id": "1JE4291016473214C", "webhook_event": { "id": "8PT597110X687430LKGECATA", "create_time": "2013-06-25T21:41:28Z", "resource_type": "authorization", "event_type": "PAYMENT.AUTHORIZATION.CREATED", "summary": "A payment authorization was created", "resource": { "id": "2DC87612EK520411B", "create_time": "2013-06-25T21:39:15Z", "update_time": "2013-06-25T21:39:17Z", "state": "authorized", "amount": { "total": "7.47", "currency": "USD", "details": { "subtotal": "7.47" } }, "parent_payment": "PAY-36246664YD343335CKHFA4AY", "valid_until": "2013-07-24T21:39:15Z", "links": [ { "href": "https://api-m.paypal.com/v1/payments/authorization/2DC87612EK520411B", "rel": "self", "method": "GET" }, { "href": "https://api-m.paypal.com/v1/payments/authorization/2DC87612EK520411B/capture", "rel": "capture", "method": "POST" }, { "href": "https://api-m.paypal.com/v1/payments/authorization/2DC87612EK520411B/void", "rel": "void", "method": "POST" }, { "href": "https://api-m.paypal.com/v1/payments/payment/PAY-36246664YD343335CKHFA4AY", "rel": "parent_payment", "method": "GET" } ] } } })
}); 


Enter fullscreen mode Exit fullscreen mode

When your webhook verification request is successful, PayPal responds with the following payload (and an HTTP status of 200):



{
  "verification_status": "SUCCESS" 
}


Enter fullscreen mode Exit fullscreen mode

PayPal has a webhook simulator with which you can quickly test your webhook listener. Grab the URL of your webhook listener, or grab a mock listener URL from services like https://webhook.site. In the webhook simulator, enter this URL in the Webhooks URL field, select the Event Type for which you want a notification message, then click Send Test:

Screenshot of PayPal Webhook Smmulator

Your webhook listener should receive a mock payload from PayPal that resembles the examples provided earlier in this post.


PayPal takes the security of our products very seriously; with this update to our webhook verification endpoint, we continue to provide seamless payment integrations, coupled with mission-critical quality security standards.


Join the PayPal Developer Community

Our Developer Community members support each other in integrating PayPal technologies, contributing to open source, expanding knowledge and networks, and improving PayPal's products and documentation. We'd love to have you join us! 💙

Top comments (5)

Collapse
 
jared201 profile image
Jared Odulio

just want to ask if you have tried that with the latest Subscription API? Seems nothing is firing from Paypal's end.

Collapse
 
montistar profile image
Christina Monti

Apologies for the late response, are you still having this issue? If so, we will check on this one for you.

Collapse
 
jared201 profile image
Jared Odulio

Yes, when I create a Subscription Plan -> Subscriptions in my Sandbox and create a webhook from a developer console as per instruction, I'm assuming the webhook is called from the Subscriptions event. But if I rather create a Subscription button and specify my URL to the notify_url parameter the webhook works fine but the payload is old version.

Thread Thread
 
aritdeveloper profile image
Arit Developer

Hello @jared201 do you have a code snippet, or perhaps a video, detailing this bug that you are experiencing? I could pass it along to our Subscriptions team.

Collapse
 
reacthunter0324 profile image
React Hunter

Sounds good