Everything you need to know about card-on-file
Recurring payments, top-ups, and subscriptions are popular payment flows used by lots of merchants in various industries such as streaming services, Software as a Service (SaaS), and subscription services.
In this blog post, we go over the technical details of tokenizing payment details and issuing payment requests on behalf of a shopper. We’ll explain the concept of Adyen tokenization, its usage, and how you can use tokenization to implement a recurring billing service for your customers.
This post comes with an example integration in .NET that can be found on GitHub. Even though we use .NET in this example, the concepts apply to other programming languages as well.
Adyen offers payment services for businesses that operate with subscription models and other recurring payments. We receive payment requests from our merchants, and our systems try to honor the payment authorization. Depending on your use case, the implementation for subscriptions may look differently. Think about the following questions:
Let’s take a look at these questions in this blog.
If you don’t want to implement and maintain a subscription billing service yourself, we have partnerships with third-providers that offer these types of billing services. You can find our partners on our website.
With Adyen, you can securely store one or more payment details per shopper in the form of tokens. This process is what we refer to as tokenization. There are three ways you can use tokens:
In the next section, we look at the subscription use case and the flow of events that involve the cardholder, the merchant, and the Adyen platform.
1. After a Customer Initiated Transaction (CIT) we collect payment information from the cardholder.
2. The merchant sends an initial authorisation request to Adyen for tokenization.3. Adyen replies with the authorisation result.
3. Adyen replies with the authorisation result.
Note: After step 1, the shopper may be required to perform a Strong Customer Authentication (SCA) step where the shopper authenticates to the issuing bank. SCA is a European requirement introduced to make online payments more secure and reduce fraud. This requirement applies to online payments made in the European Economic Area (EEA), Monaco, and the UK. These levels of authentication involve asking customers for two of the three following: something they know, something they own, and something they are. For more details visit this self-service guide.
4. At a later point in time, Adyen sends the token and the shopper reference through an asynchronous notification (webhook) to the merchant. The merchant should save this token and the shopper reference. These are used to make future payment requests for every billing event.
5. The merchant can now, at a set interval, initiate a payment request on behalf of the customer using the token and the shopper reference. This is known as a Merchant Initiated Transaction (MIT).
Finally, the merchant receives an asynchronous notification (webhook) with the outcome of the payment request.
Let’s see this in action in our .NET integration example. In our example integration we’ve implemented two views.
The initial authorisation request is performed using the sessions endpoint. The merchant sends a payment request to Adyen, in our case using the .NET library. This is what the C# request looks like:
Note (out-of-scope): For India, we have to specify a Mandate field. See the documentation for more information on which fields to include.
Now that the shopper's payment details are collected, let’s take a look at how Adyen authorizes the initial payment request and generates the token. One thing you notice in this example, is that the merchant sends a value of “0” (zero) to Adyen.
This is known as Zero Auth and brings us to the next topic: Dynamic Zero Auth.
A typical use case is when merchants need to verify the card details and account holder without charging the shopper. This might be at the start of a trial subscription, or for a pay-as-you-go model where the shopper is only charged for what is used. By sending a Zero Auth transaction to Adyen, we can do an authorisation with a zero-amount. When this Zero-Auth is accepted, it serves as a validation to the merchant that the shopper is legitimate.
However, Zero-Auths aren’t supported by every issuer. Some issuers require specific values for these authorisations. iDeal, for example, requires an amount greater than 0. Adyen takes care of this complexity by introducing Dynamic Zero Auth (also known as Dynamic Card Validation) to prevent the refusal by automatically adjusting the value to the correct amount for the authorisation.
Finally, Adyen stores the card details safely and initializes a token (also known as the “recurringDetailReference”) that the merchant will be using to make future recurring payment requests.
When you are ready to charge the shopper for a subscription, this is what the request looks like in C#.
If the payment succeeds, the customer is charged and the service is delivered. But what if the payment request fails? This brings us to the next two topics: Real-time Account Updater and Auto Rescue.
When you submit a payment that is refused for certain refusal reasons (e.g. expired card), the Adyen Real Time Account Updater instantly checks for updated card details with the card schemes (Visa, Mastercard, etc.). If there's an update, the payment is immediately retried with the updated card details. This all happens as the payment is being processed and appears as a single transaction. The token is also automatically updated to ensure it refers to the newest details.
Adyen also automatically handles cases such as expired cards. The Adyen Batch Account Updater automatically looks up the latest card that belongs to this shopper so we can continue charging the shopper even though their old card expired.
Adyen's Auto Rescue automatically retries refused or charged back shopper-not-present transactions such as subscription renewals. It uses smart logic to decide which payments can succeed when retried later, and performs these retries at optimal times.
A payment can be refused for many reasons. In some cases, when the shopper's account has insufficient funds, the payment may still succeed when submitted again at a later point in time. In other scenarios, when the shopper's account has been closed, the payment is declined permanently.
Auto Rescue schedules retries for refused or charged back payments that have a chance of succeeding. It may take several retry attempts to rescue a payment. These attempts occur within a rescue window.
Following a successful tokenization request, Adyen sends the token via an asynchronous webhook notification. Let’s take a look at how we consume the webhook notification and obtain the token (referred here as “recurringDetailReference”) in the code. This is what the C# webhook controller looks like:
You can find our .NET integration-example on GitHub. Start the application by following the steps in the readme. Once the application is started, you'll find two views here: the shopper view and the admin panel.
You can find the stored tokens in the admin panel. Keep in mind that the application keeps the tokens in a local memory cache. Once you restart the application, the tokens are lost.
Our sample application provides you with an admin panel to make payment requests on behalf of the shopper for demo purposes only. On production it would obviously not be the case: integrate the business logic and use the .NET library to bill the customer at predefined intervals by initiating the payment request using the token and the associated shopper reference.
While implementing this myself, I ran into several errors. I’ve highlighted some of the most common issues below for troubleshooting purposes.
First, let's make sure you enable “Recurring details” in Webhooks: Under Additional Data in your Customer Area , make sure you have “Recurring details” (under “Payments”) enabled to receive the notification which contains your recurringDetailReference. This reference is used to make future payment requests. Below, you can find examples of what a successful and unsuccessful webhook looks like.
Error 803: If you get this error after trying to execute a recurring payment request, this means that the stored card details (token), indicated by the recurringDetailReference, is not available for this shopperReference.Either the recurringDetailReference doesn’t exist, or the contract type is not configured properly for this recurringDetailReference.
Double-check which flags you’re sending in the documentation. You can always check which contract types are stored for a specific shopperReference, using the paymentMethods endpoint or the listRecurringDetails endpoint.
Error 422: If you get this error with errorCode '14_019', please make sure you specify the correct recurringDetailReference in your request. The sdkVersion should automatically be provided by the library.
Admin Panel issues: If nothing is showing up in the Admin Panel after making a payment request in the Shopper View. Here’s a list of steps that may help you:
We’ve seen how you can use Adyen tokenization to implement subscriptions in .NET along with how you can:
We’re always looking for ways to improve the integration-example and scale it to multiple languages that are relevant for our merchants. Have a look at our repository today and let us know on Twitter how we can improve. Alternatively, feel free to open an issue on GitHub and we’ll get to it!
By submitting this form, you acknowledge that you have reviewed the terms of our Privacy Statement and consent to the use of data in accordance therewith.