<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Beppe Catanese</title>
    <description>The latest articles on DEV Community by Beppe Catanese (@gcatanese).</description>
    <link>https://dev.to/gcatanese</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F778262%2F3c6410be-da82-4bf3-a68b-436a50288b41.jpeg</url>
      <title>DEV Community: Beppe Catanese</title>
      <link>https://dev.to/gcatanese</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gcatanese"/>
    <language>en</language>
    <item>
      <title>Adyen API Diff Tool</title>
      <dc:creator>Beppe Catanese</dc:creator>
      <pubDate>Tue, 19 Aug 2025 12:41:00 +0000</pubDate>
      <link>https://dev.to/adyen/adyen-api-diff-tool-3pjo</link>
      <guid>https://dev.to/adyen/adyen-api-diff-tool-3pjo</guid>
      <description>&lt;p&gt;APIs evolve quickly with new features, design changes, and deprecations, making it challenging for consumers to keep up. This impact can be significant: developers might miss valuable improvements, misunderstand the behavior of new features, delay the adoption of critical compliance updates. &lt;/p&gt;

&lt;p&gt;This is why we have put passion and effort in the Adyen API Diff Tool, a new tool designed to help developers and technical users easily track and compare changes between API versions.&lt;/p&gt;

&lt;p&gt;Whether you're maintaining an existing integration or building something new, staying on top of API changes is critical. Previously, this information was scattered across various sources like product announcements, documentation, release notes, and GitHub, resulting in a suboptimal user experience.&lt;/p&gt;

&lt;p&gt;This changes today with our new powerful &lt;a href="https://docs.adyen.com/api-explorer/api-diff-tool" rel="noopener noreferrer"&gt;API Diff Tool&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9k1wsey8kg0sypcdev2e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9k1wsey8kg0sypcdev2e.png" alt=" " width="800" height="513"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Features&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Our goal is simple: to make it easy to understand what’s changed in the Adyen APIs between any two versions.&lt;/p&gt;

&lt;p&gt;The Diff Tool includes built-in filters to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Compare API versions &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;View changes by version, endpoint and HTTP method&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Group changes by endpoint&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Spot quickly what’s new, changed, or removed&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Focus on Breaking Changes only&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Labels, colors, and accordions provide a clean and effective way to visualize the changes. It is embedded directly in the API Explorer. From any specific change in the log, you can easily navigate to the relevant API reference or endpoint details.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmc9mbhofbeer61krmebo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmc9mbhofbeer61krmebo.png" alt=" " width="800" height="753"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Benefits for Developers and other Users&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The API Diff Tool is designed to remove uncertainty when working with Adyen APIs. Whether you’re integrating for the first time or upgrading to a new version, it is a valuable tool to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Understand what changed**: compare any two API versions and see exactly what’s been added, removed, or modified.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Spot breaking changes early**: identify changes that could impact your integration, so you can plan ahead.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Evolve faster and safer**: stay up-to-date with the latest API releases to integrate the new products and features available.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Find what you need more quickly**: go to the API Explorer to find the API reference, the Diff Tool, a lot of examples and code snippets. Everything you need is in one place.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwi8mbyacab5o5sbunbef.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwi8mbyacab5o5sbunbef.png" alt=" " width="800" height="696"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Acknowledgments and Credits&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This initiative was a true cross-team effort involving Technical Writers, Developer Relations, and API Champions. We've put significant thought and effort into delivering on our promise of a best-in-class Developer Experience.&lt;/p&gt;

&lt;p&gt;A special thank you goes to the open-source project &lt;a href="https://github.com/Tufin/oasdiff" rel="noopener noreferrer"&gt;&lt;strong&gt;OASDiff&lt;/strong&gt;&lt;/a&gt;, which powers the engine behind our Diff Tool. It enables detailed comparisons between OpenAPI specification files, detects breaking changes, and generates change diffs in multiple formats.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Next Steps: Collect Feedback and Iterate&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The API Diff Tool helps developers and integration partners manage API updates more efficiently. It simplifies upgrading to the latest API version, troubleshooting issues, and planning new integrations. By making API changes more transparent, this tool reduces friction and effort during the integration journey, ultimately enhancing the developer experience and accelerating new API adoption.&lt;/p&gt;

&lt;p&gt;In the next iteration we will be looking at adding support for webhooks and the option to subscribe to changes.&lt;/p&gt;

&lt;p&gt;The Adyen API Diff Tool is now available in our &lt;a href="https://docs.adyen.com/api-explorer/api-diff-tool" rel="noopener noreferrer"&gt;API Explorer&lt;/a&gt;! Try it out and share your feedback. We look forward to your input to continue improving.&lt;/p&gt;

</description>
      <category>api</category>
      <category>versioning</category>
    </item>
    <item>
      <title>A Developer’s Guide to HMAC Validation for Adyen Webhooks</title>
      <dc:creator>Beppe Catanese</dc:creator>
      <pubDate>Mon, 16 Jun 2025 09:47:44 +0000</pubDate>
      <link>https://dev.to/adyen/a-developers-guide-to-hmac-validation-for-adyen-webhooks-4i96</link>
      <guid>https://dev.to/adyen/a-developers-guide-to-hmac-validation-for-adyen-webhooks-4i96</guid>
      <description>&lt;h1&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;When it comes to payments, security isn’t optional — it’s essential. If you’re integrating with Adyen, ensuring the incoming webhooks’ authenticity and integrity is very important. That’s where &lt;a href="https://www.okta.com/identity-101/hmac/" rel="noopener noreferrer"&gt;Hash-based Message Authentication Code&lt;/a&gt; (HMAC) plays a critical role in securing your Adyen integration.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhfrfwqccye08ez23fthp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhfrfwqccye08ez23fthp.png" alt="Image description" width="800" height="144"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Implementing, testing, and troubleshooting HMAC validation can be challenging. This guide explains how HMAC validation works, highlights the challenges, and provides tools and best practices for secure and reliable implementation.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;HMAC at Adyen&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;All Adyen webhooks use HMAC to ensure the integrity and authenticity of the payloads delivered to your integrations. The HMAC key should be &lt;a href="https://docs.adyen.com/development-resources/webhooks/verify-hmac-signatures/#enable-hmac-signatures" rel="noopener noreferrer"&gt;enabled&lt;/a&gt; when setting up a new webhook (either in the Customer Area Webhook page or using the &lt;a href="https://docs.adyen.com/api-explorer/Management/3/overview" rel="noopener noreferrer"&gt;Management API&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Adyen will use the HMAC key to sign the payload by creating an HMAC signature. You must validate the HMAC signature, delivered with the webhook, using the same HMAC key.&lt;/p&gt;

&lt;p&gt;Adyen webhooks fall into two main categories, each with its approach to HMAC implementation. Let’s explore the two scenarios.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;1. Payments Webhooks&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;For payments-related webhooks, the calculation of the signature involves using a &lt;a href="https://docs.adyen.com/development-resources/webhooks/verify-hmac-signatures/#verify-using-your-own-solution" rel="noopener noreferrer"&gt;subset of fields&lt;/a&gt;, and it’s embedded directly within the JSON payload under the &lt;code&gt;additionalData&lt;/code&gt; object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
   "live":"false",
   "notificationItems":[
      {
         "NotificationRequestItem":{
            "additionalData":{
               "hmacSignature":"+JWKfq4ynALK+FFzGgHnp1jSMQJMBJeb87dlph24sXw="
            },
          ...
         }
      }
   ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  &lt;strong&gt;2. Other Webhooks (Adyen for Platforms, Management)&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;For non-payment webhooks, the signature is calculated using the entire JSON payload. Instead of being included in the payload itself, the signature is provided in the HTTP Header &lt;code&gt;hmacSignature&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;content-length: 1614
content-type: application/json
hmacsignature: SMQZFOq3oIdugmf97u9TB+5256jjXgUX3MRjK+RlGNQ=
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  &lt;strong&gt;Implementing HMAC Validation&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Developers have two options for implementing HMAC validation: creating their validation function or using the Adyen’s open-source libraries.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Custom Implementation&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;If you choose to implement your own HMAC validation, you’ll need to follow Adyen’s documentation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;For payments webhooks, follow the &lt;a href="https://docs.adyen.com/development-resources/webhooks/verify-hmac-signatures/" rel="noopener noreferrer"&gt;Payment webhook HMAC validation guide&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For other webhooks, follow the &lt;a href="https://docs.adyen.com/api-explorer/Management/latest/overview" rel="noopener noreferrer"&gt;Platform webhook HMAC validation guide&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Implementing a custom HMAC validation is not trivial — it requires handling the correct fields in the exact order and matching the encryption algorithm. Instead, use Adyen’s libraries to simplify the process, reducing both effort and risks.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Using Adyen Libraries (Recommended)&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Use the &lt;a href="https://github.com/Adyen" rel="noopener noreferrer"&gt;Adyen open-source libraries&lt;/a&gt;, which provide built-in functions for calculating and validating HMAC signatures. The libraries are thoroughly tested, regularly updated, and available in multiple programming languages (Node.js, PHP, Java, .NET, etc.).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;String payload = "....";

// obtain signature
String hmacsignature = headers.get("hmacsignature");
if (hmacsignature == null || hmacsignature.isBlank()) {
   log.warn("HMAC Signature not found");
   throw new RuntimeException("HMAC Signature not found");
}

// perform HMAC validation 
if (!hmacValidator.validateHMAC(payload, hmacsignature, "MY_HMAC_KEY")) {
  throw new RuntimeException("Invalid HMAC signature");
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example of Java snippet to validate the HMAC signature&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Known Issues and Challenges&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;HMAC validation errors are, unfortunately, common and challenging to troubleshoot. Several aspects contribute to this complexity:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Propagation delay when updating the HMAC key&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using the correct HMAC key&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Unexpected modification of the webhook payload&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;HMAC Key Update Propagation Delay&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;When users update (regenerate) the HMAC key associated with a webhook, there’s a delay (up to 10 minutes) before the new HMAC key is fully propagated and used by all webhook components. During this transition period, both the previous and new HMAC keys remain valid.&lt;/p&gt;

&lt;p&gt;This delay can lead to validation failures if the implementation isn’t prepared to handle the transition period, especially if you immediately discard the old key when generating a new one.&lt;/p&gt;

&lt;p&gt;The best practice here is to &lt;strong&gt;maintain both keys temporarily&lt;/strong&gt; during the transition window.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Using the Correct HMAC Key&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;One of the most common issues occurs when developers use the HMAC key from a different webhook configuration. With multiple webhooks in use, especially across development, testing, and production environments, it’s easy to mix up which key belongs to which webhook.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Key Check Value (KCV) Verification&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;The Key Check Value (KCV) is a short hex value derived from the HMAC key that serves as a fingerprint to verify the key (without revealing it).&lt;/p&gt;

&lt;p&gt;The KCV is found on the Webhook Configuration page in the Adyen Customer Area (CA). When troubleshooting, always compare the KCV of the HMAC key you’re using with the one displayed in the CA to confirm you’re working with the correct key.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm39xau0uzd6x47z2fi15.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm39xau0uzd6x47z2fi15.png" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
Webhook Configuration page showing the KCV&lt;/p&gt;

&lt;p&gt;You can validate the KCV by implementing the following steps:&lt;/p&gt;

&lt;p&gt;1. Calculate an 8-digit zero hash (“00000000”) using your HMAC key with the HMAC-SHA256 algorithm&lt;/p&gt;

&lt;p&gt;2. Take the last 3 bytes of the resulting hash and convert it to an uppercase hex string&lt;/p&gt;

&lt;p&gt;3. Compare this value with the KCV shown in the Customer Area&lt;/p&gt;

&lt;p&gt;Adyen’s libraries simplify this process by including &lt;a href="https://github.com/Adyen/adyen-node-api-library/tree/main/tools/hmac" rel="noopener noreferrer"&gt;scripts to calculate the KCV&lt;/a&gt;, making it easy to verify that you’re using the correct HMAC key.&lt;/p&gt;
&lt;h1&gt;
  
  
  &lt;strong&gt;Unexpected Modifications of the Webhook Payload&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;A common but often overlooked cause of HMAC validation failures is unintentional modification of the webhook payload.&lt;/p&gt;

&lt;p&gt;Adyen webhooks deliver information relevant to the customer’s integration (such as references, amounts, etc.) &lt;strong&gt;without trimming or encoding data&lt;/strong&gt;. However, application frameworks and third-party libraries might alter incoming requests in various ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Trimming whitespaces&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Converting line endings&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Normalizing JSON structures&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Decoding URL-encoded characters&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check if any infrastructure (web servers, API gateways, proxies) between Adyen and your application could be altering the payload of the incoming HTTP request.&lt;/p&gt;

&lt;p&gt;Before any framework processing, capture the raw webhook body and use the proper comparison (byte or string comparison rather than object matching). During your testing, &lt;strong&gt;it’s a good practice&lt;/strong&gt; to test payloads containing special characters and whitespaces to ensure proper handling.&lt;/p&gt;
&lt;h1&gt;
  
  
  &lt;strong&gt;HMAC Validation Troubleshooting&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;When faced with HMAC validation failures, there are several approaches to troubleshoot and resolve the issue.&lt;/p&gt;
&lt;h1&gt;
  
  
  &lt;strong&gt;Test in Customer Area (CA)&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;The Adyen Customer Area provides a built-in feature to t&lt;a href="https://ca-test.adyen.com/ca/ca/config/webhooks.shtml" rel="noopener noreferrer"&gt;est your webhook configuration&lt;/a&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Go to Developers -&amp;gt; Webhooks -&amp;gt; Edit webhook&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click on “Test Configuration”&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Choose an “Event” type from the dropdown&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click “Test” to send the webhook to your endpoint&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Verify the HTTP response is successful by returning a 2xx response status code&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This page allows you to edit the webhook payload as needed (for example, changing a reference, amount, or other fields). The HMAC signature will be automatically recalculated and delivered with the new request.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use Customer Area Testing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Send webhooks from the Customer Area to verify the end-to-end flow: Adyen sends the webhook, your integration receives the event, and your implementation validates the HMAC signature. This method is ideal for confirming that the entire flow works correctly.&lt;/p&gt;
&lt;h1&gt;
  
  
  &lt;strong&gt;Test with Postman Collection&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Our &lt;a href="https://www.postman.com/adyendev" rel="noopener noreferrer"&gt;AdyenDev Postman&lt;/a&gt; space includes a Postman collection designed explicitly for webhook testing:&lt;/p&gt;

&lt;p&gt;1. Fork the Adyen Postman collection to your private workspace&lt;/p&gt;

&lt;p&gt;2. Define collection variables, including your HMAC key&lt;/p&gt;

&lt;p&gt;3. Update the webhook payload as needed&lt;/p&gt;

&lt;p&gt;4. Send the request to your application’s webhook endpoint&lt;/p&gt;

&lt;p&gt;The Adyen Webhooks Postman collection contains several sample payloads you can use or modify to simulate webhook events. It automatically calculates the HMAC signature when sending the request.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use Postman testing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use Postman to test webhooks in isolation. This is ideal for validating your implementation without involving the Adyen backend and focusing on how your integration handles webhook events independently.&lt;/p&gt;
&lt;h1&gt;
  
  
  &lt;strong&gt;Test with Adyen Library Scripts&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Adyen libraries include built-in methods to calculate the HMAC signature using your HMAC key and JSON payload. Check out the code from GitHub or open the GitHub repository in Codespaces (browser-based development environment), and follow the instructions specific to the library&lt;/p&gt;

&lt;p&gt;For example, if you are using the &lt;a href="https://github.com/Adyen/adyen-node-api-library/" rel="noopener noreferrer"&gt;Node API library&lt;/a&gt; and need to troubleshoot an issue with the HMAC validation, you can calculate the HMAC signature in 2 simple steps.&lt;/p&gt;

&lt;p&gt;First go to the &lt;a href="https://github.com/Adyen/adyen-node-api-library/tree/main/tools/hmac" rel="noopener noreferrer"&gt;folder&lt;/a&gt; that includes the scripts, and install the necessary dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// go to dir and setup
cd tools/hmac
npm install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Calculate the HMAC signature, passing the JSON payload and the HMAC key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// run script passing the HMAC key and the JSON file with the payload
node calculateHmacPayments.js 11223344D785FBAE710E7F943F307971BB61B21281C98C9129B3D4018A57B2EB payload.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;⚠️ &lt;strong&gt;Important&lt;/strong&gt;: When reusing a JSON payload, ensure it doesn’t get modified, formatted, or “prettified,” as this would alter the payload and result in a different signature.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Run in Codespaces&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;You can use effortlessly GitHub Codespaces to run these scripts directly from your browser:&lt;/p&gt;

&lt;p&gt;1. Open the GitHub repository for your Adyen library&lt;/p&gt;

&lt;p&gt;2. Start a Codespaces workspace&lt;/p&gt;

&lt;p&gt;3. In the terminal, navigate to the appropriate directory and run the scripts&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@user ➜ cd /tools/hmac
@user ➜ npm install
up to date, audited 8 packages in 477ms

@user ➜ npm list @adyen/api-library
hmac-troubleshooting@1.0.0 /workspaces/adyen-node-api-library/tools/hmac
└── @adyen/api-library@25.0.0

@user ➜ node calculateHmacPayments.js 11223344D785FBAE710E7F943F307971BB61B21281C98C9129B3D4018A57B2EB payload.json

Calculating HMAC signature with payload from 'payload.json'
HMAC signature: qHNSvxCCix79xgBdWemxf0rcNMWoLrMK/4IgMnkOsWI=
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;When to use Library Built-in Scripts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use these scripts to troubleshoot HMAC validation failures in applications using the Adyen libraries: verify the expected HMAC signature using your HMAC key and payload.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;⚠️ Important: signatures not matching&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If your application calculates a different HMAC signature than these scripts, potential issues might include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Using an outdated version of the library&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using the wrong HMAC key&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Working with a modified payload (check for spaces, formatting, and special characters)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd451h3939xk7j3iw4j4a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd451h3939xk7j3iw4j4a.png" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Key takeaways for successful HMAC implementation&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;This article explains HMAC validation, common challenges, and how to troubleshoot issues effectively:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use Adyen’s open-source libraries to simplify HMAC validation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Manage HMAC key updates to avoid discarding old keys too early.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Avoid payload modifications to maintain signature integrity.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Leverage Adyen’s testing and troubleshooting tools.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Follow our guidelines and best practices to securely process Adyen webhooks and deliver a seamless payment experience to your shoppers 💚&lt;/p&gt;

</description>
      <category>webhooks</category>
      <category>hmac</category>
      <category>testing</category>
    </item>
    <item>
      <title>A Developer's Guide to the new iDEAL</title>
      <dc:creator>Beppe Catanese</dc:creator>
      <pubDate>Tue, 10 Sep 2024 15:51:59 +0000</pubDate>
      <link>https://dev.to/adyen/a-developers-guide-to-the-new-ideal-2o0c</link>
      <guid>https://dev.to/adyen/a-developers-guide-to-the-new-ideal-2o0c</guid>
      <description>&lt;p&gt;&lt;a href="https://docs.adyen.com/payment-methods/ideal/" rel="noopener noreferrer"&gt;iDEAL&lt;/a&gt;, a Dutch payment method that covers bank-to-bank transfers, was launched in 2005 and is the most popular payment method in the Netherlands today.&lt;/p&gt;

&lt;p&gt;Shoppers can pay quickly, safely, and easily with iDEAL through their bank's app, internet banking, or by scanning a QR code on their desktop. Whether it's a payment link after a purchase or a payment request from a friend, iDEAL comes in various forms, and the magenta iDEAL logo is synonymous with online payments for many people living in the Netherlands.&lt;/p&gt;

&lt;p&gt;As the payment ecosystem rapidly changes, with increasing demand for a smooth checkout experience, iDEAL is also upgrading its infrastructure, flows, and features.&lt;/p&gt;

&lt;p&gt;Read this blog to &lt;strong&gt;learn what is new in iDEAL 2.0&lt;/strong&gt; and what developers need to know.&lt;/p&gt;

&lt;p&gt;⚠️ This is a necessary compliance change: all existing payment integrations must be updated by April 1st, 2025.&lt;/p&gt;

&lt;h2&gt;
  
  
  Features of iDEAL 2.0
&lt;/h2&gt;

&lt;h3&gt;
  
  
  New infrastructure
&lt;/h3&gt;

&lt;p&gt;The new infrastructure introduces the iDEAL Hub and a centralized payment page where the users can select their bank. The goal is to facilitate adoption and streamline the onboarding process for banks, issuers, and payment providers. Shoppers will benefit from experiencing a consistent bank selection flow across different web shops, making the process familiar and trusted.&lt;/p&gt;

&lt;h3&gt;
  
  
  iDEAL profiles
&lt;/h3&gt;

&lt;p&gt;Consumers will be able to save their delivery details and preferred accounts, creating an iDEAL profile via their issuer bank. They can share this information with a webshop, completing the order and payment in one step.&lt;/p&gt;

&lt;h3&gt;
  
  
  Payment flows
&lt;/h3&gt;

&lt;p&gt;Profiles will help recognize returning users and make the payment faster by offering different options, such as a QR code, the iDEAL payment page, or a one-click payment checkout.&lt;/p&gt;

&lt;h3&gt;
  
  
  Enabling iDEAL 2.0
&lt;/h3&gt;

&lt;p&gt;The significant change in the iDEAL payment flow is the bank selection process. The list of available banks will no longer be part of the checkout form but will instead be available on the new iDEAL payment page. The checkout page must redirect shoppers to the iDEAL payment page, where iDEAL will handle both bank selection and payment execution.&lt;/p&gt;

&lt;p&gt;This is a &lt;strong&gt;necessary compliance change&lt;/strong&gt; that requires all merchants to update the existing integrations.&lt;/p&gt;

&lt;p&gt;When adding iDEAL as a new payment method, for example when developing a new payment integration or if you configure a new merchant account, iDEAL 2.0 is enabled by default.&lt;/p&gt;

&lt;p&gt;For existing integrations on TEST we have configured the new iDEAL 2.0 payment method next to the existing one: update your payment integration and, when you are ready to test, activate iDEAL 2.0 in your Customer Area.&lt;/p&gt;

&lt;h2&gt;
  
  
  Update your payment integration
&lt;/h2&gt;

&lt;p&gt;The changes required depend on the type of integration.&lt;/p&gt;

&lt;h3&gt;
  
  
  API-only
&lt;/h3&gt;

&lt;p&gt;API-only integration is a method of integrating Adyen APIs where developers prefer to handle their checkout forms and user interfaces. This type of integration only requires one change: removing the list of banks from the Checkout page.&lt;/p&gt;

&lt;p&gt;Your payment integration must initiate an iDEAL payment using the Adyen Checkout &lt;code&gt;/payments&lt;/code&gt; API endpoint. Developers will no longer have to pass the issuer chosen by the shopper:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "merchantAccount":"YOUR_MERCHANT_ACCOUNT",
  "reference":"YOUR_ORDER_NUMBER",
  "amount":{
    "currency":"EUR",
    "value":1000
  },
  "paymentMethod":{
    "type":"ideal"
  },
  "returnUrl":"https://your-company.com/checkout?shopperOrder=12xy.."
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Plugins
&lt;/h3&gt;

&lt;p&gt;When using one our plugins to connect to an existing ecommerce, you only need to upgrade the relevant plugin:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adyen Magento v9.6.0+&lt;/li&gt;
&lt;li&gt;Salesforce Commerce Cloud v24.3.0+&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Web Drop-in and Components
&lt;/h3&gt;

&lt;p&gt;Payment integrations that embed the Web Drop-in or Components should upgrade the version of Adyen Web library to v5.65.0 or higher.&lt;/p&gt;

&lt;p&gt;The latest Adyen Web versions will no longer display the list of banks to the shopper, but only the redirect button to perform the payment on the iDEAL page.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Good to know&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Because the bank selection picklist is no longer provided, you can safely remove any custom validation designed for the previous version of Adyen Components. This is especially important if you have hidden the default Component button and implemented a custom one.&lt;br&gt;
Additionally, note that iDEAL optional configurations from previous versions are no longer available and should be removed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftq9d16j46wvr6rlcm7xw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftq9d16j46wvr6rlcm7xw.png" alt="Image description" width="800" height="221"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Check out our sample applications on &lt;a href="https://github.com/adyen-examples" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; to see how to integrate the Web Drop-in and Components, and make a payment with iDEAL.&lt;/p&gt;
&lt;h3&gt;
  
  
  iOS and Android SDKs
&lt;/h3&gt;

&lt;p&gt;We have updated our iOS and Android mobile SDKs: make sure to use a version released after July 2024.&lt;/p&gt;

&lt;p&gt;For iOS, the additional configuration for iDEAL is no longer available and can be removed.&lt;/p&gt;
&lt;h3&gt;
  
  
  Hosted Checkout
&lt;/h3&gt;

&lt;p&gt;No changes are required.&lt;/p&gt;
&lt;h2&gt;
  
  
  Activate iDEAL 2.0 in your Customer Area (Existing integrations)
&lt;/h2&gt;

&lt;p&gt;Log into the Customer Area, go to the "Payment methods" screen and select iDEAL with "iDealSim" acquirer. The next step is to click on "More actions" and choose the option "&lt;strong&gt;Deactivate&lt;/strong&gt;". Then select the other iDEAL payment method and activate it to route the iDEAL payments to the new infrastructure.&lt;/p&gt;

&lt;p&gt;From then on, all iDEAL payments will be performed using the new protocol.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdnncaiceqjq84xm5meto.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdnncaiceqjq84xm5meto.png" alt="Image description" width="800" height="83"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Save the shopper's preferred bank
&lt;/h2&gt;

&lt;p&gt;The updated iDEAL allows storing the shopper's preferred bank, enabling direct redirection to the bank without requiring the selection on the iDEAL page.&lt;br&gt;
Note that this feature is available only with the &lt;a href="https://docs.adyen.com/online-payments/build-your-integration/" rel="noopener noreferrer"&gt;Advanced Flow&lt;/a&gt; integration.&lt;/p&gt;
&lt;h3&gt;
  
  
  Save the shopper's Bank Identification Code (BIC)
&lt;/h3&gt;

&lt;p&gt;Adyen can send the bank information used by the shopper for the iDEAL payment through the payment &lt;a href="https://docs.adyen.com/api-explorer/Webhooks/latest/post/AUTHORISATION" rel="noopener noreferrer"&gt;Authorization Webhook&lt;/a&gt;. To enable this, navigate to the Customer Area and configure the Webhook by enabling the "Include Bank Account Details" option under "Additional Settings."&lt;/p&gt;

&lt;p&gt;After the iDEAL payment is completed, you will receive the Authorization Webhook. Extract the BIC number from the payload and store it for future use. You can then include it in the next iDEAL payments, indicating the BIC of the shopper's preferred bank.&lt;/p&gt;
&lt;h3&gt;
  
  
  Initiate the payment
&lt;/h3&gt;

&lt;p&gt;To initiate an iDEAL payment using the shopper's preferred bank, invoke the Checkout &lt;code&gt;/payments&lt;/code&gt; endpoint from your server-side application, as explained in the Advanced Flow integration. Ensure you set the &lt;code&gt;issuer&lt;/code&gt; field with the previously stored BIC.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "merchantAccount":"YOUR_MERCHANT_ACCOUNT",
  "reference":"YOUR_ORDER_NUMBER",
  "amount":{
    "currency":"EUR",
    "value":1000
  },
  "paymentMethod":{
    "type":"ideal",
    "issuer":"BUNKNL2A"
  },
  "returnUrl":"https://your-company.com/checkout?shopperOrder=12xy.."
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the shopper decides to use a different bank, make a new iDEAL payment without the "issuer" attribute and let the iDEAL page manage the bank selection.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;

&lt;p&gt;The new iDEAL infrastructure provides an updated sandbox for testing. It's extremely important to validate your Adyen integration on our TEST environment to simulate the shopper's flow and test possible payment outcomes.&lt;/p&gt;

&lt;p&gt;When landing on the Bank Selection page, choose the "TESTNL2A" issuer to access the test page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjczaz66tm8pcxm31fb3e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjczaz66tm8pcxm31fb3e.png" alt="Image description" width="800" height="299"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each scenario will trigger a different response that simulates the intended payment flow. Refer to the Adyen Docs &lt;a href="https://docs.adyen.com/payment-methods/ideal/api-only/#test-and-go-live" rel="noopener noreferrer"&gt;Test and Go Live&lt;/a&gt; page to find out what response to expect.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The new iDEAL 2.0 significantly enhances the shopper payment experience. It also streamlines the integration process for developers who want to offer iDEAL, thanks to introducing a centralized iDEAL page, a simplified bank selection process, and iDEAL shopper profiles. To align with these changes, developers are required to &lt;strong&gt;update their existing integrations by April 1st, 2025&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In the Adyen TEST environment, we've made the migration to iDEAL 2.0 straightforward: simply update your existing integrations and test the new iDEAL flows.&lt;/p&gt;

&lt;p&gt;On the LIVE platform, the configuration already supports iDEAL 2.0. Once testing is complete, merchants can seamlessly transition to the new iDEAL without additional changes.&lt;/p&gt;

&lt;p&gt;Check out the &lt;a href="https://docs.adyen.com/payment-methods/ideal/" rel="noopener noreferrer"&gt;iDEAL page&lt;/a&gt; and adopt the new iDEAL to offer shoppers the best experience with the most trusted payment method in the Netherlands.&lt;/p&gt;

</description>
      <category>payments</category>
      <category>testing</category>
    </item>
    <item>
      <title>Optimizing Webhook Integration: a new approach to accept events from the Adyen platform</title>
      <dc:creator>Beppe Catanese</dc:creator>
      <pubDate>Thu, 02 May 2024 08:36:36 +0000</pubDate>
      <link>https://dev.to/adyen/optimizing-webhook-integration-a-new-approach-to-accept-events-from-the-adyen-platform-4hnh</link>
      <guid>https://dev.to/adyen/optimizing-webhook-integration-a-new-approach-to-accept-events-from-the-adyen-platform-4hnh</guid>
      <description>&lt;p&gt;&lt;a href="https://docs.adyen.com/development-resources/webhooks/" rel="noopener noreferrer"&gt;Webhooks&lt;/a&gt; are crucial for getting updates and notifications from the Adyen platform. Those events include confirmation about, e.g., payment authorizations, modifications of existing payments, changes in the account data, or the availability of a new report. For any developers integrating with the Adyen platform, it’s essential to receive, acknowledge, and consume this information stream and ensure their ecommerce or payment is always up to date.&lt;/p&gt;

&lt;p&gt;Our teams also pay significant attention to keep improving the framework, ensuring reliability and performance meet the needs of our merchants and their use cases.&lt;/p&gt;

&lt;p&gt;As part of this simplification effort, &lt;strong&gt;we have introduced a different way&lt;/strong&gt; to acknowledge webhooks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In this article…&lt;/strong&gt; read how to accept webhooks delivered by Adyen, why we have changed the approach, the benefits, and the best practices we recommend for handling webhooks.&lt;/p&gt;




&lt;h2&gt;
  
  
  Accepting webhooks
&lt;/h2&gt;

&lt;p&gt;The Adyen platform requires the webhook handlers to accept explicitly when a webhook is received so that Adyen can mark it as delivered.&lt;/p&gt;

&lt;p&gt;Webhooks that are not accepted end up in the &lt;a href="https://docs.adyen.com/development-resources/webhooks/troubleshoot/#retry-queue" rel="noopener noreferrer"&gt;Retry Queue&lt;/a&gt;: Adyen will progressively try to send those events again at predefined intervals until the applications can eventually consume them.&lt;/p&gt;

&lt;p&gt;The receiving applications &lt;strong&gt;must accept a webhook within 10 seconds&lt;/strong&gt;, implementing one of the two options available.&lt;/p&gt;

&lt;h3&gt;
  
  
  Accept with ‘[accepted]’ response body
&lt;/h3&gt;

&lt;p&gt;All integrations built with Adyen have been accepting webhooks by responding with a response body containing the string ‘[accepted]’. Applications failing to meet these specifications or taking longer than 10 seconds to do so would not successfully accept the webhook, triggering the retry process.&lt;/p&gt;

&lt;p&gt;This approach, implemented for years, has now been revised.&lt;/p&gt;

&lt;h3&gt;
  
  
  Accept with any 2XX HTTP status code
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;new approach&lt;/strong&gt; simplifies the acknowledgment of webhooks.&lt;br&gt;
Whether you have built a custom integration or leveraged a middleware, all webhook handlers must respond only with a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#successful_responses" rel="noopener noreferrer"&gt;successful HTTP status code&lt;/a&gt; (2XX). Developers can choose any 2XX status code; providing a body with the HTTP response is unnecessary.&lt;/p&gt;

&lt;p&gt;Let’s see an example of how you can do this with NodeJS:&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&lt;p&gt;// webhook handler implementation&lt;br&gt;
app.post("/api/webhooks/notifications", async (req, res) =&amp;gt; {&lt;/p&gt;

&lt;p&gt;// Notification Request JSON&lt;br&gt;
  const notificationRequestItems =  req.body.notificationItems&lt;br&gt;
  // fetch first (and only) NotificationRequestItem&lt;br&gt;
  const notification = notificationRequestItems[0].NotificationRequestItem&lt;/p&gt;

&lt;p&gt;// perform basic auth and HMAC validation&lt;br&gt;
  authorize();&lt;/p&gt;

&lt;p&gt;// consume event asynchronously (ie store in queue/db)&lt;br&gt;
   store(notification);&lt;/p&gt;

&lt;p&gt;// accept the event&lt;br&gt;
   res.status(202).send(); // Send a 202 response with an empty body&lt;br&gt;
});&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Benefits and remarks&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;There are multiple reasons behind the change.&lt;/p&gt;

&lt;h3&gt;
  
  
  Align with industry standards
&lt;/h3&gt;

&lt;p&gt;As webhooks have become widely used in so many platforms and applications, there have been &lt;strong&gt;emerging industry standards&lt;/strong&gt; and best practices that we want to align with.&lt;/p&gt;

&lt;p&gt;Accepting webhooks by adopting the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/202" rel="noopener noreferrer"&gt;HTTP status code 202&lt;/a&gt; ("Accepted"), for example, makes clear the semantics of the interaction: the consumer has received the event and will eventually process the content.&lt;/p&gt;

&lt;h3&gt;
  
  
  Better support for middleware
&lt;/h3&gt;

&lt;p&gt;We have seen the adoption of middleware for ingesting webhooks. Although ensuring the reliability and performance of the ingestion of events at scale, they might lack the flexibility of &lt;strong&gt;crafting custom response&lt;/strong&gt; bodies. &lt;/p&gt;

&lt;p&gt;Commercial services may also incur extra charges for delivering text within the response body, as this triggers an increased data transfer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Remove unnecessary ambiguity
&lt;/h3&gt;

&lt;p&gt;Exclusively relying on the content of the response body has presented scenarios where webhooks were successfully acknowledged even when responding with status codes in the 4XX and 5XX ranges, conventionally used to report an error.&lt;/p&gt;

&lt;p&gt;This has resulted in &lt;strong&gt;false negatives&lt;/strong&gt;, which not only affect the accuracy of performance metrics but also require additional effort to verify those cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  New webhooks
&lt;/h2&gt;

&lt;p&gt;Every newly created webhook on the Adyen platform will work with the &lt;strong&gt;2XX HTTP status code&lt;/strong&gt; option. Developers should understand how the new approach works and make sure that their implementation, either a bespoke webhook handler or the middleware, supports it by returning a successful HTTP response status code.&lt;/p&gt;

&lt;p&gt;If the 2XX HTTP status code option isn't compatible with your integration, reach out to the Adyen Support team, and we'll assist you in finding a suitable solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Migrating existing webhooks
&lt;/h2&gt;

&lt;p&gt;All existing webhooks, however, are not automatically updated and keep functioning as before, relying on the &lt;strong&gt;'[accepted]' response body&lt;/strong&gt;. The migration is, however, straightforward and can be performed either in the Customer Area or programmatically using the Management API.&lt;/p&gt;

&lt;p&gt;Start planning the migration of your existing webhooks now and don't miss out on the advantages highlighted above.&lt;/p&gt;

&lt;h3&gt;
  
  
  Update Webhook configuration in the CA
&lt;/h3&gt;

&lt;p&gt;In the Customer Area, go to the "Developers-&amp;gt;Webhooks" page and choose the webhook that is ready to be migrated. As you edit the webhook, in the "Server configuration" section, you will see the picklist "Accept webhook."&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F99rapyll317f6snb9s9s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F99rapyll317f6snb9s9s.png" alt="Webhook configuration screen"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The picklist provides two choices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;With '[accepted]'&lt;/li&gt;
&lt;li&gt;With HTTP 2XX&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Change the preferred approach to "With HTTP 2XX" and confirm the choice. Note that &lt;strong&gt;this change is permanent&lt;/strong&gt; and can't be reverted.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwtb5actur4qyzzvme97q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwtb5actur4qyzzvme97q.png" alt="Confirmation popup"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Update Webhook configuration using the Management API
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://docs.adyen.com/api-explorer/Management" rel="noopener noreferrer"&gt;Adyen Management API&lt;/a&gt; allows to manage account and payment configuration programmatically. The API enables developers to perform and automate administrative tasks, configure settings and test webhooks.&lt;/p&gt;

&lt;p&gt;In order to update the webhook configuration and change the 'accept' mechanism you can perform a PATCH request setting the &lt;code&gt;acceptHttp200Confirmation&lt;/code&gt; property:&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&lt;h1&gt;
  
  
  example on TEST environment
&lt;/h1&gt;

&lt;p&gt;PATCH &lt;a href="https://management-test.adyen.com/v3/merchants/%7BmerchantId%7D/webhooks/%7BwebhookId%7D" rel="noopener noreferrer"&gt;https://management-test.adyen.com/v3/merchants/{merchantId}/webhooks/{webhookId}&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;{&lt;br&gt;
   "additionalSettings": {&lt;br&gt;
      "properties": {&lt;br&gt;
          "acceptHttp200Confirmation": "true"&lt;br&gt;
      }&lt;br&gt;
   }&lt;br&gt;
}&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Refactor webhook handlers&lt;br&gt;
&lt;/h3&gt;

&lt;p&gt;Developers should also refactor the applications consuming the webhook events: provide a successful response, preferably with the HTTP status code 202, and ensure the response body is empty.&lt;/p&gt;

&lt;p&gt;When a middleware processes the webhooks, the configuration should also be updated to adopt the new approach.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best practices
&lt;/h2&gt;

&lt;p&gt;Consuming the webhooks delivered by the Adyen platform requires understanding and adopting best practices. Let's summarize them again:&lt;/p&gt;

&lt;h3&gt;
  
  
  Respond with 202 and empty body
&lt;/h3&gt;

&lt;p&gt;Acknowledge the webhook with an &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/202" rel="noopener noreferrer"&gt;HTTP status code 202&lt;/a&gt; ("Accepted") to indicate that the request has been successfully received, but the processing may not be complete.&lt;/p&gt;

&lt;p&gt;Any successful 2XX HTTP status codes can be used. However, the recommendation is to use 202.&lt;/p&gt;

&lt;p&gt;Returning an &lt;strong&gt;empty response body&lt;/strong&gt; is also a good practice, as it keeps the response lightweight and avoids unnecessary data transfer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Respond within 10 seconds
&lt;/h3&gt;

&lt;p&gt;The webhook handler must acknowledge the webhook within a 10-second window; failure to do so will prompt Adyen to retry sending the event later.&lt;/p&gt;

&lt;p&gt;There are a variety of reasons that can make the acceptance of the webhook longer than for 10 seconds. The affecting factors typically are the application's architecture, the complexity of the integration process, and the dependency on other systems or components.&lt;/p&gt;

&lt;p&gt;Consider therefore adopting an asynchronous approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Store the event in a queue or database.&lt;/li&gt;
&lt;li&gt;Acknowledge the webhook with a response status code 202.&lt;/li&gt;
&lt;li&gt;Subsequently, process the event asynchronously.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This strategy allows for more efficient handling of events, ensuring smoother integration and a predictable outcome.&lt;/p&gt;

&lt;h3&gt;
  
  
  Security (basic auth and HMAC)
&lt;/h3&gt;

&lt;p&gt;Implement the required &lt;a href="https://docs.adyen.com/development-resources/webhooks/best-practices/#security" rel="noopener noreferrer"&gt;security measures&lt;/a&gt; &lt;strong&gt;before acknowledging a webhook&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Enforce Basic Authentication (username and password) to ensure that only authorized parties can access the webhook endpoint.&lt;/p&gt;

&lt;p&gt;Integrate Hash-based Message Authentication Code (HMAC) validation to verify the integrity and authenticity of the webhook payload before consuming it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Monitor event logs
&lt;/h3&gt;

&lt;p&gt;Use the &lt;a href="https://www.adyen.com/knowledge-hub/adyen-developer-dashboard" rel="noopener noreferrer"&gt;Developer Dashboard&lt;/a&gt; to monitor the health of your integration. The dashboard provides insights into the webhooks activity, aggregating valuable metrics like success rate and most frequent errors.&lt;/p&gt;

&lt;p&gt;When troubleshooting becomes necessary, dive into the Event Logs to inspect the events' status, payload, and response time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fddyiu3fcfpz1b2ykune9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fddyiu3fcfpz1b2ykune9.png" alt="Monitor webhook events"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The article outlines the new approach for accepting Adyen webhooks. We've compared the different methods, outlined the migration steps, and explained the rationale behind adopting any 2XX HTTP status code for webhook acknowledgment.&lt;/p&gt;

&lt;p&gt;Now it's time to plan your migration! Follow the recommended best practices, and don't hesitate to reach out if we can help you in any way with the transition.&lt;/p&gt;

</description>
      <category>webhooks</category>
      <category>developer</category>
    </item>
    <item>
      <title>Developer’s Guide: working with webhooks on your localhost</title>
      <dc:creator>Beppe Catanese</dc:creator>
      <pubDate>Wed, 13 Dec 2023 15:57:46 +0000</pubDate>
      <link>https://dev.to/adyen/developers-guide-working-with-webhooks-on-your-localhost-3dgg</link>
      <guid>https://dev.to/adyen/developers-guide-working-with-webhooks-on-your-localhost-3dgg</guid>
      <description>&lt;p&gt;In this &lt;strong&gt;Developer Guide&lt;/strong&gt; you will learn how to consume and test webhooks in your local development environment. You will also understand the different advantages and disadvantages associated with the options we recommend.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Webhooks are an essential feature of the Adyen platform. They deliver events like payment outcome, new chargebacks, availability of a report, updates on merchant onboarding, and so on, and therefore it is important to ensure they can be received, consumed and tested during the development of your specific Adyen integration.&lt;/p&gt;

&lt;p&gt;While inspecting the content of a webhook payload can be useful (for example by forwarding the webhook to tools like &lt;a href="https://webhook.site/" rel="noopener noreferrer"&gt;webhook.site&lt;/a&gt;), developers also require the capability to receive incoming webhooks directly in the application running on their laptop. It is a matter of more effective testing that verifies the correct processing on the incoming events and the associated workflow that follows.&lt;/p&gt;

&lt;p&gt;During the development of the application there are many changes to implement and many assumptions to confirm. The flexibility of working in the local environment is therefore crucial for both developer’s experience and productivity.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8s53e0y67i4fl5l5ej8y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8s53e0y67i4fl5l5ej8y.png" alt="Consuming webhook diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This developer guide explores the following options:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Adyen Postman Collection for webhooks&lt;/li&gt;
&lt;li&gt;Tunneling software&lt;/li&gt;
&lt;li&gt;Using a Cloud Development Environment (CDE)&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Postman Collections
&lt;/h2&gt;

&lt;p&gt;Visit the AdyenDev Postman space and fork the &lt;a href="https://www.postman.com/beppecatanese/workspace/working-with-adyen/collection/8426282-f65935ea-8a87-4883-9f58-0eeac69e185a?action=share&amp;amp;creator=8426282" rel="noopener noreferrer"&gt;Adyen Webhooks&lt;/a&gt; collection. It includes several examples of the different types of webhooks.&lt;br&gt;
Each example provides the JSON payload with the event code and any other applicable field.&lt;br&gt;
The HMAC signature is calculated ‘on-the-fly’ and included in the HTTP request.&lt;/p&gt;

&lt;h2&gt;
  
  
  HowTo
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Fork the collection&lt;/li&gt;
&lt;li&gt;Configure the environment variables:&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Webhook url (default &lt;code&gt;http://localhost:8080&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;HMAC key (same as configured in your application)&lt;/li&gt;
&lt;li&gt;Additional settings depending on your integration (Merchant Account for payments, Balance Platform Id for Platforms, etc..)&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Send the requests to your application&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  When to use it
&lt;/h2&gt;

&lt;p&gt;This is highly convenient in the initial development phase of the integration: developers want to quickly test the processing of the different JSON payloads that will be delivered by Adyen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt; ✅: easy to use with many different examples, flexible (can edit JSON payloads as needed), no need to expose a public endpoint&lt;br&gt;
&lt;strong&gt;Cons&lt;/strong&gt; ❌: not a real integration with Adyen backend&lt;/p&gt;

&lt;h2&gt;
  
  
  Tunneling Software
&lt;/h2&gt;

&lt;p&gt;Tunneling software tools such as ngrok and Microsoft Dev Tunnels can be used to expose your local environment to the internet. These tools essentially create a temporary connection between your local machine and a public endpoint, hosted by the company providing the tool.&lt;/p&gt;

&lt;p&gt;By establishing these tunnels you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Allow remote testing and collaboration&lt;/li&gt;
&lt;li&gt;Run demos using your local application&lt;/li&gt;
&lt;li&gt;Consume webhooks originated by a platform or third-party application, making webhook testing a lot simpler.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Below you can see how to test the webhook using ngrok, however the same approach applies when using a similar tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  HowTo with ngrok
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Install ngrok&lt;/li&gt;
&lt;li&gt;Start ngrok &lt;code&gt;ngrok http 8080&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Copy the ngrok generated URL for https&lt;/li&gt;
&lt;li&gt;Create/update Adyen webhook with the ngrok URL&lt;/li&gt;
&lt;li&gt;Ensure the HMAC key for the webhook is used by the application on your localhost&lt;/li&gt;
&lt;li&gt;Trigger a webhook: perform a payment or use Test Webhook function available in the Customer Area
&lt;strong&gt;Note&lt;/strong&gt;: when restarting ngrok a new URL is generated, therefore the Adyen webhook URL must also be updated.
When to use it
This option can be used throughout the development and testing of the integration.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt; ✅: receive webhooks sent by Adyen platform&lt;br&gt;
&lt;strong&gt;Cons&lt;/strong&gt; ❌: requires exposing localhost to the Internet&lt;/p&gt;

&lt;h2&gt;
  
  
  Cloud Development Environment (CDE)
&lt;/h2&gt;

&lt;p&gt;A Cloud Development Environment (CDE) is an online development environment that allows developers to write, test, and deploy code from a web browser. It provides developers with the necessary tools to build and test software, without setting up and maintaining a local infrastructure (tech stack and all dependencies).&lt;br&gt;
As the development environment is hosted in a public cloud-based platform, it provides a convenient way to test webhooks.&lt;/p&gt;

&lt;p&gt;There are several CDEs (Gitpod, GitHub Codespaces, Codeanywhere, etc..). Choose your preferred tool, deploy your application source code and make it reachable by Adyen.&lt;/p&gt;

&lt;p&gt;Below you can see how to test the webhook using Gitpod (all Adyen sample applications can be &lt;a href="https://www.adyen.com/blog/-Run-any-of-our-samples-under-a-minute-using-GitPod" rel="noopener noreferrer"&gt;deployed on Gitpod&lt;/a&gt;), however a similar approach applies when using a different CDE.&lt;/p&gt;

&lt;h2&gt;
  
  
  HowTo on Gitpod
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/adyen-examples/.github/blob/main/pages/gitpod-get-started.md" rel="noopener noreferrer"&gt;Configure&lt;/a&gt; the necessary settings (API key, merchant account, HMAC key) as Gitpod environment variables&lt;/li&gt;
&lt;li&gt;Deploy the application on Gitpod&lt;/li&gt;
&lt;li&gt;Copy the Gitpod generated URL (&lt;strong&gt;note&lt;/strong&gt;: not the Gitpod workspace URL but the URL of the web application running on Gitpod)&lt;/li&gt;
&lt;li&gt;Create a webhook using the generated Gitpod URL &lt;strong&gt;as well as&lt;/strong&gt; the path to access the webhook handler (ie &lt;code&gt;https://abcd1234.gitpod.io/api/webhooks/notifications&lt;/code&gt; by default)&lt;/li&gt;
&lt;li&gt;Generate the HMAC key for the webhook and copy it&lt;/li&gt;
&lt;li&gt;In the Gitpod terminal stop the application&lt;/li&gt;
&lt;li&gt;Set the HMAC KEY as env variable
&lt;code&gt;gp env ADYEN_HMAC_KEY=ASDEW##############&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Update the environment variables for the terminal session
&lt;code&gt;eval $(gp env -e)&lt;/code&gt;
Restart the application in the terminal (or recreate the Gitpod workpace)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  When to use it
&lt;/h2&gt;

&lt;p&gt;This approach might be suitable during testing and validation phases, later in the development lifecycle.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt; ✅: receive webhooks sent by Adyen platform, source code can be tested and modified directly on Gitpod&lt;br&gt;
&lt;strong&gt;Cons&lt;/strong&gt; ❌: requires using cloud service, it must follow closely the “HowTo” steps (for example the Gitpod URL must be generated before configuring the webhook)&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Webhooks are a critical component of Adyen’s platform, and testing them effectively during development is essential.&lt;/p&gt;

&lt;p&gt;The ability to receive and process webhooks locally greatly enhances developer productivity. We’ve explored three options, each with its own advantages and limitations: Adyen Postman Collections for quick testing, tunneling software for ongoing development, and Gitpod for more comprehensive testing.&lt;/p&gt;

&lt;p&gt;Choose the approach that fits best with your needs, requirements and development methodology, and reach out to let us know what works for you and how we can help you further.&lt;/p&gt;

</description>
      <category>webhooks</category>
      <category>testing</category>
    </item>
    <item>
      <title>Simplify payment testing with the Adyen Test Cards browser extension</title>
      <dc:creator>Beppe Catanese</dc:creator>
      <pubDate>Mon, 27 Nov 2023 13:50:46 +0000</pubDate>
      <link>https://dev.to/adyen/simplify-payment-testing-with-the-adyen-test-cards-browser-extension-1jnf</link>
      <guid>https://dev.to/adyen/simplify-payment-testing-with-the-adyen-test-cards-browser-extension-1jnf</guid>
      <description>&lt;p&gt;Testing payment flows is a challenging and time-consuming process, involving multiple steps, different payment methods, and manually entering data such as card details. &lt;/p&gt;

&lt;p&gt;We’ve built the &lt;a href="https://chrome.google.com/webstore/detail/adyen-test-cards/icllkfleeahmemjgoibajcmeoehkeoag" rel="noopener noreferrer"&gt;Adyen Test Card Chrome extension&lt;/a&gt; to solve this challenge, designed to simplify the testing process. By adding the extension directly to your browser, you can copy the card details to the clipboard or prefill the Adyen web Drop-in with a single click.&lt;/p&gt;

&lt;p&gt;In this article, you’ll discover the benefits of the Adyen Test Cards extension, how we built it, and what it means in terms of security.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbr2qoez0g19wy2ile1mx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbr2qoez0g19wy2ile1mx.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Meet the Adyen Test Card extension
&lt;/h2&gt;

&lt;p&gt;Given the high number of returning visitors to the Adyen Test Cards page, we saw an opportunity to assist developers by streamlining the testing process. This is why we built the extension: to simplify the testing of payment flows for developers.&lt;/p&gt;

&lt;p&gt;Designed to facilitate Adyen Checkout integration testing, the Adyen Test Card extension reduces the time and effort spent on payment flow testing. It brings the test card numbers you need directly into your browser and simplifies the testing process for developers. It removes the burden of going back and forth between different pages to collect the card data you need to test. &lt;/p&gt;

&lt;p&gt;To make the design as simple as possible, we used &lt;a href="https://developer.chrome.com/docs/extensions/reference/sidePanel/" rel="noopener noreferrer"&gt;chrome.sidePanel&lt;/a&gt;, a pre-built side panel that doesn't overlap with the tab's content and that can be easily resized or closed. The extension builds its UI and logic within the side panel, creating features that deliver user experiences that nicely blend with the &lt;a href="https://docs.adyen.com/online-payments/build-your-integration/" rel="noopener noreferrer"&gt;Adyen Drop-in&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make testing easy
&lt;/h2&gt;

&lt;p&gt;There are multiple features that contribute to enhancing the testing experience for developers. The most significant ones are:&lt;/p&gt;

&lt;h3&gt;
  
  
  One-click prefill
&lt;/h3&gt;

&lt;p&gt;Testing checkout integrations previously meant spending time searching for the right card, copying (from the Adyen Test Cards page or your local file) and pasting it in the right field, then repeating the same process for the expiry date and CVC data.&lt;/p&gt;

&lt;p&gt;Now, the one-click prefill feature of the Adyen Web Drop-in does it for you. All you need to do is find the card information you need, select, and paste it in the right field.&lt;/p&gt;

&lt;p&gt;There is also a copy-to-clipboard feature in case the card number needs to be used with applications that don't use the Adyen Web Drop-in.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqkwndfh69iyp2043cfds.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqkwndfh69iyp2043cfds.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Pin your favorites
&lt;/h3&gt;

&lt;p&gt;You can use the ‘’Add to Favorites’’ option to speed up the testing process further. This feature makes it possible to pin frequently used cards to the top of the extension panel for quick, convenient access.&lt;/p&gt;

&lt;h3&gt;
  
  
  Different payment methods
&lt;/h3&gt;

&lt;p&gt;Next to the different credit and debit cards, the extension also supports gift cards and IBANs. You can also &lt;a href="https://github.com/adyen-examples/adyen-testcards-extension/issues" rel="noopener noreferrer"&gt;submit a request&lt;/a&gt; to add other payment methods or card numbers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;Installing the extension is easy and can be done in the Chrome Web Store by searching for the Adyen Test Cards extension. All you need to do is click the “Add to Chrome” button. &lt;/p&gt;

&lt;p&gt;Watch the video on our &lt;a href="https://www.youtube.com/watch?v=INDxpfjnAnE" rel="noopener noreferrer"&gt;AdyenDev YouTube&lt;/a&gt; channel for a detailed guide on installing and using the extension.&lt;/p&gt;

&lt;h3&gt;
  
  
  Security
&lt;/h3&gt;

&lt;p&gt;The extension is designed with security as a key consideration, promoting best practices in payment security by discouraging using real cards for testing.&lt;/p&gt;

&lt;p&gt;The Adyen Test Cards extension only copies (using Javascript) the selected card details into the checkout form. No other data or fields are read or changed. The &lt;a href="https://github.com/adyen-examples/adyen-testcards-extension" rel="noopener noreferrer"&gt;source code&lt;/a&gt; is Open-Source, and the extension has no telemetry.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build and Testing
&lt;/h2&gt;

&lt;p&gt;Developing the Chrome extension is an easy process. You first need to create a manifest file in a JSON format that defines the extension's metadata, permissions, and assets. &lt;/p&gt;

&lt;p&gt;In the manifest file, you can find the permissions required by the extension:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"sidePanel": Gives you access to the Chrome side-panel component.&lt;/li&gt;
&lt;li&gt;"scripting": Allows you to execute the script to modify the page's content, specifically by populating the card details into their corresponding fields.&lt;/li&gt;
&lt;li&gt;"activeTab": Permits you to only interact with the active tab.&lt;/li&gt;
&lt;li&gt;"storage": Lets you save the list of favorite cards in the local storage.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then, you need to develop the source code that contains several elements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JavaScript and HTML code: Implements the functional behavior and rendering of the user interface.&lt;/li&gt;
&lt;li&gt;Content script: Javascript code that manages the extension's interaction with the tab's content.&lt;/li&gt;
&lt;li&gt;Service worker: Background script that manages the extension's state.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Chrome extension is loaded directly from the source code during the development, leveraging the Chrome Developer mode and making code modifications immediately visible. This, combined with using Chrome DevTools, makes debugging and troubleshooting a lot easier.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw112dbk2o0kxgagrferm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw112dbk2o0kxgagrferm.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Taking testing to the next level
&lt;/h2&gt;

&lt;p&gt;The Adyen Test Cards Chrome extension helps developers perform more convenient, secure, and effective testing. By quickly accessing a list of test card data without manually entering the information, you can speed up the testing process and spend more time developing the integration without wasting time and energy on repetitive tasks.&lt;/p&gt;

&lt;p&gt;Adyen Test Cards Data mimics real transactions, allowing you to test different scenarios and outcomes. By eliminating the manual entry of the payment method details, the extension reduces the possibility of error during testing, resulting in more robust integrations.&lt;/p&gt;

&lt;p&gt;We’re proud to support developers during their integration journey with the Adyen platform. Providing effective tools removes friction, boosts productivity, and ultimately contributes to a better and more robust integration.&lt;/p&gt;

&lt;p&gt;Get started by installing the Adyen Test Card extension from the &lt;a href="https://chrome.google.com/webstore/detail/adyen-test-cards/icllkfleeahmemjgoibajcmeoehkeoag" rel="noopener noreferrer"&gt;Chrome Store&lt;/a&gt; or downloading it from the source code on &lt;a href="https://github.com/adyen-examples/adyen-testcards-extension" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;. Give us your feedback, and let us know what you think should be included in the next releases.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>payments</category>
      <category>chrome</category>
      <category>extensions</category>
    </item>
    <item>
      <title>Adyen for Platforms onboarding made easy</title>
      <dc:creator>Beppe Catanese</dc:creator>
      <pubDate>Tue, 15 Aug 2023 09:30:34 +0000</pubDate>
      <link>https://dev.to/adyen/adyen-for-platforms-onboarding-made-easy-4ak4</link>
      <guid>https://dev.to/adyen/adyen-for-platforms-onboarding-made-easy-4ak4</guid>
      <description>&lt;p&gt;&lt;a href="https://www.adyen.com/platform-payments" rel="noopener noreferrer"&gt;Adyen for Platforms&lt;/a&gt; is our end-to-end solution designed for marketplaces and other platform models looking to set up a scalable, feature-rich platform for their merchants and end users. Amongst its vast array of features, one stands out: the Hosted Onboarding solution.&lt;/p&gt;

&lt;p&gt;Hosted Onboarding simplifies the process for both the platform and its merchants. It reduces the complexities that come with complying to regulatory requirements and enables sellers to quickly get onboarded and accept payments.&lt;/p&gt;

&lt;p&gt;While Hosted Onboarding offers an out-of-the box intuitive user interface, customizable themes and configuration, and tailored onboarding flows, it's important to understand there is some &lt;strong&gt;development work&lt;/strong&gt; required to ensure a seamless integration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In this article…&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;...discover the key benefits and functionalities of Adyen's Hosted Onboarding solution. Design an optimal flow between the platform and the Hosted Onboarding solution. Learn what developers need to consider, implement and optimize to deliver a frictionless and secure integration.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Onboarding flow
&lt;/h2&gt;

&lt;p&gt;The onboarding of new sellers on the platform involves multiple steps and the process can vary significantly. The main factors that determine this process are the platform type (marketplace or platform setup), its location (countries), and the type of end merchants (individuals, organizations, sole proprietorships). Moreover when making &lt;a href="https://docs.adyen.com/marketplaces-and-platforms#financial-products" rel="noopener noreferrer"&gt;financial products&lt;/a&gt; available, additional regulations may apply.&lt;/p&gt;

&lt;p&gt;You can find a comprehensive guide of the verification process on Adyen Docs. Now we are going to focus on a specific example: get ready to onboard the restaurant Healthy Tacos for a US based platform in the food and beverage industry.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcqvjgtdt9f2jhoismiwj.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcqvjgtdt9f2jhoismiwj.jpg" alt="Image description" width="800" height="587"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this context the onboarding journey of Healthy Tacos looks like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a profile&lt;/li&gt;
&lt;li&gt;Fill in the required information&lt;/li&gt;
&lt;li&gt;Provide the necessary documents (if applicable)&lt;/li&gt;
&lt;li&gt;The Healthy Tacos account is verified and can begin accepting transactions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2oozo7njwlfssuxko7ib.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2oozo7njwlfssuxko7ib.jpg" alt="Image description" width="800" height="504"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The diagram helps us visualize the journey on a mobile. It also distinguishes the ownership of each phase (Platform vs Adyen).&lt;/p&gt;

&lt;p&gt;The “&lt;strong&gt;Setup&lt;/strong&gt;” is the responsibility of the platform and consists of the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create the “Legal Entity”&lt;/li&gt;
&lt;li&gt;Create the “Account Holder”&lt;/li&gt;
&lt;li&gt;Create the onboarding link&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Those steps are to be implemented by the platform developers, integrating the Adyen APIs, before merchants can be involved.&lt;/p&gt;

&lt;p&gt;Once the account is set up the “&lt;strong&gt;Onboarding&lt;/strong&gt;” journey begins. This is taken care of by Adyen.&lt;/p&gt;

&lt;p&gt;Finally the account is “&lt;strong&gt;Ready&lt;/strong&gt;”. The platform must listen and process the incoming webhooks to confirm the onboarding status.&lt;/p&gt;

&lt;p&gt;Let’s start the journey and look at what each step entails and what, as a developer, you need to design and implement.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a new platform
&lt;/h2&gt;

&lt;p&gt;Check out the Get started guide to learn how to register for a new account as well as understanding all requirements and preliminary decisions to consider.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites: API key and webhooks
&lt;/h3&gt;

&lt;p&gt;Before starting the integration process, few prerequisites must be fulfilled.&lt;/p&gt;

&lt;h3&gt;
  
  
  API access
&lt;/h3&gt;

&lt;p&gt;Create the API credential (and API key) for the &lt;a href="https://docs.adyen.com/api-explorer/legalentity/latest/overview" rel="noopener noreferrer"&gt;Legal Entity Management API&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Create the API credential (and API key) for the &lt;a href="https://docs.adyen.com/api-explorer/balanceplatform/" rel="noopener noreferrer"&gt;Balance Platform Configuration API&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;You will be using both APIs to create the information required to kick off the onboarding.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tip&lt;/strong&gt;: Check out the AdyenDev Postman space to access the Postman collections with predefined requests and JSON payloads for all Adyen APIs, including the platform and onboarding endpoints.&lt;/p&gt;

&lt;h3&gt;
  
  
  User role
&lt;/h3&gt;

&lt;p&gt;Ensure the “Manage hosted onboarding themes” role has been assigned to your user account in the Balance Platform &lt;a href="https://developers.adyen.com/#customerAreaLogin" rel="noopener noreferrer"&gt;Customer Area&lt;/a&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  Webhooks
&lt;/h3&gt;

&lt;p&gt;Set up the &lt;a href="https://docs.adyen.com/marketplaces-and-platforms/webhooks" rel="noopener noreferrer"&gt;webhooks&lt;/a&gt; to receive real-time updates from the verification process.&lt;/p&gt;

&lt;p&gt;Webhooks play an essential role in ensuring an efficient onboarding process. You need to set up the “Configuration” webhook to always stay informed about any changes. For example, when the onboarding is completed or in case additional details must be provided.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5fv7zlwsl3zlfkkfau5q.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5fv7zlwsl3zlfkkfau5q.jpg" alt="Image description" width="800" height="498"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Additionally, it is crucial to have the webhook in place &lt;strong&gt;after the seller is onboarded&lt;/strong&gt;. For instance, if a new (financial) product is introduced, which mandates additional documentation, or an expired passport must be replaced, the webhook will be the mechanism to notify you about such events.&lt;/p&gt;

&lt;h2&gt;
  
  
  Seller account setup
&lt;/h2&gt;

&lt;p&gt;Let’s tackle the first step: the account creation of the seller that must be onboarded onto the platform. This falls under the responsibility of the platform and therefore involves some development effort.&lt;/p&gt;

&lt;p&gt;Each entity operating on the platform must have its own “Legal Entity”. This can be created using the Legal Entity Management API.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST /legalEntities

{
   "type":"organization",
   "organization":{
      "legalName":"Healthy Tacos",
      "registeredAddress":{
         "country":"US"
      }
   }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;which will return, if successful, the identifier of the newly created “Legal Entity” (ie LE000123).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tip&lt;/strong&gt;: You should consider adopting the Adyen Libraries for a robust and scalable integration. Avoid writing the REST API integration code. Instead work with your preferred tech stack and get access to pre-built functions, helpers, error handling and security features.&lt;/p&gt;

&lt;p&gt;The next step is the creation of the “AccountHolder” linked to the “Legal Entity”. This step will be accomplished using the Balance Platform Configuration API.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST /accountHolders

{
  "balancePlatform": "MY_PLATFORM_BP",
  "description":"Healthy Tacos account holder",
  "legalEntityId":"LE000123"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The seller account is now created and we are almost ready to start the onboarding. The last task is the creation of the Hosted Onboarding link.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hosted Onboarding link
&lt;/h2&gt;

&lt;p&gt;The Hosted Onboarding link is the URL that is provided to merchants who are invited to onboard onto the platform. It should be embedded into a page within your platform, for example in their “User Account” page.&lt;/p&gt;

&lt;p&gt;It is crucial to note that the link &lt;strong&gt;expires after 4 minutes&lt;/strong&gt;, therefore it should not be generated and stored to be used later. Instead, you should create the link on-demand by utilizing the LEM API's '/onboardingLinks' endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST /legalEntities/{{id}}/onboardingLinks/

{
 “themeId” : “YOUR_THEME_ID”,
 "redirectUrl" : "https://example.com/",
 "locale" : "en-US"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;themeId&lt;/strong&gt; allows you to specify a custom theme for the Hosted Onboarding experience. You can create, view and update customized onboarding themes in the Balance Platform Custom Area. A theme can have its own background image, colors and logo. The links to the Support, FAQ and Privacy pages can also be defined.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;redirectUrl&lt;/strong&gt; property specifies the page where merchants are redirected upon completing the onboarding process. Don’t forget that they are sent to the Adyen hosted application, therefore it is very important to redirect them back to your platform at the end of the onboarding flow.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;locale&lt;/strong&gt; property can be utilized to specify the desired language. By default, the application will use the language set in the user's browser. However, you have the option to configure the language by passing the corresponding locale, enabling customization of the link based on the market and even combining it with different themes.&lt;/p&gt;

&lt;p&gt;Additional settings can be configured, when creating the link, to control further what the merchants can change during the onboarding.&lt;/p&gt;

&lt;h2&gt;
  
  
  A use case
&lt;/h2&gt;

&lt;p&gt;When the platform wants to operate in Europe, it could decide to employ the language for each country (IT for Italy, NL for the Netherlands, etc.) while sharing the same custom theme (logo and branding). The platform, passing the additional settings, can also remove the possibility to edit the type and country of the “Legal Entity” which has been already set during the account setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Onboard your users
&lt;/h2&gt;

&lt;p&gt;Once the seller account is set up and the custom theme is defined, it’s finally onboarding time!&lt;/p&gt;

&lt;p&gt;A potential scenario involves sending an email to the sellers to access your platform, where they will find a newly generated Hosted Onboarding link. As they access the Onboarding screens, Adyen takes on the responsibility of collecting all necessary information and relevant documentation.&lt;/p&gt;

&lt;h3&gt;
  
  
  The happy flow
&lt;/h3&gt;

&lt;p&gt;The Hosted Onboarding application will guide the merchants through a few screens:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enter company details and decision makers&lt;/li&gt;
&lt;li&gt;Upload or scan legitimate ID like passport or driving license&lt;/li&gt;
&lt;li&gt;Verify the bank details&lt;/li&gt;
&lt;li&gt;Sign the service agreement&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The application is mobile-friendly and the real-time verification functionalities provide the best experience. Users can take pictures of an ID document and (where supported) choose the &lt;a href="https://docs.adyen.com/marketplaces-and-platforms/collect-verification-details/hosted#instant-bank-account-verification" rel="noopener noreferrer"&gt;instant bank account verification&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To see an example of the entire hosted onboarding flow, you can watch our videos &lt;a href="https://docs.adyen.com/marketplaces-and-platforms/collect-verification-details/hosted?tab=org-required-info_1" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In most cases the onboarding process completes smoothly. You will receive a webhook to confirm the seller is onboarded and they can start accepting payments.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk43ymmgxnfik79vlwfxb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk43ymmgxnfik79vlwfxb.jpg" alt="Image description" width="486" height="864"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Dealing with verification errors
&lt;/h2&gt;

&lt;p&gt;In some cases, it may not be possible to verify all the details provided by users. Or they might be required to make modifications to the information they have submitted as well as include additional data.&lt;/p&gt;

&lt;p&gt;The range of issues can vary, from verification errors caused by incomplete information to the rejection if a risk of fraudulent activity is detected.&lt;/p&gt;

&lt;p&gt;When the verification is unsuccessful and the capability is denied, the webhook delivers all the information necessary to deal with it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“allowed” false indicates the “Account Holder” cannot operate&lt;/li&gt;
&lt;li&gt;“verificationStatus” can be invalid or rejected&lt;/li&gt;
&lt;li&gt;“problems” listing the details of what went wrong&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The payload of a webhook notifying that there is missing information (i.e. bank statement) looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "data": {
    "accountHolder": {
      "capabilities": {
        "sendToTransferInstrument": {
          "allowed": "false",
          "enabled": "true",
          "problems": [
            {
              "entity": {
                "id": "LE00000000000000000000001",
                "type": "LegalEntity"
              },
              "verificationErrors": [
                {
                  "code": "2_8037",
                  "message": "bankStatement was missing.",
                  "remediatingActions": [
                    {
                      "code": "1_703",
                      "message": "Upload a bank statement"
                    }
                  ],
                  "type": "dataMissing"
                }
              ]
            }
          ],
          "requested": "true",
          "verificationStatus": "invalid"
        }
      },
      "description": "Test Account holder",
      "reference": "YOUR_INTERNAL_IDENTIFIER",
      "id": "AH00000000000000000000001",
      "legalEntityId": "LE00000000000000000000001",
      "status": "Active"
    },
    "balancePlatform": "YOUR_BALANCE_PLATFORM"
  },
  "environment": "test",
  "type": "balancePlatform.accountHolder.updated"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should read and process the detailed information about the error(s) and rely on the “remediatingActions” to plan the next step.&lt;/p&gt;

&lt;p&gt;Adyen uses &lt;a href="https://docs.adyen.com/marketplaces-and-platforms/kyc-verification-codes" rel="noopener noreferrer"&gt;specific verification codes&lt;/a&gt; to provide the most accurate feedback. Codes are unique and never change; this should allow you to create workflows that trigger the course of action based on the verification status and corresponding code.&lt;/p&gt;

&lt;p&gt;In the majority of cases, users will be asked to provide additional information to successfully complete the onboarding. To facilitate this, make sure to notify your users that they need to &lt;strong&gt;come back to the platform&lt;/strong&gt; and continue onboarding via a newly generated onboarding link. This link will redirect the users to the application where they can provide what it is missing or incorrect.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu2ieuownugilrmi16vfx.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu2ieuownugilrmi16vfx.jpg" alt="Image description" width="486" height="864"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Best practices for developers
&lt;/h2&gt;

&lt;p&gt;Several aspects are very important to developers. Let’s recap the essential best practices to follow for creating a seamless onboarding process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Webhook setup
&lt;/h3&gt;

&lt;p&gt;The setup of the webhook is crucial. Make sure your application endpoint can receive and correctly handle the events that Adyen will send &lt;strong&gt;during and after&lt;/strong&gt; the onboarding. Implement the necessary security measures (Basic Authentication and HMAC validation).&lt;/p&gt;

&lt;p&gt;To learn more about webhook processing and best practices, including security, error handling, and event retries, check out the "&lt;a href="https://www.adyen.com/blog/consuming-webhooks" rel="noopener noreferrer"&gt;Consuming webhooks&lt;/a&gt;" article on the Adyen tech blog.&lt;/p&gt;

&lt;h3&gt;
  
  
  Custom theme
&lt;/h3&gt;

&lt;p&gt;We strongly advise &lt;strong&gt;creating a custom theme&lt;/strong&gt; that seamlessly integrates with the design and style of your platform. This gives the users the feeling they are always operating within your platform, enhancing the overall user experience.&lt;/p&gt;

&lt;p&gt;By reusing your platform's logo, images, and color schemes, you maintain a consistent branding experience and a cohesive flow between the platform and applications.&lt;/p&gt;

&lt;h3&gt;
  
  
  Onboarding link
&lt;/h3&gt;

&lt;p&gt;Remember to generate the onboarding link &lt;strong&gt;on demand&lt;/strong&gt;: create the link dynamically when the user accesses a specific page, just before starting or resuming the onboarding. Avoid storing the link permanently (as it expires after 4 minutes) and never send the onboarding link by email.&lt;/p&gt;

&lt;p&gt;The recommended approach is to make the link available in a page that is only accessible to the user, after login. Provide a way, such as a button, for the user to generate the onboarding link. Alternatively, create one on-the-fly when the user wants to access the onboarding application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Onboarding status
&lt;/h3&gt;

&lt;p&gt;While webhook is the most effective way to stay up-to-date with the status of the onboarding, it is also possible to make a &lt;a href="https://docs.adyen.com/api-explorer/#/balanceplatform/latest/get/accountHolders/{id}" rel="noopener noreferrer"&gt;GET /accountHolders/{id}&lt;/a&gt; request using the LEM API endpoint. The response fetches the “Account Holder” listing all capabilities and the current verification status.&lt;/p&gt;

&lt;p&gt;Avoid excessive and unnecessary calls to the API endpoint, instead use it only when strictly necessary. In cases where webhook processing fails or there is a requirement for real-time verification of certain information, the endpoint can be used selectively to perform these checks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The Adyen for Platforms Hosted Onboarding solution offers a simple and streamlined process for platform owners to implement the onboarding of merchants, reducing complexity and ensuring compliance with regulatory requirements across markets and regions.&lt;/p&gt;

&lt;p&gt;While the application provides out-of-the-box management of onboarding flows, an intuitive mobile-friendly user interface and customizable themes, it is important for platforms to understand there is some development work.&lt;/p&gt;

&lt;p&gt;In this article, and through the Adyen Docs site, we advised developers to implement an effective integration that blends in with the platform branding and style. By deploying webhooks, platforms receive real-time updates, reducing the duration and effort of the entire process. By following the recommended practices, developers can deliver a solution that ensures a user-friendly end-to-end onboarding experience.&lt;/p&gt;

&lt;p&gt;Are you ready for the next step? Visit our &lt;a href="https://developer.adyen.com/" rel="noopener noreferrer"&gt;Adyen Developer website&lt;/a&gt; to discover more content and resources for developers who are building the best platforms for their users.&lt;/p&gt;

</description>
      <category>platform</category>
      <category>onboarding</category>
      <category>developers</category>
    </item>
    <item>
      <title>Effortless API Testing with the Adyen Postman collections</title>
      <dc:creator>Beppe Catanese</dc:creator>
      <pubDate>Mon, 26 Jun 2023 13:52:43 +0000</pubDate>
      <link>https://dev.to/adyen/effortless-api-testing-with-the-adyen-postman-collections-49pf</link>
      <guid>https://dev.to/adyen/effortless-api-testing-with-the-adyen-postman-collections-49pf</guid>
      <description>&lt;p&gt;As a global leading technology-driven company, at Adyen we recognise the importance of equipping developers with tools and resources that reduce time to value and make the integration with our platform faster and better.&lt;/p&gt;

&lt;p&gt;That's why we have launched the &lt;a href="https://www.postman.com/adyendev"&gt;Adyen Postman space&lt;/a&gt;. Leveraging the robust capabilities of Postman—a very popular tool in the API ecosystem - the developers, who work with the Adyen platform, can quickly discover, explore and test the Adyen APIs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In this article..&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;…click, fork, play! Explore the benefits of using the Adyen Postman collections for discovering, exploring and testing the Adyen APIs. Checkout the step-by-step guide to getting started.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Adyen Postman Collections
&lt;/h2&gt;

&lt;p&gt;Adyen Postman collections consist of preconfigured API requests that enable developers to effortlessly invoke Adyen's APIs. The collections are automatically generated from the &lt;a href="https://github.com/adyen/adyen-openapi"&gt;OpenAPI specifications&lt;/a&gt;, ensuring all API endpoints and the JSON payloads are accurate and always up-to-date.&lt;br&gt;
We provide a single workspace for all Adyen APIs. In the workspace there is a collection for each of the Adyen services, from Checkout to Recurring, Point of Sale and Platforms.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Jdo7p2Nq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w3qlneoqeqlca25xl7dw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Jdo7p2Nq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w3qlneoqeqlca25xl7dw.png" alt="Image description" width="800" height="467"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Streamlined integration
&lt;/h3&gt;

&lt;p&gt;The primary advantage of adopting the Adyen Postman collections is the streamlined integration process we are able to offer. Following few simple steps the developers can perform API calls easily:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fork the environment and define your own credentials&lt;/li&gt;
&lt;li&gt;Fork the collection&lt;/li&gt;
&lt;li&gt;Run the HTTP requests&lt;/li&gt;
&lt;li&gt;Stay up to date&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Fork the environment
&lt;/h3&gt;

&lt;p&gt;By forking the preconfigured environment, developers obtain a template to configure essential settings such as the API key and other configuration options. It is important to keep the forked environment private to protect sensitive information.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--A2uDepHz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jzblmyaotk0rwmfrpqqm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A2uDepHz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jzblmyaotk0rwmfrpqqm.png" alt="Image description" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The configuration can be defined at different levels: the preferred approach is using the Postman environment as it can be shared across collections. It is however possible to set the values in the Global scope (always available throughout the entire workspace) or in the Collection directly.&lt;/p&gt;
&lt;h2&gt;
  
  
  Fork the collection
&lt;/h2&gt;

&lt;p&gt;To begin using the Adyen Postman collections, developers can fork a specific collection. By doing so, they can leverage the prebuilt requests, including parameters and payloads, saving valuable time and effort.&lt;br&gt;
The collections are designed with &lt;strong&gt;flexibility&lt;/strong&gt; in mind: they define variables that can be managed in one place and re-used across all requests (think of merchant and company accounts, platform code and other parameters).&lt;/p&gt;

&lt;p&gt;Once the collection is forked it becomes available in the developer’s private workspace. The requests can be customized (when needed) and executed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eO_WN_ZD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ku0171aq3i2db4wc45xv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eO_WN_ZD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ku0171aq3i2db4wc45xv.png" alt="Image description" width="800" height="467"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Developers using the Adyen Postman collections can invoke all API's endpoints using their own API key and access rights, validate the responses and verify the outcome.&lt;br&gt;
The collections simplify the work of developers and testers providing many pre-defined scenarios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;make a payment using various payment methods&lt;/li&gt;
&lt;li&gt;execute Adyen for Platforms Onboarding scenarios&lt;/li&gt;
&lt;li&gt;issuing of physical and virtual cards&lt;/li&gt;
&lt;li&gt;create different transaction rules&lt;/li&gt;
&lt;li&gt;etc..&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Stay Informed
&lt;/h2&gt;

&lt;p&gt;The Adyen Postman space provides a convenient way to &lt;strong&gt;stay updated on changes and new releases&lt;/strong&gt;. By watching a collection, users receive an email notification when there is a modification or something new in the collection.&lt;/p&gt;

&lt;p&gt;New API releases might bring new features, corrections, or sometimes better documentation and examples. Any of those changes is pushed to the developers watching the collection allowing them to inspect the differences and pull the changes.&lt;/p&gt;

&lt;p&gt;This proactive approach keeps developers informed about new versions and, ultimately, it is a great way to discover new features and upgrade their integration.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--u1O5VBQJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2x7e9oj5o27mpcahtt4a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--u1O5VBQJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2x7e9oj5o27mpcahtt4a.png" alt="Image description" width="800" height="467"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Payment subscriptions with Postman
&lt;/h2&gt;

&lt;p&gt;Let’s see the Postman collections in action. We are going to look at the Payment Subscriptions (Tokenization) use case where the shopper authorizes a recurring payment for a subscription.&lt;/p&gt;
&lt;h3&gt;
  
  
  Set the API Key and Merchant Account
&lt;/h3&gt;

&lt;p&gt;You start with forking the environment called “Adyen APIs”. In your own local fork, configure the &lt;code&gt;X-API-Key&lt;/code&gt; (API Key from the API credential) and the &lt;code&gt;Merchant Account&lt;/code&gt;. Keep the environment private as it contains sensitive information.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oemGHofR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vtfr1n03hinh4ixu6ew9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oemGHofR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vtfr1n03hinh4ixu6ew9.png" alt="Image description" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Fork the Checkout API collection
&lt;/h3&gt;

&lt;p&gt;Next fork the Checkout API collection, then browse to the “Payments” folder and take a look at the “Tokenize card details for a subscription” request.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JMs5sPvS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cxk9htvpaacf5eiwmk1v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JMs5sPvS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cxk9htvpaacf5eiwmk1v.png" alt="Image description" width="800" height="467"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The request payload is pre-configured with variables like the merchantAccount (defined in the environment above), dynamic variables (i.e. auto generated reference) and some data (like the amount) that can be changed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
 "amount": {
  "currency": "USD",
  "value": 1000
 },
 "reference": "{{$guid}}",
 "paymentMethod": {
  "type": "scheme",
  "number": "4111111111111111",
  "expiryMonth": "03",
  "expiryYear": "2030",
  "holderName": "John Smith",
  "cvc": "737"
 },
 "shopperReference": "SHOPPER_REF_1",
 "storePaymentMethod": true,
 "shopperInteraction": "Ecommerce",
 "recurringProcessingModel": "Subscription",
 "returnUrl": "https: //your-company.com/...",
 "merchantAccount": "{{YOUR_MERCHANT_ACCOUNT}}"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You only need to enable the environment, in the top-right corner, and execute the request. The response body will include the resultCode ('Authorized') and the generated token (in the 'additionalData.recurring.recurringDetailReference' field).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
 "additionalData": {
  "recurring.recurringDetailReference": "TOKEN_REF",
  "recurringProcessingModel": "Subscription",
  "paymentMethod": "visa",
  "recurring.shopperReference": "SHOPPER_REF_1"
 },
 "pspReference": "PSP00000001",
 "resultCode": "Authorised",
 "amount": {
  "currency": "USD",
  "value": 1000
 },
 "merchantReference": "111ab222-abcd-1234-aaaa-0f0f0f0f0fOf",
 "paymentMethod": {
  "brand": "visa",
  "type": "scheme"
 }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last step is to make a subscription payment using the token.&lt;br&gt;
Find the “Make a card payment with a token” request, set the token in the 'storedPaymentMethodId' field and execute the payment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--J1pgmWM5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m376vhkiyv03cp042hwp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--J1pgmWM5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m376vhkiyv03cp042hwp.png" alt="Image description" width="800" height="467"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Adyen Postman on Github
&lt;/h2&gt;

&lt;p&gt;The Adyen Postman space provides the latest and greatest version of the Adyen APIs. However it is sometimes necessary to work with an older version. This is why we also store the Postman (JSON) files for all API releases on the &lt;a href="https://github.com/adyen/adyen-postman"&gt;adyen-postman GitHub repository&lt;/a&gt;.&lt;br&gt;
Import the JSON file in Postman and run the requests against a previous API version: test URLs, endpoint paths and payloads are already configured accordingly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Adyen Postman collections provide developers with a powerful toolset for the discovery, configuration and testing of the Adyen's APIs. Using automation we ensure the collections are always up-to-date and the information is consistent. Leveraging on Postman notifications and its Git-alike version control developers are informed as soon as a new version is available.&lt;/p&gt;

&lt;p&gt;Save valuable time and effort by avoiding manual uploads of the OpenAPI files. Instead take advantage of a readily available collection for an effortless and effective utilization.&lt;/p&gt;

&lt;p&gt;Get started with the &lt;a href="https://www.postman.com/adyendev"&gt;Adyen Postman collections&lt;/a&gt;. Start by forking the environment, exploring the collections and invoking the endpoints. Reduce time to value and make your integration journey simpler and better.&lt;/p&gt;

</description>
      <category>api</category>
      <category>postman</category>
      <category>testing</category>
    </item>
    <item>
      <title>Adyen for Java developers</title>
      <dc:creator>Beppe Catanese</dc:creator>
      <pubDate>Wed, 24 May 2023 15:00:13 +0000</pubDate>
      <link>https://dev.to/adyen/adyen-for-java-developers-3p2g</link>
      <guid>https://dev.to/adyen/adyen-for-java-developers-3p2g</guid>
      <description>&lt;p&gt;In today's digital age, the ability to connect to different applications through APIs (Application Programming Interfaces) is essential for any modern platform. APIs allow the design of sophisticated workflows, enabling communication between systems that need to exchange data and provide services.&lt;/p&gt;

&lt;p&gt;While developers can use different languages and frameworks to directly consume the REST APIs, the adoption of libraries is the most effective path to create friction-less integrations that boost both productivity and developer experience.&lt;/p&gt;

&lt;p&gt;In a previous &lt;a href="https://www.adyen.com/blog/adyen-api-libraries"&gt;blog&lt;/a&gt; we explained the benefits of using an Adyen API Library. Let’s now explore more specifically the choices and advantages available to Java developers.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;In this article..&lt;/strong&gt;&lt;br&gt;
…discover the Adyen Java Library, what’s new in the latest release, and how to bootstrap a new application or upgrade an existing one.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Adyen Java Library
&lt;/h2&gt;

&lt;p&gt;The Adyen Java library is the toolkit provided to Java developers who work or will work with Adyen’s APIs. It enables them to focus on the use cases and its functional aspects while the library takes care of the necessary groundwork such as connection setup, security features (authentication, encryption and tokenization), validation, exception handling, etc…&lt;/p&gt;

&lt;p&gt;The library includes a wrapper for each of our public APIs, complete with documentation. Whether you are implementing a payment flow, platform integration, issuing, capital or API management &lt;strong&gt;you only need to use this library&lt;/strong&gt;. As you expand the scope of your integration and access new products or services, the library is already set up and the additional code is minimal.&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefits
&lt;/h3&gt;

&lt;p&gt;The Java library brings the following advantages typical of the Java ecosystem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easy access, available on Maven central
Usage of packages to ensure encapsulation and avoid name clashing&lt;/li&gt;
&lt;li&gt;Built-in JSON support with Gson&lt;/li&gt;
&lt;li&gt;Custom exception class (ApiException) to provide a consistent exception handling&lt;/li&gt;
&lt;li&gt;Dependency management: use Dependabot or Renovate to be notified when a new Adyen Java Library version is released&lt;/li&gt;
&lt;li&gt;Comprehensive unit testing coverage: check unit tests to see an example of how services are invoked and models are defined&lt;/li&gt;
&lt;li&gt;Built-in HTTP client (with additional proxy support) with the option to override and use your own implementation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Supported APIs
&lt;/h3&gt;

&lt;p&gt;All Adyen products are supported in the latest version of the Java library.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Online Payments&lt;/strong&gt;: everything you need to process payments and any advanced use case: Checkout, Payouts, Recurring Payments&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Point of Sale&lt;/strong&gt;: management of point-of-sale (POS) payment terminals&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Management&lt;/strong&gt;: configuration of company and merchant accounts, stores, payment terminals&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Platforms and Financial Products&lt;/strong&gt;: work with Adyen for Platforms. Account structure, onboarding, payment flows, embedded financial services&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What’s new in the Java library
&lt;/h3&gt;

&lt;p&gt;The Java Library v20 upgrade delivers a lot of new features as well as several significant improvements.&lt;/p&gt;

&lt;p&gt;A substantial redesign is perhaps the most noteworthy change, as it brings the library in line with Adyen API catalog and naming conventions. This update enables you to quickly locate the relevant Java service that corresponds to an API (i.e. CheckoutService when using the Checkout API). By maintaining consistency across Adyen documentation, the API Explorer, and code samples, you can easily find the information you need.&lt;/p&gt;

&lt;p&gt;Another significant change is the adoption of OpenAPI-driven code generation. Java classes that map the request and response payloads are now generated using OpenAPI Generator, ensuring that the code complies with the contract (i.e. the specification), thus avoiding errors and inconsistencies.&lt;/p&gt;

&lt;p&gt;There are other valuable improvements to make sure the library is &lt;strong&gt;comprehensive&lt;/strong&gt; (all API versions are updated to the latest release, there is support for Adyen for Platforms and Embedded Financial Services), &lt;strong&gt;fast&lt;/strong&gt; (providing built-in methods for JSON processing) and &lt;strong&gt;easy&lt;/strong&gt; (adding adapter classes mapping each payment method).&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;The Adyen Java library requires minimum setup. Make sure you match the pre-requisites (Java 11, a valid API Key), then add the dependency in your Java project with your favorite build tool.&lt;/p&gt;

&lt;p&gt;Maven&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;dependency&amp;gt;
  &amp;lt;groupId&amp;gt;com.adyen&amp;lt;/groupId&amp;gt;
  &amp;lt;artifactId&amp;gt;adyen-java-api-library&amp;lt;/artifactId&amp;gt;
  &amp;lt;version&amp;gt;20.0.0&amp;lt;/ver
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Gradle&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dependencies {
  implementation 'com.adyen:adyen-java-api-library:20.0.0'
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Setup the client that will access the Adyen service&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Setup Client and Service
Client client = new Client("Your X-API-KEY", Environment.TEST);

// PaymentsApi service
PaymentsApi paymentsApi = new PaymentsApi(client);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use the relevant service and models to access the functionality, for example when using Checkout you can get the list available payment methods:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PaymentMethodsRequest paymentMethodsRequest = new PaymentMethodsRequest();
paymentMethodsRequest.setMerchantAccount("YOUR_MERCHANT_ACCOUNT");
PaymentMethodsResponse resp = paymentsApi.paymentMethods(paymentMethodsRequest);

// print available payment methods
resp.getPaymentMethods().stream().forEach(System.out::println);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When using the Management API (i.e. generate client Key) the approach is similar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Management ClientKeyMerchantLevel service
ClientKeyMerchantLevel merchantLevel = new ClientKeyMerchantLevel(client);

// generate Client Key
GenerateClientKeyResponse resp = merchantLevel.generateNewClientKey("YOUR_MERCHANT_ACCOUNT", "YOUR_API_CREDENTIAL_ID");

System.out.println(resp.getClientKey());
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Working with webhooks
&lt;/h3&gt;

&lt;p&gt;The Adyen Java library provides support for webhooks, an essential feature of the Adyen platform. The Java library simplifies this by providing a model for the incoming payload (NotificationRequestItem) as well as a helper class (HMACValidator) to validate the HMAC signature.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// YOUR_HMAC_KEY from the Customer Area
String hmacKey = "YOUR_HMAC_KEY";
String notificationRequestJson = "NOTIFICATION_REQUEST_JSON";
HMACValidator hmacValidator = new HMACValidator();

NotificationHandler notificationHandler = new NotificationHandler();
NotificationRequest notificationRequest = notificationHandler.handleNotificationJson(notificationRequestJson);

// fetch first (and only) NotificationRequestItem
var notificationRequestItem = notificationRequest.getNotificationItems().stream().findFirst();

if (notificationRequestItem.isPresent()) {
    // Handle the notification
    if ( hmacValidator.validateHMAC(notificationRequestItem, hmacKey) ) {
     // Process the notification based on the eventCode
 // …
    } else {
// Non valid NotificationRequest
 throw new RuntimeError("Invalid HMAC signature");
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uhY-d-NV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f5k4uv5kp3h3f5v5ngic.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uhY-d-NV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f5k4uv5kp3h3f5v5ngic.png" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Is your application already using the Adyen Java library? Do you want to use this latest version? Then this section is for you.&lt;/p&gt;

&lt;p&gt;The Adyen Java Library v20 brings lots of new features but, at the same time, introduces several breaking changes. Although affecting existing working code is never good news, &lt;strong&gt;“breaking by design”&lt;/strong&gt; is sometimes necessary. The redesign of the library, the code generation and many other improvements are addressing inconsistencies and removing legacy code.&lt;/p&gt;

&lt;p&gt;The new version can better assist you in the implementation of your workflows and use cases, and allow you to easily integrate new products and features as they become available on the Adyen platform.&lt;/p&gt;

&lt;h3&gt;
  
  
  Migrating your code
&lt;/h3&gt;

&lt;p&gt;All Java models are created based on the OpenAPI specifications, which results in various modifications such as the relocation and renaming of packages, classes, and fields.&lt;/p&gt;

&lt;p&gt;Generic models (i.e. Address, Name, BankAccount, etc..) are no longer shared. Each package defines the models it needs. While this results in some duplication of the Java classes, it ensures a good encapsulation of the services.&lt;/p&gt;

&lt;p&gt;Notifications have been renamed to webhooks, for example class GenericNotification is now GenericWebhook (watch out, this class includes constants that might be used by your application) and NotificationHandler has become WebhookHandler.&lt;/p&gt;

&lt;p&gt;If you work with the &lt;strong&gt;Checkout API&lt;/strong&gt; you need to consider the following changes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The single Checkout class has been removed in favor of providing a different service class for each Checkout functionality: PaymentsApi, RecurringApi, ModificationsApi, etc.. Each service corresponds to a functionality (sub-folder) of the Checkout API (see API Explorer) ensuring consistency between the library and the API.&lt;/li&gt;
&lt;li&gt;com.adyen.model.Amount is now com.adyen.model.checkout.Amount&lt;/li&gt;
&lt;li&gt;com.adyen.model.checkout.details.StorePaymentMethodDetails is now com.adyen.model.checkout.StorePaymentMethodDetails&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PaymentsRequest&lt;/code&gt; has been renamed &lt;code&gt;PaymentRequest&lt;/code&gt;, &lt;code&gt;PaymentsResponse&lt;/code&gt; has been renamed &lt;code&gt;PaymentResponse&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Several helper methods (setAmountData, setCardData, isAuthorised, getCardHolderName) have been removed to let Java models provide getter/setter methods only, consistently with the OpenAPI specification and the API Explorer documentation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  GSON
&lt;/h4&gt;

&lt;p&gt;Another major change is the introduction of GSON as the preferred JSON processing framework. This should be transparent to the application as the library takes care of providing the serialization and deserialization logic that converts JSON payloads into Java objects.&lt;/p&gt;

&lt;p&gt;You can find within each model (ie CardDetailsRequest) the methods to perform the JSON processing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public static CardDetailsRequest fromJson(String jsonString) throws IOException {
   return JSON.getGson().fromJson(jsonString, CardDetailsRequest.class);
 }


public String toJson() {
   return JSON.getGson().toJson(this);
 }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the case of handling the webhooks you can take advantage of the built-in methods, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@PostMapping("/webhooks/notifications")
public ResponseEntity&amp;lt;String&amp;gt; webhooks(@RequestBody  ) throws Exception {
  // from JSON string to object
  var notificationRequest = NotificationRequest.fromJson(json);

  // consume event
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Upgrade the Recurring Payment sample
&lt;/h2&gt;

&lt;p&gt;Let’s look at a use case and what should be done when upgrading an existing application to the Adyen Java library v20.&lt;/p&gt;

&lt;p&gt;On &lt;a href="https://github.com/adyen-examples/adyen-java-spring-online-payments"&gt;GitHub&lt;/a&gt; you can find a Java sample application that demonstrates how to implement payment subscriptions. It is a simplified version of a website that offers a music subscription service. There are 2 flows basically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the shopper can purchase a subscription, saving the card details for the recurring payment (aka &lt;a href="https://docs.adyen.com/online-payments/tokenization"&gt;Tokenization&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;the site administrator can make payments on behalf of the shopper (for example monthly when the subscription is renewed) and optionally expire the token&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eTQNHxDi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x9qlhh2ybm7lcf5cx7ke.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eTQNHxDi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x9qlhh2ybm7lcf5cx7ke.jpg" alt="Image description" width="800" height="623"&gt;&lt;/a&gt;&lt;br&gt;
The first step is to update the dependency version in the application. It uses Gradle therefore we need to change the&lt;code&gt;adyen-java-library&lt;/code&gt; version in &lt;code&gt;build.gradle&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;implementation 'com.adyen:adyen-java-api-library:20.0.0'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The new version (as outlined above) has refactored packages and classes, so we need to update several imports and replace the Checkout class with PaymentsApi:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import com.adyen.model.checkout.Amount;
import com.adyen.model.checkout.CreateCheckoutSessionRequest;
import com.adyen.model.checkout.CreateCheckoutSessionResponse;
import com.adyen.service.checkout.PaymentsApi;

@RestController
@RequestMapping("/api")
public class SubscriptionResource {

// PaymentsApi service class 
private final PaymentsApi paymentsApi;
// …
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other classes and references to update:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PaymentsRequest and PaymentsResponse have been renamed to PaymentRequest and PaymentResponse: the imports and the class names must be updated&lt;/li&gt;
&lt;li&gt;The class that defines the payment method is now called CheckoutPaymentMethod&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The revised code snippet to perform a payment using a token looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PaymentRequest paymentRequest = new PaymentRequest();
paymentRequest.setMerchantAccount(“YOUR_MERCHANT_ACCOUNT”);
paymentRequest.setAmount
(new Amount().currency("EUR").value(1199L));
paymentRequest.setReference(orderRef);
paymentRequest.setShopperInteraction(PaymentRequest.ShopperInteractionEnum.CONTAUTH);
paymentRequest.setShopperReference(Storage.SHOPPER_REFERENCE);
paymentRequest.setRecurringProcessingModel(PaymentRequest.RecurringProcessingModelEnum.SUBSCRIPTION);
paymentRequest.setPaymentMethod(new CheckoutPaymentMethod(new StoredPaymentMethodDetails().storedPaymentMethodId(“abc123”));

PaymentResponse response = this.paymentsApi.payments(paymentRequest);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally we need to update the webhook handler to take advantage of the built-in methods for deserializing the JSON payload into a Java object&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// processing incoming webhooks
@PostMapping("/webhooks/notifications")
public ResponseEntity&amp;lt;String&amp;gt; webhooks(@RequestBody String json) 
throws Exception {


   // from JSON string to object
   NotificationRequest notificationRequest = NotificationRequest.fromJson(json);


// fetch first (and only) NotificationRequestItem
Optional&amp;lt;NotificationRequestItem&amp;gt; notificationRequestItem = 
notificationRequest.getNotificationItems().stream().findFirst();
if (notificationRequestItem.isPresent()) {
// consume webhooks
// ………
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Next steps
&lt;/h2&gt;

&lt;p&gt;It is time to get coding.&lt;/p&gt;

&lt;p&gt;For new starters the simplest way to see the Adyen Java library in action is to look at the &lt;a href="https://github.com/adyen-examples/adyen-java-spring-online-payments"&gt;Java Spring sample application&lt;/a&gt;. The sample uses the Web Drop-in and the Java library to demonstrate the Checkout use case.&lt;/p&gt;

&lt;p&gt;Run the application with &lt;a href="https://www.youtube.com/watch?v=0VKnZtiTaHs"&gt;one click using Gitpod&lt;/a&gt; and browse through the source code to learn how to obtain the available payment methods, perform the transaction and process the asynchronous event delivered by webhooks.&lt;/p&gt;

&lt;p&gt;If you are upgrading an existing application the Upgrade section above will guide you through the changes and how to deal with them. We are of course ready to help you in case something is not clear or needs additional details.&lt;/p&gt;

&lt;p&gt;We are looking forward to hearing your feedback about our libraries, what is missing or can be improved. Join our &lt;a href="https://forms.gle/FzyavyxX5S2GGGYr9"&gt;survey&lt;/a&gt; and let us know how we can improve them and make your developer experience better.&lt;/p&gt;

</description>
      <category>java</category>
      <category>payment</category>
      <category>integration</category>
    </item>
    <item>
      <title>Building better applications with Adyen API Libraries</title>
      <dc:creator>Beppe Catanese</dc:creator>
      <pubDate>Wed, 29 Mar 2023 19:11:08 +0000</pubDate>
      <link>https://dev.to/adyen/building-better-applications-with-adyen-api-libraries-113e</link>
      <guid>https://dev.to/adyen/building-better-applications-with-adyen-api-libraries-113e</guid>
      <description>&lt;p&gt;REST APIs are the de-facto standard of integrating platforms and third-party services. We know that very well at Adyen since our platform is designed around modular components that can be plugged into custom workflows, interact securely with business and consumer data and integrated using open standards.&lt;/p&gt;

&lt;p&gt;However, with the large range of available products and the many advanced use cases, the increasing complexity cannot be overlooked. That’s where API Libraries play a critical role: they simplify the integration, reduce effort and unlock the full potential of the &lt;strong&gt;Adyen single-platform&lt;/strong&gt; for developers that work with us.&lt;/p&gt;

&lt;h3&gt;
  
  
  In this article..
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;…read about the features of the Adyen API Libraries, the benefits they bring and why we implement an OpenAPI-driven approach to maximize the developer experience.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Adyen API Libraries
&lt;/h2&gt;

&lt;p&gt;Adyen Libraries are pre-built software components that simplify the process of accessing the Adyen REST APIs by providing a high-level abstraction. By using these libraries, developers can make API calls without having to write low-level code for the REST communication protocol, while also gaining access to functions and helpers for security, error management, and product-specific features.&lt;/p&gt;

&lt;p&gt;The overall &lt;strong&gt;developer experience is enhanced&lt;/strong&gt; significantly, making it easier and quicker to integrate with the Adyen platform.&lt;/p&gt;

&lt;p&gt;For statically-typed programming languages (Java, .NET, Go, Typescript) the great advantage is the domain models (classes mapping the request and response payloads) that the libraries provide out-of-the-box.&lt;/p&gt;

&lt;p&gt;The libraries, which evolve alongside the APIs, come with comprehensive documentation that explains basic setup as well as advanced settings. Additionally they include code snippets to help developers understand how to use them effectively.&lt;/p&gt;

&lt;p&gt;Several popular programming languages and frameworks are supported.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmunay5m0bui17lrkq0j9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmunay5m0bui17lrkq0j9.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits
&lt;/h2&gt;

&lt;p&gt;Developers love libraries and we are investing significant effort to make sure they are simple, fast and comprehensive:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Simple&lt;/strong&gt;: A library provides a pre-built set of modules and functions that developers can leverage to quickly integrate the APIs. This ease of integration reduces effort by removing the need to manually build out the API integration code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fast&lt;/strong&gt;: libraries includes clear documentation, code samples, and other resources that help developers understand how to use the API effectively. Default settings are coded into the library, built-in validation finds inconsistencies earlier, and exception management makes sure that errors are caught and dealt with accordingly. All of that boosts productivity and reduces time to value.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Comprehensive&lt;/strong&gt;: A library is typically designed to work with a specific programming language and framework. Developers can therefore work with their preferred technology stack and tools, resulting in a better developer experience. Security features (HMAC validation, masking, SSL certificate management) are also part of the library to ensure that the API is used securely.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We have also chosen to open source the projects: libraries are best developed as open-source projects, with the active participation of a community that provides valuable feedback, reports issues and proposes solutions. The joint effort makes sure they deliver real value to its users.&lt;/p&gt;

&lt;h2&gt;
  
  
  OpenAPI driven approach
&lt;/h2&gt;

&lt;p&gt;The OpenAPI specification is a pillar of Adyen’s &lt;a href="https://www.adyen.com/blog/api-first-adyen" rel="noopener noreferrer"&gt;API-first&lt;/a&gt; vision. We have adopted OpenAPI several years ago with the goal to create APIs that enable fast integration for developers and help businesses succeed.&lt;/p&gt;

&lt;p&gt;Adyen’s OpenAPI specifications are generated internally and published to &lt;a href="https://github.com/adyen/adyen-openapi" rel="noopener noreferrer"&gt;Github&lt;/a&gt; for both our users and the tools we offer. This pipeline benefits a range of applications.&lt;/p&gt;

&lt;p&gt;The Adyen &lt;a href="https://docs.adyen.com/api-explorer" rel="noopener noreferrer"&gt;API Explorer&lt;/a&gt;: an interactive and comprehensive environment for working with all Adyen APIs, ensuring that developers have access to the most up-to-date documentation and functionality.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://www.postman.com/adyendev" rel="noopener noreferrer"&gt;AdyenDev Postman&lt;/a&gt; space: a dedicated workspace featuring the Postman collections of the latest API versions.&lt;/p&gt;

&lt;p&gt;The Adyen &lt;a href="https://github.com/adyen" rel="noopener noreferrer"&gt;Open Source Libraries&lt;/a&gt;: a collection of libraries, components and plug-ins that streamline the API integration process.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/adyen-examples" rel="noopener noreferrer"&gt;Adyen Examples&lt;/a&gt;: the repository of all example integrations for the various libraries and plugins.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4cx0cko93cpmekav8y4l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4cx0cko93cpmekav8y4l.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks to the OpenAPI standard and the &lt;a href="https://github.com/OpenAPITools/openapi-generator" rel="noopener noreferrer"&gt;OpenAPI Generator&lt;/a&gt;, we’ve established a development pipeline with &lt;strong&gt;shorter release cycles&lt;/strong&gt; for our libraries.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automating libraries
&lt;/h2&gt;

&lt;p&gt;Whenever a new API version is released, we publish the corresponding OpenAPI file on Github. The specifications are therefore available to the merchants and all developers who work with the Adyen platform.&lt;/p&gt;

&lt;p&gt;The next step of our automated pipeline is to generate and update the libraries’ source code. From the OpenAPI specification files we create services, models, documentation and code snippets. The source code is reviewed, tested and merged into the existing libraries, and swiftly released.&lt;/p&gt;

&lt;p&gt;This pipeline has allowed us to closely follow the API releases, making new features available sooner through our API libraries. It has also improved consistency and reduced mistakes by automating the code generation.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;With the automation of the OpenAPI code generation we aim to have general availability across all API Libraries within 2 weeks of new releases and updates from the Adyen platform.&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;Vivienne Klaassens&lt;/strong&gt; — Product Manager&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this article, we have discussed our approach to API Libraries and how they benefit you as a developer. By utilizing the OpenAPI standard and implementing an automated pipeline, we ensure that our libraries closely follow the API releases.&lt;/p&gt;

&lt;p&gt;As a result, developers can &lt;strong&gt;quickly and easily access the latest features&lt;/strong&gt; and capabilities of our platform, saving them valuable time and effort while they focus on their specific use cases.&lt;/p&gt;

&lt;p&gt;We are always looking for contributors to our Open Source projects: we believe this is a great way to improve the libraries and build a stronger community. It can be code contributions, testing, documentation or even just logging an issue.&lt;/p&gt;

&lt;p&gt;Go ahead and clone a library or a sample application, check out what works well and what else we can do to make your developer experience even better.&lt;/p&gt;

&lt;p&gt;Reach us on our Github home or on Twitter.&lt;/p&gt;

</description>
      <category>api</category>
      <category>productivity</category>
      <category>programming</category>
    </item>
    <item>
      <title>Consuming webhooks</title>
      <dc:creator>Beppe Catanese</dc:creator>
      <pubDate>Thu, 02 Feb 2023 11:49:05 +0000</pubDate>
      <link>https://dev.to/adyen/consuming-webhooks-56fo</link>
      <guid>https://dev.to/adyen/consuming-webhooks-56fo</guid>
      <description>&lt;p&gt;Webhooks are an essential feature of the Adyen Platform. Payment flows often depend on external factors, like a third-party authorization. There are also events outside the control of the application that integrate with Adyen, for example triggered by customers (such as chargeback requests) or by administration functions (like the availability of a new report). &lt;/p&gt;

&lt;p&gt;This is why we have created a sophisticated framework that caters to all those scenarios, addressing flexibility (how webhooks are set up and managed), reliability (retry and event logging), and consistency (events are delivered as they happen).&lt;/p&gt;

&lt;h3&gt;
  
  
  In this article..
&lt;/h3&gt;

&lt;p&gt;..find out how to set up, validate, and consume webhooks. Learn about best practices for an optimal integration. &lt;/p&gt;

&lt;p&gt;You can also check out the “Creating and consuming notification webhooks” &lt;a href="https://youtu.be/pwR4A4KLVuI" rel="noopener noreferrer"&gt;video&lt;/a&gt; on our AdyenDevs YouTube channel.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a webhook?
&lt;/h2&gt;

&lt;p&gt;A webhook is an HTTP-based push mechanism that enables Adyen to send real time events to your application. There are multiple events that might be important in your workflow, for example payment status updates and modifications or changes to the company account and store setup. &lt;/p&gt;

&lt;p&gt;The framework allows businesses and platforms to &lt;strong&gt;subscribe&lt;/strong&gt; to the events that are relevant and configure the additional data that should be delivered with the event.&lt;/p&gt;

&lt;h2&gt;
  
  
  An example
&lt;/h2&gt;

&lt;p&gt;Let's look at a payment flow using the Adyen Drop-in: with this UI component, you can integrate a Checkout component in your web application  that supports various payment methods and can perform the actual payment flow.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1gmt4pe5fu7dhverikja.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1gmt4pe5fu7dhverikja.jpg" alt="Image description" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After the initialization (in the case of the drop-in, it is the creation of a session), the component takes care of everything, from displaying the available payment methods to capturing the data entered by the shopper and executing the payment.&lt;/p&gt;

&lt;p&gt;What then happens is that the final payment status is later notified (confirmed)  &lt;strong&gt;asynchronously&lt;/strong&gt;, after a short delay, via a webhook.&lt;/p&gt;

&lt;h2&gt;
  
  
  Do I need a webhook?
&lt;/h2&gt;

&lt;p&gt;You do. In case of a payment, the confirmation might come after a &lt;strong&gt;significant delay&lt;/strong&gt;. In some local payment methods (for instance iDEAL in the Netherlands), the final outcome of the payment might take several hours to complete. &lt;/p&gt;

&lt;p&gt;There are also a variety of &lt;strong&gt;events triggered by the platform&lt;/strong&gt; that are important and which your back office (and CRM) should be informed about: we have already mentioned the availability of a new report but it is also crucial to stay up to date with changes to merchant data, updates on the terminal fleet configuration, and platform onboarding milestones.&lt;/p&gt;

&lt;p&gt;Last but not least, the webhook framework provides features like &lt;strong&gt;automated retries&lt;/strong&gt;, &lt;strong&gt;system notifications&lt;/strong&gt;, and &lt;strong&gt;logging&lt;/strong&gt; that help manage errors and monitor inconsistencies.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Developers in action
&lt;/h2&gt;

&lt;p&gt;Let’s dig into technical details that are relevant to developers, shall we?&lt;/p&gt;

&lt;p&gt;In the next sections we will be looking at how to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create and validate a webhook&lt;/li&gt;
&lt;li&gt;Secure a webhook&lt;/li&gt;
&lt;li&gt;Run the sample application&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Create and validate a webhook
&lt;/h2&gt;

&lt;p&gt;There are 2 ways to create a webhook: via the Customer Area web application and through the Management API. &lt;/p&gt;

&lt;p&gt;In this article, we focus on the Customer Area to perform the setup (so we can better understand the relevant fields and options). You can check out our previous &lt;a href="https://www.adyen.com/blog/automate-workflows-with-management-api" rel="noopener noreferrer"&gt;blog&lt;/a&gt; to explore how to use the Management API to automate configuration and workflows. &lt;/p&gt;

&lt;h3&gt;
  
  
  Customer Area
&lt;/h3&gt;

&lt;p&gt;Log in to the Customer Area and access the &lt;strong&gt;Developers-&amp;gt; Webhook&lt;/strong&gt; screen (your account must have the Merchant Technical Integrator or Merchant Admin role) and create a new webhook.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm3p9s8inumz3od1wrzyq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm3p9s8inumz3od1wrzyq.jpg" alt="Image description" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this example, we set up a &lt;strong&gt;Standard notificatio&lt;/strong&gt;n: choose a name (&lt;strong&gt;Description&lt;/strong&gt;) and enter a valid URL in the &lt;strong&gt;Server configuration&lt;/strong&gt; field (this is the URL of the application that will be processing the incoming webhook event).&lt;/p&gt;

&lt;p&gt;In this setup, we are going to use &lt;a href="http://webhook.site/" rel="noopener noreferrer"&gt;webhook.site&lt;/a&gt; (&lt;em&gt;), a tool that helps to validate and inspect incoming webhooks without the need to expose your application or server to the internet. Grab the URL generated by webhook.site, paste it into Server configuration and click **Apply&lt;/em&gt;*.&lt;/p&gt;

&lt;p&gt;(*) Other websites offer similar options&lt;/p&gt;

&lt;h3&gt;
  
  
  Validate the webhook
&lt;/h3&gt;

&lt;p&gt;Even before creating the webhook, it is already possible to perform the validation. Click on &lt;strong&gt;Test Configuration&lt;/strong&gt; and choose which &lt;strong&gt;Event&lt;/strong&gt; to send: the JSON payload – which will be delivered – is displayed and can be edited (if needed).&lt;/p&gt;

&lt;p&gt;Go ahead and test: webhook.site will show you (in real time) the incoming notification with all the relevant details (like HTTP request headers and request body) while in the Customer Area you can see the HTTP response code and body received back.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HTTP 200 but test fails&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The validation however did not entirely succeed. We have received a response with HTTP status code 200 but the Customer Area warning is pretty clear: the body of the HTTP response is not what we expected.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9hoacqcsvi38ybuevcbv.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9hoacqcsvi38ybuevcbv.jpg" alt="Image description" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can address this in webhook.site: find the &lt;strong&gt;Edit&lt;/strong&gt; menu where it is possible to define the body of the HTTP response. Edit the webhook configuration to &lt;strong&gt;return the string [accepted]&lt;/strong&gt;.&lt;br&gt;
When re-running the validation we can see that the warning has disappeared and the test is now successful.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note for developers&lt;/strong&gt;: webhook responses must return HTTP status code 200 and a body with the string ‘[accepted]’ when this is successfully consumed. &lt;/p&gt;
&lt;h3&gt;
  
  
  Secure a webhook
&lt;/h3&gt;

&lt;p&gt;Complete the webhook configuration, setting the recommended security settings via:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Basic Authentication&lt;/li&gt;
&lt;li&gt;HMAC key&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: we also recommend configuring &lt;strong&gt;HTTPS using TLS 1.3&lt;/strong&gt; for the endpoint that received the webhook events.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Basic Authentication&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Setting up Basic Authentication for the webhook is very important: you want to authenticate the incoming HTTP requests and confirm they are sent by Adyen.&lt;/p&gt;

&lt;p&gt;Define the &lt;strong&gt;Username&lt;/strong&gt; and &lt;strong&gt;Password&lt;/strong&gt;: those will be encoded (base64) and passed in the Authorization header. It is the responsibility of your server (or application) to verify the credentials when an incoming notification arrives.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjz71w5t7r8xd8ne1bp8e.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjz71w5t7r8xd8ne1bp8e.jpg" alt="Image description" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Basic Authentication is one of the oldest and simplest ways to perform authentication over HTTP. It is supported by pretty much all web servers, API gateways, and HTTP-facing software: the recommendation is to &lt;strong&gt;use one of the proven products or open source packages&lt;/strong&gt; instead of implementing this at application level.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HMAC key&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Generate the HMAC key which will be used by Adyen to sign the webhook event: the signature will be included in the JSON payload and, again, it is the responsibility of your application to verify it is valid. &lt;/p&gt;

&lt;p&gt;This security setting is also essential as it guarantees that the webhook comes from Adyen and the payload has not been altered by unauthorized parties.&lt;/p&gt;
&lt;h2&gt;
  
  
  Run the sample application
&lt;/h2&gt;

&lt;p&gt;It is finally time to look at the code and how the webhook is consumed. &lt;/p&gt;

&lt;p&gt;Visit the Github repository of the &lt;a href="https://github.com/adyen-examples/adyen-node-online-payments" rel="noopener noreferrer"&gt;Adyen NodeJS&lt;/a&gt; sample application: it implements a Checkout screen that supports various payment methods as well as an example of the endpoint consuming the webhook.&lt;/p&gt;

&lt;p&gt;The README file explains what you need to do to run the application on Gitpod, a developer-friendly cloud IDE (Integrated Development Environment):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Get hold of the Adyen API keys &lt;/li&gt;
&lt;li&gt;Configure Gitpod environment variables &lt;/li&gt;
&lt;li&gt;Launch the workspace&lt;/li&gt;
&lt;li&gt;Configure the webhook (URL and HMAC key)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note to developers&lt;/strong&gt;: pay attention to the order of the steps above. Gitpod generates a new URL for each workspace. Therefore it is necessary to launch it first then copy the generated URL. Use the Gitpod URL to configure the webhook (field Server Configuration) in the Customer Area. Don’t forget to generate the HMAC key (necessary to validate the webhook payload) and store it as a Gitpod environment variable (ADYEN_HMAC_KEY).&lt;/p&gt;
&lt;h3&gt;
  
  
  Webhook endpoint
&lt;/h3&gt;

&lt;p&gt;The Sample Application provides an implementation of the endpoint that will receive and consume the webhook event. &lt;/p&gt;

&lt;p&gt;First take a look at the JSON payload &lt;a href="https://docs.adyen.com/api-explorer/Webhooks/1/post/AUTHORISATION" rel="noopener noreferrer"&gt;schema&lt;/a&gt; to understand the structure of the payload. Here is an example with the most relevant attributes of the AUTHORISATION event:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "live": "false",
   "notificationItems": [
     {
      "NotificationRequestItem": {
       "additionalData": {
         "recurring.recurringDetailReference": "123",
         "recurring.shopperReference": "xyz",
         “hmacSignature”: “ab1323…..”
       },
       "amount": {
         "currency": "EUR",
         "value": 1000
        },
        "eventCode": "AUTHORISATION",
        "eventDate": "2022-12-01T01:00:00+01:00",
        "merchantAccountCode": "YOUR_MERCHANT_ACCOUNT",
        "merchantReference": "YOUR_MERCHANT_REFERENCE",
        "paymentMethod": "ach",
        "pspReference": "YOUR_PSP_REFERENCE",
        "operations" : [],
        "success": "true"
      }
     }
   ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The payload includes an array of &lt;code&gt;NotificationItems&lt;/code&gt;: the array will &lt;strong&gt;always include a single element&lt;/strong&gt;. Developers should &lt;a href="https://docs.adyen.com/development-resources/webhooks/verify-hmac-signatures" rel="noopener noreferrer"&gt;validate&lt;/a&gt; the hmacSignature and process the item.&lt;br&gt;
Fortunately all our libraries include the functions to perform this type of validation, so the step is straightforward.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.post("/api/webhooks/notifications", async (req, res) =&amp;gt; {

 // YOUR_HMAC_KEY from the Customer Area
 const hmacKey = process.env.ADYEN_HMAC_KEY;

 // Notification Request JSON
 const body = req.body;
 const items = body.notificationItems

 // Fetch single event
 const notification = items[0].NotificationRequestItem
 console.log(eventCode: ’ + notification.eventCode);

 // validate HMAC signature
 if(validator.validateHMAC(notification, hmacKey)) {
  // process payload asynchronously
  const result =  consumePayload(notification);

  res.send('[accepted]')

 } else {
   // invalid signature
   res.status(401).send('Invalid HMAC signature');
 }
} 

function consumePayload() {
  // add to queue or DB
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Best practices
&lt;/h2&gt;

&lt;p&gt;Here are several recommendations and tips to consider for getting the best out of the webhook framework.&lt;/p&gt;

&lt;h3&gt;
  
  
  Security
&lt;/h3&gt;

&lt;p&gt;This was already discussed above, but it is really important so let’s recap once more.&lt;/p&gt;

&lt;p&gt;Use both Basic Authentication (authenticate incoming requests) and HMAC (validate signature of the payload). Don’t forget to leverage TLS 1.3, the most modern security protocol. &lt;/p&gt;

&lt;p&gt;The webhook endpoint doesn’t need to include any parameter, especially your API key or other tokens. Usually a URL without query string should be enough:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://{your_server}/{path}
Ie https://example.com/webhook/api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Manage duplicates and expect delays
&lt;/h3&gt;

&lt;p&gt;It’s unusual but webhook events might be delivered more than once. Therefore you should handle duplicates in your design. &lt;/p&gt;

&lt;p&gt;The duplicates have the same ‘eventCode’ and ‘pspReference’: use this unique combination to identify &lt;strong&gt;when a second event is delivered and update the information&lt;/strong&gt; in your system accordingly. For example the &lt;a href="https://www.adyen.com/revenue-optimization" rel="noopener noreferrer"&gt;Adyen Revenue Accelerate&lt;/a&gt; supports retrying payments that have failed but eventually become authorized after another attempt.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4bw8wfl3zyxq3p4kv4vq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4bw8wfl3zyxq3p4kv4vq.jpg" alt="Image description" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Webhook events are delivered with a certain delay (few seconds to minutes). We understand this is crucial in the case of payment authorizations: we strive to minimize the delay but often that depends on external factors (response from third-party systems).&lt;/p&gt;

&lt;h3&gt;
  
  
  Retry
&lt;/h3&gt;

&lt;p&gt;Each webhook delivery expects an acknowledgement that will mark it as successful. &lt;br&gt;
When this is not the case, the Adyen Platform will resend the event later. The first retry occurs after a few minutes but the following attempts (until the acknowledgement is received) are scheduled with an increasing delay.&lt;/p&gt;

&lt;p&gt;Make sure your endpoint implementation responds correctly and monitor errors on your side.&lt;/p&gt;
&lt;h3&gt;
  
  
  Consume payload asynchronously
&lt;/h3&gt;

&lt;p&gt;Developers might design their application logic to process the webhook events as they come, within the same application thread. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.post("/api/webhooks/notifications", async (req, res) =&amp;gt; {

 // Notification Request JSON
 const items = req.body.notificationItems
 // Fetch single event
 const notification = items[0].NotificationRequestItem

 if( validator.validateHMAC(notification, hmacKey) ) {
   // apply business logic

  // send ack
  res.send('[accepted]')
 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is an approach we &lt;strong&gt;do not&lt;/strong&gt; recommend. The complexity of the application logic (business rules as well as integration with other components) or the duration of certain operations (downloading large reports) might take a long time and can cause the timeout of the HTTP request. &lt;/p&gt;

&lt;p&gt;In situations like these, the webhook event is marked as failed and will be resent later.&lt;/p&gt;

&lt;p&gt;The best practice is to consume and &lt;strong&gt;process the payload asynchronously&lt;/strong&gt;: the webhook is marked successful immediately after validating the HMAC signature while your backend takes care of consuming and processing the event.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.post("/api/webhooks/notifications", async (req, res) =&amp;gt; {

 if( validator.validateHMAC(notification, hmacKey) ) {
  // process payload asynchronously
  const result =  consumePayload(notification);

  res.send('[accepted]')
 } else {
   // invalid signature
   res.status(401).send('Invalid HMAC signature');
 }

}

function consumePayload() {
  // add to queue or DB
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Webhooks are an essential feature of the Adyen Platform and we try our best to provide exhaustive documentation, code samples, and relevant technical content. &lt;/p&gt;

&lt;p&gt;Does the asynchronous nature of the webhook add complexity to your architecture? Do you have suggestions or requests to improve your developer experience? Reach out to &lt;a href="https://twitter.com/AdyenDevs" rel="noopener noreferrer"&gt;@AdyenDevs&lt;/a&gt; and let’s get started.&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>cryptocurrency</category>
      <category>web3</category>
      <category>offers</category>
    </item>
    <item>
      <title>Pay by Link for developers</title>
      <dc:creator>Beppe Catanese</dc:creator>
      <pubDate>Mon, 21 Nov 2022 12:46:32 +0000</pubDate>
      <link>https://dev.to/adyen/pay-by-link-for-developers-2o9i</link>
      <guid>https://dev.to/adyen/pay-by-link-for-developers-2o9i</guid>
      <description>&lt;p&gt;&lt;a href="https://www.adyen.com/blog/pay-by-link---your-route-to-contextual-commerce-" rel="noopener noreferrer"&gt;Pay By Link&lt;/a&gt; is one the tools Adyen makes available to developers and merchants who want to support multi-channel customer journeys and implement an effective &lt;a href="https://www.adyen.com/unified-commerce" rel="noopener noreferrer"&gt;Unified Commerce&lt;/a&gt; strategy. They can be created online or in-store, applied to different use cases but at the same time still being part of one platform.&lt;/p&gt;

&lt;h3&gt;
  
  
  In this article..
&lt;/h3&gt;

&lt;p&gt;.. you can read what Pay by Link is, its use cases and challenges, and how to generate one using the Adyen Customer Area, the REST APIs or the SDKs.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Pay by Link is
&lt;/h2&gt;

&lt;p&gt;Pay by Link is the generation of a unique link which can be shared with shoppers to perform a payment. It comes with three essential features: simplicity, flexibility and branding.&lt;/p&gt;

&lt;p&gt;Start with &lt;strong&gt;simplicity&lt;/strong&gt;: Pay by Link can be generated in different ways (Customer Area, APIs) and requires a minimum set of data.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;flexibility&lt;/strong&gt; comes with the possibility to share the links in many different ways, from Social Media to messaging applications, emails or creating a QR code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Branding&lt;/strong&gt; is also important: the payment page can be customized (title, logo, background) by the merchant to keep the identity and style of the brand all the way to the payment execution.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Pay by Link is not
&lt;/h2&gt;

&lt;p&gt;Despite its ease of use, Pay by Link &lt;strong&gt;cannot replace the checkout experience&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;From the shopper point of view it is important to stay within the merchant website, branded and designed to maximize the shopping experience. While Pay by Link hosted page can be customized (see above) it still represents a step outside the site where the shopper is buying the product or service, involving redirecting between different hosts and adding potential friction in the payment flow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pay by Link Use Cases
&lt;/h2&gt;

&lt;p&gt;Pay by Link works very well in scenarios where there is &lt;strong&gt;no real time requirement&lt;/strong&gt;: the shopper is not waiting for the payment outcome to be able to obtain the goods. Think, for example, of B2B payments such as invoicing.&lt;/p&gt;

&lt;p&gt;Another valid use case is when &lt;strong&gt;the payment can be performed offline&lt;/strong&gt;, for example something goes wrong during the checkout flow and the payment link is later sent to the shopper for completing the purchase.&lt;/p&gt;

&lt;p&gt;Yet another is when shoppers interact with shop assistants via an application or a chatbot: they are guided through products and options, and eventually they receive a Pay by Link to complete the purchase.&lt;/p&gt;

&lt;p&gt;Here is a &lt;a href="https://www.adyen.com/press-and-media/2020/pay-by-link-technology-helps-australian-boutique-keep-sales-flowing-during-lockdown" rel="noopener noreferrer"&gt;success story&lt;/a&gt; on how phone orders have been made more secure with Pay by Link.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pay by Link in the Customer Area
&lt;/h2&gt;

&lt;p&gt;The easiest way to use the Pay by Link feature is to create the link in the Adyen Customer Area. This is trivial (there is no development work required for the business to accept payments) and convenient (often adopted by in-store employees or customer support teams).&lt;/p&gt;

&lt;p&gt;Log in in the Customer Area, make sure the role “Enable Pay by Link” has been granted to your user account, then access the Create Pay by Link screen.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4i5zm0xs10um03hvzj04.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4i5zm0xs10um03hvzj04.jpg" alt="Payment Links screen (Customer Area)" width="800" height="244"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F510kdk932jsv3upu21rb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F510kdk932jsv3upu21rb.jpg" alt="Create Payment Link screen (Customer Area)" width="800" height="718"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We do our best to make all those fields self-explanatory and provide sensible defaults. Let’s look at the most interesting ones:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;“link type”: you can define if the link is single-use (only one payment can be performed) or if it is meant to be used several times, usually because it is sent to multiple recipients.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;“link validity”: every link has an expiration date that can be set during the creation. Note that it is always possible, after the link is generated, to manually expire the link.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The optional “Additional Details” section can be used to ask the shopper to provide certain information before performing the payment, which is important when contact details (name, email address, delivery address) or invoicing information (name, address) are required.&lt;/p&gt;

&lt;h2&gt;
  
  
  Custom look-and-feel
&lt;/h2&gt;

&lt;p&gt;The customisation of Adyen’s Pay by Link page is implemented by creating themes. Each theme defines the title of the page, the logo to be displayed and a background image.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz1zvrnqqyhrt2tfls9n0.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz1zvrnqqyhrt2tfls9n0.jpg" alt="Custom Themes screen (Customer Area)" width="800" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Pay by Link API
&lt;/h2&gt;

&lt;p&gt;Although creating Pay by Link in the Customer Area requires minimal work , developers typically need a granular control of the feature. This is why Pay by Link, like &lt;strong&gt;all features in the Adyen platform&lt;/strong&gt;, provides an API.&lt;/p&gt;

&lt;p&gt;The API allows the creation, management and integration of Pay by Link with a bespoke workflow. This can be a link following an automated process, a conversation with a chatbot or a notification on a messaging platform.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://docs.adyen.com/api-explorer/Checkout/69/post/paymentLinks" rel="noopener noreferrer"&gt;Pay by Link REST&lt;/a&gt; API has a single endpoint (&lt;code&gt;/paymentLinks&lt;/code&gt;) that supports 3 HTTP verbs: POST (create a new one), GET (retrieve existing) and PATCH (update existing). Let’s have a look.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a new Pay by Link (POST)
&lt;/h3&gt;

&lt;p&gt;Create a new Pay by Link by performing a POST request and providing a payload with the payment attributes. Here is an example that provides the basic information, however the API allows to include additional fields (billingAddress, deliveryAddress, price and product information) when necessary.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -d '
{
  "amount" : {
     "currency" : "BRL",
     "value" : 10000
  },
  "countryCode" : "BR",
  "merchantAccount" : "myMerchantAccount",
  "reference" : "a121"
}
'
-H "Content-Type: application/json" 
-H "X-API-Key: #####" -X POST 
https://checkout-test.adyen.com/v69/paymentLinks
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Pay by Link creation is confirmed with the HTTP response status code 201 and a response body with the information of the newly created link (i.e. url, expiry date, etc..)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "amount": {
    "currency": "BRL",
    "value": 10000
  },
  "billingAddress": {
    "city": "São Paulo",
    "country": "BR",
    "houseNumberOrName": "999",
    "postalCode": "59000060",
    "stateOrProvince": "SP",
    "street": "Roque Petroni Jr"
  },
  "countryCode": "BR",
  "expiresAt": "2022-09-21T09:48:49Z",
  "merchantAccount": "TestMerchantAccount",
  "reference": "a121",
  "reusable": false,
  "shopperEmail": "test@email.com",
  "shopperLocale": "pt_BR",
  "shopperReference": "12345678",
  "id": "XYZ123",
  "status": "active",
  "url": "https://test.adyen.link/XYZ123"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Working with Adyen SDKs
&lt;/h2&gt;

&lt;p&gt;Adyen actively maintains several language-specific &lt;a href="https://github.com/adyen" rel="noopener noreferrer"&gt;open source libraries&lt;/a&gt; that allow a simple and speedy integration of features and products offered by API. Using the SDK developers can create the Pay by Link from the environment and technology stack of their choice.&lt;/p&gt;

&lt;p&gt;When using the &lt;strong&gt;Java SDK in a Kotlin application&lt;/strong&gt;, for instance, developers only need to initialize the Client handler and call the corresponding &lt;code&gt;PaymentLinks&lt;/code&gt; create method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// obtain client
private var client = Client(“#####”, Environment.TEST)
private var paymentLinks = PaymentLinks(client)

// create new Pay by Link
val createPaymentLinkRequest = CreatePaymentLinkRequest()
   .amount(
       Amount()
           .currency("BRL")
           .value(10000)
   )
   .merchantAccount(adyenConfig.merchantAccount)
   .reference(reference)
   .countryCode("BR")
   .billingAddress(
       Address()
           .street("Roque Petroni Jr")
           .postalCode("59000060")
           .city("São Paulo")
           .country("BR")
   )

val paymentLink = paymentLinks.create(createPaymentLinkRequest)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Get and Patch
&lt;/h3&gt;

&lt;p&gt;The Pay by Link API also provides a way to access (GET) the information about an existing Pay by Link as well as the option to update (PATCH) the status. The latter is interesting, for example, when the Pay by Link needs to be manually expired.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "status": "expired"
}
' 
-H "Content-Type: application/json" 
-H "X-API-Key: #####" -X PATCH 
https://checkout-test.adyen.com/v69/paymentLinks/XYZ123
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This again can be done using the SDK.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// obtain client
private var client = Client(“#####”, Environment.TEST)
private var paymentLinks = PaymentLinks(client)

// get paymentLink by id
var paymentLink = paymentLinks.retrieve(“00000001”)

// update paymentLink status
paymentLink = paymentLinks.update("000000001", 
UpdatePaymentLinkRequest().status(
  UpdatePaymentLinkRequest.StatusEnum.EXPIRED)
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It must be noted that the &lt;code&gt;GET&lt;/code&gt; endpoint returns the &lt;strong&gt;status of the payment link&lt;/strong&gt; and not the payment status.&lt;/p&gt;

&lt;h2&gt;
  
  
  Working sample
&lt;/h2&gt;

&lt;p&gt;The best way to demonstrate the Pay by Link capabilities to the developers is of course to create a working demo. This is why we have developed a &lt;a href="https://github.com/jlengrand/pay-by-link-sample-kotlin" rel="noopener noreferrer"&gt;Kotlin Sample&lt;/a&gt; application on Github.&lt;/p&gt;

&lt;p&gt;The sample application demonstrates how you can create payment links and perform (simulate) the actual payment as well as check their status. It is developed with a Kotlin backend, a NodeJS frontend and it can be deployed on Gitpod.&lt;/p&gt;

&lt;p&gt;The Pay by Link capabilities are integrated using the open source &lt;a href="https://github.com/Adyen/adyen-java-api-library" rel="noopener noreferrer"&gt;Adyen Java API&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi927o5oqfednjmwucdxv.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi927o5oqfednjmwucdxv.jpg" alt="Pay by Link demo app" width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feel free to clone the source code, play around and provide us with some feedback or requests to improve it further.&lt;/p&gt;

&lt;h2&gt;
  
  
  Interesting to know
&lt;/h2&gt;

&lt;p&gt;Unlike the Customer Area the Pay by Link API supports all payment methods available to the merchant. There are few payments where extra information is required, for example indicating price and product information as &lt;code&gt;lineItems&lt;/code&gt;: that can only be done via the API.&lt;/p&gt;

&lt;p&gt;Moreover the links created via API can optionally store the payment details, something not supported in the CA for security reasons.&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenges
&lt;/h2&gt;

&lt;p&gt;Although Pay by Link is easy and flexible, it is not intended to &lt;strong&gt;replace the shopper checkout experience&lt;/strong&gt;. It might be tempting to adopt this tool outside its scope, but developers should remember the friction of redirecting shoppers to different pages. From a technical point of view the complexity of dealing with different entry points (start of the checkout, redirect back from the payment page).&lt;/p&gt;

&lt;p&gt;It is also important to remember that Pay by Link based solutions should anyway integrate webhooks. &lt;strong&gt;Notification webhooks&lt;/strong&gt; deliver the final outcome of the payment and must be consumed to verify the transaction is successful and the purchase can be confirmed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Pay by Link remains a powerful tool when used within the right context. Merchants and developers should ensure Pay by Link is adopted for the right use case. In that case the creation of simple yet robust payment flows can bring significant competitive advantages with a small development effort.&lt;/p&gt;

</description>
      <category>css</category>
      <category>webdev</category>
      <category>discuss</category>
    </item>
  </channel>
</rss>
