Design to Duty: How we make architecture decisions at Adyen
In short, using a webhook is a great way for your applications to receive events or notifications from a service.
To illustrate, think about your favorite local bookstore. Before you ever make a trip out to them, you’d prefer to know whether or not a certain book is in stock. One way to find out is to call the bookstore yourself and ask them directly.
While this certainly works, one drawback is that you may have to make repeated calls to find out the availability of your favorite book. This wouldn’t be a great use of your (nor the store’s) time and resources. What if the book tends to sell out quickly? Having information about the book’s availability the moment it’s restocked could greatly increase your chances of coming home with a new novel.
In the context of software development, calling the bookstore is like making an API call and receiving a response. For both situations, it’s still a manual process, and you receive information only when you ask for it.
However, what if the bookstore calls you when they finally have the book in-stock? This would save time for both parties, as information about any in-stock status changes would only be sent whenever there’s new information to share in the first place.
This is the philosophy behind a webhook: a way to receive new information or data proactively without having to repeatedly poll a service. Now, how does this look like in real-world applications?
Imagine the “read receipts” in your favorite messaging app. For the most part, it’s made possible by taking advantage of an event webhook. That is, whenever your sent message is opened by the other application, an HTTP POST request is made to a specified URL. In turn, your application is notified with data that the message has been read, and can then run business logic for rendering the read receipt. There’s no need for your application to continuously check if your message has been read, as it’ll be automatically notified when the read status has been updated.
All in all, using a webhook is ideal whenever you need to run some business logic in your application based on an event happening in another application.
Webhooks are essential in the financial services space due to the asynchronous information flow of banks, payment methods, and other financial systems. Adyen provides a webhook to communicate this crucial information to our customers as soon it is available. This information includes:
There are two main steps to configure Adyen’s notification webhooks:
Let’s check out how to set up notifications in a test online Checkout application built in React and Express. We’ll also be using ngrok, which helps provide a public URL to tunnel into localhost as we test our integration.
Before writing our first line of code, be sure to clone and install the test application. You can find instructions for getting everything up and running, including generating the required account keys, in the test application’s README.
Once your project is up and running (i.e., accessible on port 8080), the first step is to expose and configure an endpoint on the server. In the Express server file, we’ll create an HTTP POST route to /api/webhook/notification:
As notifications come in, we’ll first acknowledge the notifications with an [accepted] response. This helps ensure that our application server continues to properly accept notifications:
Next, we’ll need to retrieve the array of notification request items from the POST body, which looks something like this:
Note that some fields included in the NotificationRequestItem object depend on the type of event that triggered the notification. For example, notifications triggered by a request to refund will be different than a notification triggered by a chargeback request.
Next, we need to iterate over the list of notification request items, and process them based on the type of event the notification item is associated with (i.e., its eventCode). As we iterate through the list, however, we’ll also want to verify its HMAC (hash-based message authentication code) signatures. This helps protect the application server from unauthorised notifications, such as any data that may have been modified during transmission. Since our application leverages the Adyen Node.js server-side library to interact with Adyen’s API, we can conveniently import and instantiate the built-in HMAC validator class to do just that:
Next, we’ll begin processing each notification request item:
As we iterate through the list of notification request items, we use our instance of the HMAC validator to validate each notification request item, passing in the object itself, as well as our HMAC key (referenced above in an environment variable). This secret key enables HMAC-signed notifications, and we’ll generate it shortly in the next steps of this blog.
If the notification request item is valid, we run some business logic based on the event code. For example, the notification may detail a successful payment, or inform you that a new report (for accounting purposes) is available. Your application can then take any action it needs to based on this new information.
All together, our endpoint should look something like the following:
At this point, our server endpoint has been exposed and configured. The issue however, is that our application is currently being served on localhost. To set up the webhook, we’ll need a public URL to the application. This is where we leverage the ngrok tool, which helps us tunnel (i.e., forward) to our local application from a publicly-accessible URL.
If everything’s running correctly, you should see something like this output in the terminal:
Note the public URL as referenced by “Forwarding” in the output. We’ll use this value as we head into the Adyen Customer Area for webhook configuration.
The next step is to provide your server’s details, as well as customize the information you want to receive in notifications. To get started, first log in to Customer Area. On the top right, navigate to Account > Server communication. Then, next to Standard Notification, click Add.
Under Transport, supply the following information:
Finally, under Additional Settings, select the information you want to receive in notifications. For example, adding the acquirer result allows you to receive standardized mapping of the acquirer results for AVS and CVC checks. For more information on shopper and transaction information, check out Additional settings in our documentation.
The final step is to select Generate new HMAC key. This allows you to receive HMAC-signed notifications, which will verify the integrity of notifications using these HMAC signatures. After generating the HMAC key, assign its value to an environment variable (i.e., process.env.ADYEN_HMAC_KEY as referenced in the above server code).
At this point, the server and server communication settings have been fully set. Before we jump into testing, be sure to select Save Configuration at the bottom of the page.
To make sure that we can receive notifications, we’ll first need to test them. While still on the current server settings page, scroll to the bottom and toggle which notifications you want to test. Then, select Test Configuration.
If everything was set up correctly, you should see something like the following at the top of the page:
At this point, it’s a wrap! Feel free to further configure your server communication, and continue to apply any business logic in your server code as you see fit.
Implementing Adyen notification webhooks is crucial for a successful integration with Adyen. To get started, feel free to check out the quick start in documentation. To see everything in action, first make sure you have the proper keys and credentials from a test account, then clone one of our example integrations.
By submitting this form, you acknowledge that you have reviewed the terms of our Privacy Statement and consent to the use of data in accordance therewith.