Integrate iDEAL using the Orders API
Last updated: Feb 19th, 1:19am
Render payment buttons and process payments with the Orders API.
Know before you code
- Request approval to enable iDEAL by visiting these sandbox and live links:
- Sandbox: https://www.sandbox.paypal.com/bizsignup/entry?product=ideal&capabilities=IDEAL&country.x=<merchant's country>
- Live: https://www.paypal.com/bizsignup/entry?product=ideal&capabilities=IDEAL&country.x=<merchant's country>
- Partners: Be sure to onboard your merchants upfront, before they accept payments. Onboarding after making payments, specifically Progressive Onboarding, isn't supported for alternative payment methods.
- Make sure you're subscribed to the following webhook events:
PAYMENT.CAPTURE.COMPLETED
- Listen for this webhook to get notified about a successful order capture.PAYMENT.CAPTURE.DENIED
- This webhook tells you when an order capture fails.
- Make sure your preference for receiving payments in your PayPal business or merchant account is set to accept and convert to the currency in your account. In your profile, select Account Settings > Payment preferences > Block payments and click Update to mark this preference.
- 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:
- When processing iDEAL payments, you don't need to capture payment for the order.
Offer iDEAL on the checkout page
You'll need to create the user interface to offer banks through iDEAL and collect the buyer's information, then you'll use the API calls described in the remainder of this topic to:
- Create the order with buyer's
full_name,
country_code
and iDEAL as the payment source. - Redirect the buyer to iDEAL.
- Refer to Payment method icons for icons you can use and download locations.
Create an order
Use the buyer information you captured from your user interface to create an order with iDEAL as the payment source.
API endpoint used in Sample request: Create order
- Sample request
- Sample response
1curl -v -X POST 'https://api-m.sandbox.paypal.com/v2/checkout/orders' \2-H "PayPal-Request-Id: PAYPAL-REQUEST-ID" \3-H "Content-Type: application/json" \4-H "Authorization: Bearer ACCESS-TOKEN" \5-d '{6 "intent": "CAPTURE",7 "purchase_units": [8 {9 "reference_id": "d9f80740-38f0-11e8-b467-0ed5f89f718b",10 "amount": {11 "currency_code": "EUR",12 "value": "1.00"13 }14 }15 ],16 "payment_source": {17 "ideal": {18 "country_code": "NL",19 "name": "Firstname Lastname",20 "bic": "BUSINESS-IDENTIFICATION-CODE"21 }22 }23}'
Modify the code
After you copy the code in the sample request, modify the following:
ACCESS-TOKEN
- Your access token.PayPal-Request-Id
- Replace the sample ID with a unique ID you generate. This ID helps prevent duplicate authorizations in the event that the API call is disrupted. See also: API idempotencyintent
- To use an alternative payment method, this parameter must be set toCAPTURE
as it is in this sample code.payment_source
- Specifyideal
as the payment method and include the country code and account holder's full name.
Note: You can't use a business identification number (BIC) to identify the bank when you create an order using iDEAL as the payment method. Remove bic
from your request parameters, unless it is for a returning buyer, and remove any hosted pages used for bank selection.
purchase_units.amount
- Pass the amount of the order and the currency code.processing_instruction
- Set this value toORDER_COMPLETE_ON_PAYMENT_APPROVAL
as it is in this sample code.application_context
- Specify the preferred language for returned errors, the URL the buyer is returned to after approving the purchase with their selected payment method, and the URL the buyer is returned to after canceling an approval with their selected payment method. Whilereturn_url
andcancel_url
are optional fields, this integration requires you specify them to handle the handoff from the payment method back to your site. You can use thecancel_url
to redirect buyers when an error occurs while they're on the payment method's site, so make sure your cancel URL works for that situation as well as an actual cancellation by the buyer.
Note: Change or add other parameters in the Create order request body to create an order that reflects the actual order details.
Step result
A successful request results in the following:
- A return status code of HTTP
200 OK
. - A JSON response body that contains the order ID. You'll use the order ID and
payer-action
HATEOAS URL in the next step. See also: HATEOAS links.
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.
Unsuccessful confirm order request
This code sample shows an unsuccessful attempt to confirm an order without a properly onboarded merchant.
API endpoint used in the sample request: Create order
- Sample request
- Sample response
1curl -v -X POST 'https://api-m.sandbox.paypal.com/v2/checkout/orders/ORDER-ID/confirm-payment-source' \2-H "PayPal-Request-Id: PAYPAL-REQUEST-ID" \3-H "Content-Type: application/json" \4-H "Authorization: Bearer ACCESS-TOKEN" \5-d '{6 "payment_source": {7 "ideal": {8 "country_code": "NL",9 "name": "Firstname Lastname",10 "experience_context": {11 "return_url": "https://example.com/return",12 "cancel_url": "https://example.com/cancel"13 }14 }15 }16}'
Step result
This unsuccessful single-shot create order request results in the following:
- A return status code of HTTP
422 Unprocessable Entity
. - A JSON response body that passes
NOT_ENABLED_FOR_PAYMENT_SOURCE
, a description of the error, and a message thatdetails.fields.field
has an incorrect value.
Unsuccessful single-shot create order request
This code sample shows an unsuccessful attempt to create a new order and capture the payment without a properly onboarded merchant.
API endpoint used in the sample request: Create order
- Sample request
- Sample response
1curl -v -X POST 'https://api-m.sandbox.paypal.com/v2/checkout/orders' \2-H "PayPal-Request-Id: PAYPAL-REQUEST-ID" \3-H "Content-Type: application/json" \4-H "Authorization: Bearer ACCESS-TOKEN" \5-d '{6 "intent": "CAPTURE",7 "payment_source": {8 "ideal": {9 "country_code": "NL",10 "name": "Firstname Lastname",11 "experience_context": {12 "return_url": "https://example.com/return",13 "cancel_url": "https://example.com/cancel"14 }15 }16 },17 "processing_instruction": "ORDER_COMPLETE_ON_PAYMENT_APPROVAL",18 "purchase_units": [19 {20 "reference_id": "d9f80740-38f0-11e8-b467-0ed5f89f718b",21 "amount": {22 "currency_code": "EUR",23 "value": "100"24 }25 }26 ]27 }28}'
Step result
This unsuccessful single-shot create order request results in the following:
- A return status code of HTTP
422 Unprocessable Entity
. - A JSON response body that passes
NOT_ENABLED_FOR_PAYMENT_SOURCE
, a description of the error, and a message thatdetails.fields.field
has an incorrect value.
Redirect buyer for purchase approval
In your user interface, attach the payer-action
redirect URL returned in the Create Order
response to the iDEAL payment button. This sends the buyer to their bank to approve the purchase. Once the buyer approves the purchase, the payment is automatically captured.
In the sample, the redirect URL is: "https://www.sandbox.paypal.com/payment/ideal?token=5KP92830L1747245S"
.
Step result
After successfully completing the bank approval:
- The buyer is redirected to the
return_url
mentioned in the Create Order request. - The
PAYMENT.CAPTURE.COMPLETED
webhook event is triggered, which indicates that payment capture was successful.
After unsuccessful bank approval:
- The buyer is redirected to the
cancel_url
mentioned in the Create Order request.
Listen to webhooks for payment status
Listen to the following webhooks to get the result of order capture:
- The
PAYMENT.CAPTURE.COMPLETED
webhook event indicates a successful order capture. - The
PAYMENT.CAPTURE.DENIED
webhook events indicate a failed order capture. - Optional: Use Show order details endpoint to determine the status of an order.
- The
up
HATEOAS link indicates the order associated with this capture.
- The
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 Webhook Payloads
- Sample PAYMENT.CAPTURE.COMPLETED
- Sample PAYMENT.CAPTURE.DENIED
- Sample CHECKOUT.ORDER.DECLINED
1{2 "id": "WH-2B342482FC0449155-12X09416XP387753C",3 "event_version": "1.0",4 "zts": 1481046241,5 "create_time": "2022-04-08T10:37:05Z",6 "resource_type": "capture",7 "resource_version": "2.0",8 "event_type": "PAYMENT.CAPTURE.COMPLETED",9 "summary": "Payment completed for EUR 1.00 EUR",10 "resource": {11 "amount": {12 "value": "1.00",13 "currency_code": "EUR"14 },15 "create_time": "2022-04-08T10:37:05Z",16 "update_time": "2022-04-08T10:37:05Z",17 "final_capture": true,18 "seller_receivable_breakdown": {19 "paypal_fee": {20 "value": "0.20",21 "currency_code": "EUR"22 },23 "gross_amount": {24 "value": "1.00",25 "currency_code": "EUR"26 },27 "net_amount": {28 "value": "0.80",29 "currency_code": "EUR"30 }31 },32 "links": [33 {34 "method": "GET",35 "rel": "self",36 "href": "https://api-m.sandbox.paypal.com/v2/payments/captures/8SS60826HT082593F"37 },38 {39 "method": "POST",40 "rel": "refund",41 "href": "https://api-m.sandbox.paypal.com/v2/payments/captures/8SS60826HT082593F/refund"42 },43 {44 "method": "GET",45 "rel": "up",46 "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5KP92830L1747245S"47 }48 ],49 "id": "8SS60826HT082593F",50 "status": "COMPLETED"51 },52 "links": [53 {54 "href": "https://api-m.sandbox.paypal.com/v1/notifications/webhooks-events/WH-2B342482FC0449155-12X09416XP387753C",55 "rel": "self",56 "method": "GET"57 },58 {59 "href": "https://api-m.sandbox.paypal.com/v1/notifications/webhooks-events/WH-2B342482FC0449155-12X09416XP387753C/resend",60 "rel": "resend",61 "method": "POST"62 }63 ]64}
Note:
resource.supplementary_data.related_ids.order_id
parameter in the webhook payload.Alternatively, you can get the order capture result from the Show order details endpoint.
Important: Exercise caution when polling for order capture result using the Show order details endpoint. PayPal enforces rate limits on API requests.
- Sample request
- Sample response
1curl -v -X GET https://api-m.sandbox.paypal.com/v2/checkout/orders/5KP92830L1747245S \2 -H "Content-Type: application/json" \3 -H "Authorization: Bearer <Access-Token>"
Step result
A successful request returns the HTTP 200 OK
status code with a JSON response body that returns a COMPLETED
status.
A successfully captured order has the following:
- The order status as
COMPLETED
, which means the order was captured successfully. - A capture with
COMPLETED
status is present in the response parameterpurchase_units[0].payments.captures[0]
. - The
up
HATEOAS link indicates the order associated with this capture.
Notify buyer of payment success
After a successful payment, notify the buyer of a successful transaction. You can do this by sending a confirmation email.