This is the updated version of the iDEAL integration that ensures compliance with the latest iDEAL payment experience by redirecting payers to an iDEAL-hosted page for payment collection.
The legacy version of the iDEAL integration was deprecated and is no longer supported as of April 1, 2025. Use this updated integration to stay compliant with the latest iDEAL payment experience.
iDEAL is a payment method that enables customers to complete online payments using their bank credentials. It is a preferred online payment method in the Netherlands.
This tutorial guides you on using Chargebee.js to integrate iDEAL on your website, and creating a subscription after the user checks out.
Currently, Chargebee JS supports the below payment options for iDEAL:
- Stripe
- Adyen
- Mollie
Gateway prerequisites
The following is the list of requirements to fulfill before starting the integration steps.
- Enable the payment gateway of your choice:
- Stripe. Learn more.
- Adyen. Learn more.
- Mollie. Learn more.
- Configure Smart routing to select iDEAL for EUR currency.
Set up Chargebee.js
Include the Chargebee.js script on your page and initialize a Chargebee instance before you start. For the script tag, the Chargebee.init options, and the tearDown() caveat, see Set up Chargebee.js.
Create a Payment Intent
You should create a payment intent before submitting the form to authorize the payments.
payment_intent performs the essential function of tracking different events involved in a transaction. This includes:
Automatically changing its status based on the outcome of authorization and capture events.
Automatically refunding in case of an error post-payment.
A payment_intent can be created at your server-side using create a payment intent API and returned to the client side. The payment method handler uses the created payment_intent internally to perform authorization.
Here's the sample code to create a payment_intent.
This must be done from your backend to avoid exposing sensitive data.
Example:
curl https://{site-name}.chargebee.com/api/v2/payment_intents \
-u {fullaccess_api_key}: \
-d amount=500 \
-d currency_code="EUR" \
-d payment_method_type="ideal"
The above step should be initiated as a request from your frontend.
Frontend code:
function createPaymentIntent() {
return fetch('/payment-intents', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
amount: 500,
currency_code: 'EUR',
payment_method_type: 'ideal'
})
}).then(function(response) {
return response.json();
}).then(function(responseJson) {
return responseJson.payment_intent;
});
}
Load the iDEAL module
Load the iDEAL module by calling the load() method.
cbInstance.load('ideal');
Handle Payment
Use ideal as the input parameter to handlePayment function, as this enables the function to handle iDEAL payments. Chargebee takes care of redirecting users to the page meant for payment authorization.
Pass the payer's details in the paymentInfo object using the userName and userEmail fields:
userName: The payer's full name.userEmail: The email address of the payer.
These fields are required when the gateway is Stripe, which uses them to identify the payer during authorization. For Stripe, userName must match the name on the payer's bank account exactly, because Stripe uses it as the account holder name on the SEPA Direct Debit mandate. To keep your integration portable across gateways, provide both fields. For the complete list of paymentInfo properties, see the iDEAL payment handler API reference.
Chargebee JS does not support payments via in-app browsers of Instagram, Facebook and Snapchat.
cbInstance.load('ideal').then(() => {
cbInstance.handlePayment('ideal', {
paymentIntent: () => {
// Make a call to your server to create a Chargebee `payment_intent`.
return createPaymentIntent()
},
paymentInfo: {
// Required for Stripe.
userName: 'Jane Doe',
userEmail: 'janedoe@example.com'
}
}).then(intent => {
// SUCCESS!!! payment_intent is authorised.
var response = fetch('/subscriptions', {
method: 'POST',
body: JSON.stringify({
paymentIntentId: intent.id,
plan_id: 'pro_plan',
plan_quantity: 1,
billingAddress: {...}, // provide billing address
customer: {...} // provide customer details if the subscription is to be created for an existing <code>customer</code> in Chargebee.
})
}).then(function(response) {
return response.json();
});
}).catch(err => {
// OOPS!!! payment_intent is not authorised.
})
});
On successful authorization, the payment_intent turns authorized and the user is redirected back to your website.
Use webhooks for production use, instead of making the subscription creation request from the frontend, it's more secure and reliable to respond to webhooks from Chargebee on the backend. Listen to the payment_intent_updated event via webhooks and create the subscription when the payment_intent.status is authorized.
Create a subscription (server)
Pass the ID of the successfully authorized payment_intent to Chargebee’s create a subscription API.
curl https://{site}.chargebee.com/api/v2/customers/__test__8asz8Ru9WhHOJO/subscription_for_items \
-X POST \
-u {site_api_key}: \
-d payment_intent[id]="<Id of authorized payment_intent recieved in last step.>" \
-d subscription_items[item_price_id][0]="basic-EUR" \
-d subscription_items[billing_cycles][0]=2 \
-d subscription_items[quantity][0]=1 \
-d subscription_items[item_price_id][1]="day-pass-EUR" \
-d subscription_items[unit_price][1]=100
We're always happy to help you with any questions you might have! Click here to reach out to us.