3DS supported Adyen.js Integration with Chargebee APIs

Watch Video

Tutorial Scope 

This tutorial will address the specifics of implementing card payments with 3D Secure flow and creating a subscription in Chargebee, using Adyen's Web Components, integrated through Chargebee.js and Chargebee APIs.

Adyen.js: Overview 

Adyen  is a payment solution that processes payments from all over the world. The card details are captured and tokenized on your side by Adyen's javascript library, and the token is sent to Chargebee. To know more, click Adyen documentation .

Adyen does not provide an option to retrieve the details of an object, which makes the integration process difficult. Also, Adyen requires you to set identifiers like unique transaction reference (Transaction ID) during the initial payment processing step, increasing complexity. Therefore, we have mandated the use of Chargebee.js helper function even if you want to use Adyen.js with Adyen Web Components to make the integration process more manageable and smoother. Without Chargebee.js, the integration will not work correctly.

We have implemented 3DS support for the latest version of Adyen.js using Chargebee.js 3DS helper module. If you are using Adyen's CSE (Client-Side Encryption), you need to adopt the latest version of Adyen.js to avail Chargebee's 3DS helper JS. To know more about versions in Adyen, see Adyen Release Notes  filtered by version.

Alternatively, you can also integrate with Adyen using Chargebee's Components and Hosted Fields. For more details, see Chargebee documentation .
Refer to our 3DS helper JS implementation guide  to rewire your Adyen.js integration and accommodate 3DS.

Overview 

Here's a detailed overview of how the Adyen.js and Chargebee 3DS checkout flow works:

  • After the customer is led to the checkout page, Adyen web components are used to collect the card details of the customer.
  • When the customer submits the payment form, Adyen passes this information to Chargebee.js to perform the 3DS flow.
  • Chargebee uses the 3DS-verified token to create a payment intent.
  • When the payment intent is authorized, it is used to create a subscription in Chargebee using the create subscription API .

Prerequisites 

Before trying out this tutorial, you need to setup the following:

Client-Side Implementation 

Step 1: Get available payment methods

Start by getting a list of the available payment methods of the customers based on their country, device, and payment amount.
From your server, make a POST / paymentMethods  request to Adyen to get a list of payment methods available, specifying:

  • Merchant Account - The merchant account name

  • Amount - The currency and value of the payment

  • Country Code - Customers country code. This is used to filter the list of available payment methods.

Request: Here is a sample request to get the available payment methods:

curl https://checkout-test.adyen.com/v67/paymentMethods \
-H "x-API-key: YOUR_X-API-KEY" \
-H "content-type: application/json" \
-d '{
  "merchantAccount": "YOUR_MERCHANT_ACCOUNT",
  "countryCode": "NL",
  "amount": {
    "currency": "EUR",
    "value": 1000
  },
  "channel": "Web",
  "shopperLocale": "nl-NL"
}'

Response

{
 "paymentMethods":[
  {
    "details":[...],
    "name":"Credit Card",
    "type":"scheme"
    ...
  },
  {
    "details":[...],
    "name":"SEPA Direct Debit",
    "type":"sepadirectdebit"
  },
  ...
  ]
}

Pass the response to your front end to show a list of available payment methods.

Step 2: Build the checkout form

Next, use the Adyen web components to render the payment method and collect the payment details of the customer. Install the Adyen Web Component's node package or use a <script> tag. Click Adyen's documentation  to know more about the web components.

  • Include the script in the <body> above any other JavaScript in your checkout page. Use the script from Adyen documentation .

Sample Script

  • php
  • Ruby
  • Java
  adyen_wc_3ds/index.html  -   View full code
<script src="https://checkoutshopper-test.adyen.com/checkoutshopper/sdk/4.7.3/adyen.js" integrity="sha384-YiT4BfPwbplFwUnpDjm2rmWCvpzdi6+l+1E+J9JKTB3CYyKbbwJ8ghkUheQf79X9" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://checkoutshopper-test.adyen.com/checkoutshopper/sdk/4.7.3/adyen.css" integrity="sha384-X1zQUhO5NGWdMQmDcuv2kyQK65QR7/VJtNthEImZm7jOvOEicQrnVijI0n9DcHkF" crossorigin="anonymous" />
<!-- Adyen provides the SRI hash that you can include as the integrity attribute.-->
<!-- Refer to their release notes to get the SRI hash for the specific version: https://docs.adyen.com/online-payments/release-notes -->

  • Create a DOM element on your checkout page, placing it where you want the payment method form to be rendered.
  • php
  • Ruby
  • Java
  adyen_wc_3ds/index.html  -   View full code
<div id="component-container"></div>
  • Create a configuration object with the below parameters and use that configuration object to create an instance of Adyen checkout. Then use the checkout.create to create and mount an instance of the payment method component. To know more about configuration objects in Adyen, click here. 

OnSubmit, create a function handleChargebeeFlow(), use this function to pass in the tokenized card information to Chargebee.

  • php
  • Ruby
  • Java
  adyen_wc_3ds/index.html  -   View full code
function handleOnChange(state, component) {
    state.isValid; // True or false. Specifies if all the information that the shopper provided is valid.
    state.data; // Provides the data that you need to pass in the `/payments` call.
    component; // Provides the active component instance that called this event.
}

function handleOnAdditionalDetails(state, component) {
    state.data; // Provides the data that you need to pass in the `/payments/details` call.
    component; // Provides the active component instance that called this event.
}

const configuration = {
    locale: "en_US", // The shopper's locale. For a list of supported locales, see https://docs.adyen.com/online-payments/components-web/localization-components.
    environment: "test", // When you're ready to accept live payments, change the value to one of our live environments https://docs.adyen.com/online-payments/components-web#testing-your-integration.
    clientKey: "test_GLYLHBKR7FEADBZPLHKLVGY2DAP2A667", // Your client key. To find out how to generate one, see https://docs.adyen.com/development-resources/client-side-authentication. Web Components versions before 3.10.1 use originKey instead of clientKey.
    paymentMethodsResponse: paymentMethodsResponse, // The payment methods response returned in step 1.
    onChange: handleOnChange, // Your function for handling onChange event
    showPayButton: true,
    onSubmit: handleChargebeeFlow,
    amount: {
        // Optional. Used to display the amount in the Pay Button.
        value: 900,
        currency: "USD",
    },
    onAdditionalDetails: handleOnAdditionalDetails, // Your function for handling onAdditionalDetails event
};

For example, here is how you would mount the Card Component using any CSS Selector, card.

  • php
  • Ruby
  • Java
  adyen_wc_3ds/index.html  -   View full code
const checkout = new AdyenCheckout(configuration);
const card = checkout.create("card");
card.mount("#component-container");

Step 3: Set Up Chargebee Js

Follow these steps to pass the card component to Chargebee.js to complete the 3DS.

  • Insert the Chargebee.js into your application.

Include the following script into your HTML page.

  • php
  • Ruby
  • Java
  adyen_wc_3ds/index.html  -   View full code
<script src="https://js.chargebee.com/v2/chargebee.js"></script>

  • Initialize the Chargebee Instance

Inside your JavaScript code, initialise Chargebee once the page is loaded and store the Chargebee instance in a variable. Further you can use this to create a 3DS handler.

  • php
  • Ruby
  • Java
  adyen_wc_3ds/index.html  -   View full code
let chargebeeInstance = Chargebee.init({
    site: "acme-test",
    publishableKey: "test__"
});
// You can access the above created instance anywhere using the following code
let chargebeeInstance = Chargebee.getInstance();

Step 4: 3D Secure Check

Load 3DS handler

This function will load the 3DS-helper  module and initializes the 3DS handle object. You can use this approach to load the 3DS-helper module.

  • php
  • Ruby
  • Java
  adyen_wc_3ds/index.html  -   View full code
chargebeeInstance.load3DSHandler()

Set Payment Intent

Use this function to set paymentIntent that was created on your server-side. The paymentIntent will contain information about the payment gateway and the amount that needs to be charged.

Note
  • Pass Adyen checkout instance while setting up payment intent on the 3DS Handler. Learn more 
  • If the amount/currency gets changed during the checkout process, use the Update a payment intent API to update properties on a PaymentIntent object. Learn more 
  • php
  • Ruby
  • Java
  adyen_wc_3ds/index.html  -   View full code
threeDSHandler.setPaymentIntent(response, {
    adyen: checkout
});

Handle Payment Intent

Call this function to initiate 3DS flow  for the entered card details. Based on the Issuing Bank and gateway settings, the 3DS flow or challenge flow may be initiated or skipped. After a successful 3DS authorization, paymentIntent will be marked as authorized. This paymentIntent ID can then be used to create subscriptions or create payment methods. To know more about the parameters used in handleCardPayment, click here 

Note

Adyen card component needs to pass as payment info.

Return value: Authorized paymentIntent object

  • php
  • Ruby
  • Java
  adyen_wc_3ds/index.html  -   View full code
let payment_info = {};
payment_info.element = card;
let additionalData = {};
additionalData.billingAddress =
    firstName: "John",
    lastName: "Doe",
    phone: "+234567890",
    addressLine1: "PO Box 9999",
    addressLine2: "",
    addressLine3: "",
    city: "Walnut",
    state: "California",
    stateCode: "CA",
    countryCode: "US",
    zip: "91789",

};
payment_info.additionalData = additionalData;
let callbacks = {
change: function(intent) {
// Triggers on each step transition
console.log("Data Changed");
},
success: function(intent) {
// Triggers when card is 3DS authorized
create_subscription(intent);
},
error: function(intent, error) {
// Triggers when 3DS authorization fails
console.log("3DS Authorization failed");
console.log(error);
},
};
threeDSHandler.handleCardPayment(payment_info, callbacks);

Example

  • php
  • Ruby
  • Java
  adyen_wc_3ds/index.html  -   View full code
{
    "amount": 9999999,
    "created_at": 1630489992,
    "currency_code": "USD",
    "expires_at": 1630491792,
    "gateway": "adyen",
    "gateway_account_id": "gw_16BjrWSedpvrr2KJh",
    "id": "AzZlysShkfqRT2KiaW5mUzjwmOU02t1FUlVB6Hcd9bZKjeOBV3",
    "modified_at": 1630489992,
    "object": "payment_intent",
    "payment_method_type": "card",
    "status": "authorized"
}

To create a subscription in Chargebee, the Payment Intent has to be in an Authorized state. On receiving a successful response, the 3DS is authorized and you can move on to create a subscription in Chargebee.

Server-Side Implementation 

Step 1: Set up Chargebee's Client Library

Download and import  the client library of your choice. Configure the client library with the Chargebee Test site and its full-access API Key. 

Step 2: Create a Chargebee Payment Intent

A paymentIntent must be created at your server using create paymentIntent API  and returned to the client-side. 3DS handler uses the created paymentIntent internally to perform 3DS authorization.

While creating the paymentIntent, you need to specify the amount that needs to be charged from the customer. You can also choose to specify which gateway needs to be used for this charge.

Before you create the paymentIntent, you need to configure Adyen  in Chargebee. Make sure you have 3DS enabled in your Chargebee Test Site.

Here's the sample code to create a payment_intent

curl  https://{site-name}.chargebee.com/api/v2/payment_intents \
     -u {fullaccess_api_key}:\
     -d amount=500 \
     -d currency_code="EUR"
     -d gateway_account_id=""
     -d payment_method_type=""

Response

{"payment_intent": {
    "amount": 5000,
    "created_at": 1517501515,
    "currency_code": "USD",
    "expires_at": 1517503315,
    "gateway": "chargebee",
    "gateway_account_id": "gw___test__KyVnGlSBWTQeudG",
    "id": "__test__KyVnHhSBWTQz2Cu__test__0DZayCQMcAwDkEIPpUrGwkiyL25s7W1X",
    "modified_at": 1517501515,
    "object": "payment_intent",
    "payment_method_type": "card",
    "status": "inited"
}}

Step 3: Creating a Subscription

To create a subscription in Chargebee, the[Chargebee Payment Intent]fetched earlier has to be passed along with other POST parameters (from the checkout page's form submit an event), using the create subscription API .

Sample request to create a subscription in Chargebee

curl  https://<site-name>.chargebee.com/api/v2/subscriptions \
     -u {full_access_api_key}:\
     -d payment_intent[id]="<Id of authorized payment_intent recieved in last step.>"
     -d plan_id="pro_plan"\
     -d plan_quantity: 1\
     -d customer[first_name]="John" \
     -d customer[last_name]="Doe" \
     -d customer[email]="[email protected]" \
     -d customer[allow_direct_debit]=true \
     -d billing_address[first_name]="John" \
     -d billing_address[last_name]="Doe" \
     -d billing_address[line1]="PO Box 9999" \
     -d billing_address[city]="Walnut" \
     -d billing_address[state]="California" \
     -d billing_address[zip]="91789" \
     -d billing_address[country]="US"

Though the parameters have been validated at the client-side, for additional security, we strongly recommend that you perform these validations on the server-side as well.

Chargebee Response

  • Chargebee returns a successful response in the JSON format that is wrapped in the form of a 'result' class by the client library.

  • In case of an error, Chargebee returns an error response, which is an exception thrown by the client library.

In case of successful checkout, you can redirect the user to a simple Thank You page.

Validation and Error-Handling 

Here's how we validate user inputs and handle API call errors in this demo:

  • Client-Side Validation: Chargebee uses the jQuery form validation  plugin to verify whether the user's field inputs(email, zip code, and phone number) are valid or not.

  • Server-Side Validation: As this is a demo application we have skipped the server-side validation for all input parameters. However, we recommend you perform the validation at your end.

  • Payment Errors: If a payment fails due to card verification or processing errors, Chargebee returns an error response which is returned as a payment exception by the client library. Exceptions are handled in the demo application with appropriate error messages.

  • General API Errors: Chargebee might return error responses due to various reasons such as invalid configuration, bad requests, etc. To identify specific reasons for all error responses you can check the API documentation . Also, take a look at the error handler file to check how these errors can be handled.

Test Cards 

When you're all set, test your integration with some test transactions. Here are some credit card numbers that you can use to test the application:

 Card Type

  Card Number

 Expiry Date 

  Security Code 

 American Express

  3714 4963 5398 431

   03/2030

         7373

 Visa

  4917 6100 0000 0000

   03/2030

          737

For more test cards, click here .