Accept iDEAL payments
DocsCurrentLast updated: September 19th 2024, @ 11:07:28 am
iDEAL is a payment method in the Netherlands that allows buyers to select their issuing bank from a list of options. The buyer experience, once they've been handed off to the issuing bank they selected, differs depending on the bank.
Countries | Payment type | Payment flow | Currencies | Minimum amount | Refunds |
---|---|---|---|---|---|
Netherlands (NL ) | bank redirect | redirect | EUR | 0.01 EUR | Within 180 days |
How it works
- Your checkout page offers alternative payment methods.
- Buyer provides their personal details and selects an alternative payment method from your checkout page.
- Buyer is transferred from your checkout page to the third-party bank to confirm the purchase.
- Buyer authorizes and confirms payment.
- Buyer returns to your site to see confirmation of purchase.
- Merchant initiates completion of payment. PayPal moves the funds to the merchant. Transaction shows in your PayPal account with the payment method the buyer used.
Eligibility
- Available to merchants globally, except in Russia, Japan, and Brazil.
- Billing agreements, multiple seller payments, and shipping callback aren't supported.
- Support for order capture only (order authorize is not supported). See authorized and captured payments.
- Chargebacks aren't supported.
- Transaction must be an online purchase (buy online, pay in store is not supported).
Integrate
There are 2 integration paths you can take:
- JavaScript SDK: Merchants can use PayPal-hosted UI components, called payment fields, to collect payment information for alternative payment methods.
- Orders REST API: Integrate directly with the Orders API to fully customize the checkout experience.
- JavaScript SDK
- Orders API
Use the JavaScript SDK to render payment fields and buttons and process payments with the Orders API.
Buyer experience
Note: The payment button is disabled in the buyer experience demo. On button click, the user is redirected to their bank to authorize the transaction.
Know before you code
Note: Partners need to onboard merchants upfront before they accept payments. iDEAL doesn't support onboarding after making payments, specifically Progressive Onboarding.
- Complete the steps in Get started to get your sandbox account information from the Developer Dashboard:
- Client ID: Authenticates your account with PayPal and identifies an app in your sandbox.
- Client Secret: Authorizes an app in your sandbox. Keep this secret safe and don't share it.
- Business account credentials
- Make sure the preference for receiving payments in your PayPal business account is set to accept and convert them to the default currency. To verify, in your profile select Account Settings > Payment preferences > Block payments and select Update to mark this preference.
- This client-side and server-side integration uses the following:
Note: The integration steps for implementing alternative payment methods are similar. If you've integrated another alternative payment method before, you can likely reuse that code with adjustments for this payment method.
- Make sure you're subscribed to the following webhook events:
CHECKOUT.ORDER.APPROVED
- Listen for this webhook and then capture the payment.CHECKOUT.PAYMENT-APPROVAL.REVERSED
- This webhook tells you when an approved order is cancelled and refunded because it wasn't captured within the capture window. Let the payer know about the problem and the reversed order.
- By adding funding sources to your checkout integration, you agree to the PayPal alternative payment methods agreement. This is in addition to the user agreement applicable to the country in which your business is physically located.
- Request approval to enable iDEAL by visiting these Sandbox and Live links. Replace
MERCHANT-COUNTRY
in the URL with the 2-character country code for the merchant's country of operation:- Sandbox:
https://www.sandbox.paypal.com/bizsignup/entry?product=ideal&capabilities=IDEAL&country.x=MERCHANT-COUNTRY
- Live:
https://www.paypal.com/bizsignup/entry?product=ideal&capabilities=IDEAL&country.x=MERCHANT-COUNTRY
- Sandbox:
Use Postman to explore and test PayPal APIs.
Get up and running in GitHub Codespaces
GitHub Codespaces are cloud-based development environments where you can code and test your PayPal integrations. Learn more
1. Add PayPal JavaScript SDK
Add or update the JavaScript SDK script on your web page.
<script src="https://www.paypal.com/sdk/js?client-id=YOUR_CLIENT_ID&components=buttons,payment-fields,marks,funding-eligibility&enable-funding=ideal¤cy=EUR"></script>
This table lists the parameters you pass to the JavaScript SDK.
Query param | Default | Description |
client-id
|
none | Your PayPal REST client ID. This identifies your PayPal account and determines where transactions are paid. |
components
|
buttons
|
A comma-separated list of components to enable. The buttons , payment-fields , marks , and funding-eligibility components are required for payment fields components.
|
enable-funding
|
none | The enabled payment methods to show in buttons and marks.
Note: By default, PayPal JavaScript SDK provides smart logic to display only appropriate marks and buttons for the current buyer. This optional parameter bypasses the buyer country check for desired payment methods. For example: |
currency
|
USD
|
This is the currency for the payment. This value needs to match the currency used when creating the order. |
locale
|
automatic | The locale renders components. By default PayPal detects the correct locale for the buyer based on their geolocation and browser preferences. It is recommended to pass this parameter with a supported locale if you need the PayPal buttons to render in the same language as the rest of your site. |
intent
|
capture
|
The intent for the transaction. This determines whether the funds are captured immediately while the buyer is present on the page. |
commit
|
true
|
This indicates that the final amount won't change after the buyer returns to your site from PayPal. |
vault
|
false
|
Whether the payment information in the transaction will be saved. Save your customers' payment information for billing agreements, subscriptions, or recurring payments. Marking this parameter false shows all funding sources, including payment methods that can't be saved.
|
See additional, optional parameters.
2. Render payment mark
You can use a mark integration for payment fields components to present the payment method options to the buyer as radio buttons.
paypal
.Marks({
fundingSource: paypal.FUNDING.IDEAL,
})
.render("#ideal-mark");
3. Render payment fields
Use payment fields to collect payment information from buyers. Fields dynamically render based on the selected funding source and you can customize the fields to align with your brand.
Choose from a single page checkout flow or a multi-page checkout flow.
- Single page
- Multi-page
If there are validation errors in the input fields, they'll show on the click of the button.
paypal
.PaymentFields({
fundingSource: paypal.FUNDING.IDEAL,
/* style object (optional) */
style: {
/* customize field attributes (optional) */
variables: {},
/* set custom rules to apply to fields classes (optional) */
rules: {},
},
fields: {
/* fields prefill info (optional) */
name: {
value: "Firstname Lastname",
},
},
})
.render("#ideal-container");
For style
parameters, please reference this style page: Custom style for payment fields
4. Render payment button
paypal
.Buttons({
fundingSource: paypal.FUNDING.IDEAL,
style: {
label: "pay",
},
createOrder() {
return fetch("/my-server/create-paypal-order", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
// use the "body" param to optionally pass additional order information
// like product skus and quantities
body: JSON.stringify({
cart: [
{
sku: "YOUR_PRODUCT_STOCK_KEEPING_UNIT",
quantity: "YOUR_PRODUCT_QUANTITY",
},
],
}),
})
.then((response) => response.json())
.then((order) => order.id);
},
onApprove(data) {
return fetch("/my-server/capture-paypal-order", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
orderID: data.orderID,
}),
})
.then((response) => response.json())
.then((orderData) => {
// Successful capture! For dev/demo purposes:
console.log(
"Capture result",
orderData,
JSON.stringify(orderData, null, 2),
);
const transaction = orderData.purchase_units[0].payments.captures[0];
console.log("Transaction Status:", transaction.status);
console.log("Transaction ID:", transaction.id);
// When ready to go live, remove the alert and show a success message within this page. For example:
// const element = document.getElementById('paypal-button-container');
// element.innerHTML = '<h3>Thank you for your payment!</h3>';
// Or go to another URL: window.location.href = 'thank_you.html';
});
},
onCancel(data, actions) {
console.log(`Order Canceled - ID: ${data.orderID}`);
},
onError(err) {
console.error(err);
},
})
.render("#ideal-btn");
createOrder
Implement the
createOrder
function to allow the JavaScript SDK to submit buyer information and set up the transaction on the click of the button.Note: iDEAL requires orders to be created in a currency of EUR.
Use your server-side Create order call to set up the details of a one-time transaction including the amount, line item detail, and more.
If order creation fails, the Orders API can return an error in the console.
After order creation, orders are confirmed with buyer-selected payment source. If the order cannot be processed with the selected payment source, the relevant errors are returned in the console.
onCancel
Implement the optional
onCancel()
function to show a cancellation page or return to the shopping cart.onError
Implement the optional
onError()
function to handle errors and display generic error message or page to the buyers. This error handler is a catch-all. Errors at this point are not expected to be handled beyond showing a generic error message or page.
5. Capture the transaction
Implement the onApprove
function, which is called after the buyer approves the transaction.
Captures the funds from the transaction and shows a message to the buyer to let them know the transaction is successful. The method is called after the buyer approves the transaction on paypal.com.
Because this is a client-side call, PayPal calls the Orders API on your behalf, so you don't need to provide the headers and body.
capture()
- Promise returning the order details.
paypal
.Buttons({
fundingSource: paypal.FUNDING.IDEAL,
createOrder() {
return fetch("/my-server/create-paypal-order", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
// use the "body" param to optionally pass additional order information
// like product skus and quantities
body: JSON.stringify({
cart: [
{
sku: "YOUR_PRODUCT_STOCK_KEEPING_UNIT",
quantity: "YOUR_PRODUCT_QUANTITY",
},
],
}),
})
.then((response) => response.json())
.then((order) => order.id);
},
onApprove(data) {
return fetch("/my-server/capture-paypal-order", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
orderID: data.orderID,
}),
})
.then((response) => response.json())
.then((orderData) => {
// Successful capture! For dev/demo purposes:
console.log(
"Capture result",
orderData,
JSON.stringify(orderData, null, 2),
);
const transaction = orderData.purchase_units[0].payments.captures[0];
console.log("Transaction Status:", transaction.status);
console.log("Transaction ID:", transaction.id);
// When ready to go live, remove the alert and show a success message within this page. For example:
// const element = document.getElementById('paypal-button-container');
// element.innerHTML = '<h3>Thank you for your payment!</h3>';
// Or go to another URL: window.location.href = 'thank_you.html';
});
},
})
.render("#ideal-button-container");
//This function displays payment buttons on your web page.
For the capture call details and example responses, see Capture payment for order in the Orders API reference.
If order capture fails, the Orders API can return an error in the console.
6. Handle webhook events
A webhook handler is a script you create on your server that completes specific actions on webhooks that hit your listener URL.
- We recommend subscribing to the
CHECKOUT.ORDER.APPROVED
webhook event in case a customer accidentally closes the browser and exits the checkout process after approving the transaction through their APM but before finalizing the transaction on your site. - We also recommend subscribing to the
CHECKOUT.ORDER.DECLINED
webhook event to receive notifications of any other failure scenarios. This webhook event passes a failure reason code and error message to indicate what caused the error. - Listen for the
CHECKOUT.PAYMENT-APPROVAL.REVERSED
webhook as an indication that an approved order wasn't captured within the capture window resulting in a cancellation of the order and a refund the buyer's account. Then notify your buyer of the problem and the reversed order. PAYMENT.CAPTURE.PENDING
,PAYMENT.CAPTURE.COMPLETED
, andPAYMENT.CAPTURE.DENIED
webhooks indicate capture status.
See Subscribe to checkout webhooks for more information.
Here are some additional resources as you create webhook handler code:
- Webhook Management API - Manage webhooks, list event notifications, and more.
- Webhook events
- Checkout webhook events - Checkout buyer approval-related webhooks.
- Order webhook events - Other order-related webhooks.
- Show order details endpoint - Determine the status of an order.
Sample integration
See a sample iDEAL integration in the PayPal GitHub repository.
Merchant onboarding payment error
Partners need to onboard merchants upfront before they accept payments. iDEAL doesn't support onboarding after making payments, specifically Progressive Onboarding. See the Onboard a merchant section for more details.
When you submit an order with ideal
as the payment_source
, and the merchant isn't onboarded, you get the following error message:
The 'API caller' and/or 'payee' is not set up to be able to process the selected payment source. If you have already completed the required steps, please allow 2 business days for PayPal to complete the setup. If you continue to receive this error, please contact your Account Manager or check status at https://www.paypal.com/businessmanage/account/payments.
Onboard a merchant
For merchants operating in AT
, AU
, BE
, BG
, CA
, CY
, CZ
, C2
, DE
, DK
, EE
, ES
, FI
, FR
, GR
, HU
, IE
, IT
, LI
, LT
, LU
, LV
, MT
, NL
, NO
, PL
, PT
, RO
, SE
, SI
, SK
, UK
, and US
:
- Step 1: Your merchant needs to complete production onboarding to process iDEAL payments with their PayPal account, or go here.
- Step 2: Your merchants can check the onboarding status in their PayPal account.
Note: Partners can use the Integrated Sign Up (ISU) flow to onboard their merchants:
- Send an API call to the Partner Referral API at
https://developer.paypal.com/docs/api/partner-referrals/v2/
.- Pass iDEAL in the products array. If you pass iDEAL in the capabilities array, the request will return an error.
For merchants in the rest of the world, you need to use offline onboarding:
- Step 1: Your merchant needs to complete Critical Infrastructure Protection (CIP) using their PayPal account.
- Step 2: Enable iDEAL for your merchant by working with your Customer Success Manager or Sales team representative.
Important: Ensure that the merchant includes their website URL in their PayPal account.