Payment-method icon

PayPal Express Checkout

Render a PayPal Express Checkout button for one-click checkout.

You can render a PayPal Express Checkout button anywhere on your site, like a product page, to let shoppers pay without going to an additional checkout page.

PayPal Checkout Shortcut on HPP is deprecated. If you use HPP, upgrade your integration and use the instructions here to implement PayPal Express Checkout. You must do this before May 1st, 2025. Contact our Support Team or your account manager if you have questions.

Requirements

Try it out!

Implement the PayPal Web Component. PayPal Express Checkout is supported from v5.59.0 and later.

How it works

  1. When the shopper selects the PayPal Express Checkout button, the Component makes a /payments request.
  2. The Component shows a PayPal lightbox either with the delivery methods for the shopper's default delivery address or without delivery methods.
  3. Depending on how you present the lightbox, the final payment amount can change when there is a change in delivery details. For example:
    • If you show the lightbox with delivery methods, and the shopper selects a different delivery method, or changes the delivery address.
    • If you show the lightbox without delivery methods, and the shopper changes the delivery address.
  4. If the final payment amount changes, you update the amount and send it to Adyen.
  5. The Component makes a /payments/details request to authorize the payment.
  6. When the payment is completed in the PayPal lightbox, the Component receives the shopper's payment information from PayPal.

If you use the Advanced flow, you can additionally implement a review page where your shopper can review and confirm their payment. To learn about this flow and the setup, refer to Add a payment review page.

PayPal Lightbox with delivery methods:

PayPal Lightbox without delivery methods:

Set up PayPal express

Step 1: Store the PSP reference

When the shopper selects the PayPal Express Checkout button, the onSubmit callback is triggered and your server makes a /payments request.

The /payments response contains the pspReference field. Store the PSP reference in your back end.

Step 2: Implement the API endpoint to update PayPal orders

Integrate an additional endpoint to update PayPal orders.

Depending on how you present the PayPal lightbox, the final payment amount can change:

  • PayPal lightbox with delivery methods: you show the delivery methods for the shopper's default delivery address. If your shopper changes their delivery address, or selects a different delivery method, the delivery fees may change the final payment amount.
  • PayPal lightbox without delivery methods: you show the default delivery address of the shopper. If your shopper changes their delivery address, the final payment amount may change.

If the payment amount does not change, no additional action is required.

If the payment amount changes, update it and send it to Adyen. To update the payment amount, make a POST  /paypal/updateOrder request, including the following parameters:

Parameter Required Description
pspReference -white_check_mark- The pspReference from the /payments response.
paymentData -white_check_mark- The paymentData that you received to your front end. The value of this parameter changes each time you make a /paypal/updateOrder request.
Use the paymentData retrieved from the Component.
amount -white_check_mark- The currency and value of the final payment amount including the delivery fees, in minor units.
deliveryMethods Only for PayPal lightbox with delivery methods The array that lists the delivery methods available for the delivery address and their fees. Use the selected field to specify the chosen delivery method by setting it to true.

Below is an example to update the payment amount if you present the PayPal lightbox with delivery methods. In this example, the original item costs EUR 110 and the selected delivery method costs EUR 10.

Update payment amount with delivery methods
Expand view
Copy link to code block
Copy code
Copy code
curl https://checkout-test.adyen.com/checkout/v71/paypal/updateOrder \
-H 'x-api-key: ADYEN_API_KEY' \
-H 'content-type: application/json' \
-d '{
"pspReference": "DZ4DPSHB4WD2WN82",
"paymentData": "XYZ...",
"amount": {
"currency": "EUR",
"value": 12000
},
"deliveryMethods": [
{
"reference": "1",
"description": "Express Shipping",
"type": "Shipping",
"amount": {
"currency": "EUR",
"value": 1000
},
"selected": true
},
{
"reference": "2",
"description": "Standard Ground",
"type": "Shipping",
"amount": {
"currency": "EUR",
"value": 500
},
"selected": false
}
]
}'

Below is an example to update the payment amount if you present the lightbox without delivery methods:

Update payment amount without delivery methods
Expand view
Copy link to code block
Copy code
Copy code
curl https://checkout-test.adyen.com/checkout/v71/paypal/updateOrder \
-H 'x-api-key: ADYEN_API_KEY' \
-H 'content-type: application/json' \
-d '{
"pspReference": "HWL5D5BDLSGLNK82",
"paymentData": "XYZ...",
"amount": {
"currency": "EUR",
"value": 12000
}
}'

In the response, you get an updated paymentData. Pass the new value to your front end. The Component needs it to complete the payment.

Example successful update response
Expand view
Copy link to code block
Copy code
Copy code
{
"paymentData": "ABC...",
"status": "success"
}

If your request fails, you receive a response that contains an errorCode. Use the errorType and message fields to troubleshoot the error.

Example failed update response
Expand view
Copy link to code block
Copy code
Copy code
{
"status": 422,
"errorCode": "000",
"message": "Only 1 deliveryMethod should be selected",
"errorType": "validation",
"pspReference": "DZ4DPSHB4WD2WN82"
}

Step 3: Add additional PayPal configuration

In the PayPal configuration object, set the property isExpress to true.

Configure isExpress
Expand view
Copy link to code block
Copy code
Copy code
const payPalConfiguration = {
isExpress: true
// ... Your other configurations.
}

Step 4: Handle delivery address changes

Implement the onShippingAddressChange event in your PayPal configuration object. The event is triggered when the PayPal lightbox opens. You make an initial POST /paypal/updateOrder request.

  • PayPal lightbox with delivery methods: with your initial request, you pass the available delivery methods to Adyen, based on the shopper's default shipping address.
  • PayPal lightbox without delivery methods: with your initial request, you pass the current payment amount to Adyen.

If your shopper changes their delivery address, the onShippingAddressChange event is triggered again. For the PayPal lightbox with delivery methods, you then need to handle the delivery method changes. For the PayPal lightbox without delivery methods, you make a POST  /paypal/updateOrder request to update the final amount.

Implement your own function to make a /paypal/updateOrder request and update the amount. Below is an example that uses the updatePayPalOrder function. You need to pass the updated paymentData you get in the response to the Component.

Implement onShippingAddressChange
Expand view
Copy link to code block
Copy code
Copy code
const payPalConfiguration = {
isExpress: true,
onShippingAddressChange: async function(data, actions, component) {
// Example: not shipping to NL.
if (data.shippingAddress.countryCode == 'NL') {
return actions.reject();
}
// Get the current paymentData value stored within the Component.
const currentPaymentData = component.paymentData;
// Implement the code to call your backend endpoint to update the final amount based on the selected delivery method, passing the paymentData.
const { paymentData } = await updatePayPalOrder(data.shippingAddress, currentPaymentData);
// Update the Component paymentData value with the new one.
component.updatePaymentData(paymentData);
},
// ... Your other configurations.
}

Step 5: Handle delivery method changes

This step is only required if you present default delivery methods when the PayPal lightbox opens.

Implement the onShippingOptionsChange event in your PayPal configuration object to handle situations where the shopper selects a different delivery method.

Make a POST /paypal/updateOrder request. In your request, specify the chosen delivery method by setting selected:true, and update the amount.value based on the selected delivery method.

Implement onShippingOptionsChange
Expand view
Copy link to code block
Copy code
Copy code
const payPalConfiguration = {
isExpress: true,
onShippingAddressChange: function(data, actions, component) {...},
onShippingOptionsChange: async function(data, actions, component) {
// Example: PostNL is unavailable.
if (data.selectedShippingOption.label.includes('PostNL')) {
return actions.reject(data.errors.METHOD_UNAVAILABLE);
}
// Get the current paymentData value stored within the Component.
const currentPaymentData = component.paymentData;
// Implement the code to call your backend endpoint to update the final amount based on the selected delivery method, passing the paymentData.
const { paymentData } =await updatePayPalOrder(data.selectedShippingOption, currentPaymentData)
// Update the Component paymentData value with the new one.
component.updatePaymentData(paymentData);
}
},
// ... Your other configurations.
}

Step 6: Get the shopper's payment information

After the shopper completes the payment in the PayPal lightbox and the lightbox closes, you can get the shopper's payment information.

How you do this depends on the Web Component version you are using:

When the lightbox closes, the Component triggers the onAuthorized callback.

Implement the onAuthorized callback in your PayPal configuration object to get the information, using the following properties:

Property Description
data The raw event received from PayPal that contains the shopper details in the authorizedEvent object, the billingAddress, and the deliveryAddress. The Component formats the details for compatibility with the Checkout API.
actions
  • actions.resolve(): continues the flow.
  • actions.reject(): cancels the flow.

You can use the shopper's details to manage the order. For example, use the shopper's name and delivery address for the shipping label.

Implement onAuthorized
Expand view
Copy link to code block
Copy code
Copy code
const payPalConfiguration = {
isExpress: true,
onShippingAddressChange: function(data, actions, component) {...},
onShippingOptionsChange: function(data, actions, component) {...}, // Only if you need to handle delivery method changes.
onAuthorized: (data, actions) => {
// You can use the shopper's details to manage the order.
actions.resolve();
},
// ... Your other configurations.
}

Step 7: Submit additional payment details

If you want to present an additional payment review page where your shopper can review their payment details, skip this step and follow the steps to add a payment review page instead.

In your AdyenCheckout configuration, or in the paypalConfiguration object, implement the onAdditionalDetails callback, which makes a POST /payments/details request to authorize the payment. In your request, include the following fields:

  • details: the state.data.details from the onAdditionalDetails event.
  • paymentData: the state.data.paymentData from the onAdditionalDetails event.
Implement onAdditionalDetails
Expand view
Copy link to code block
Copy code
Copy code
onAdditionalDetails: async (state, component) => {
const response = await makePaymentDetailsCall(state);
// The rest of your implementation.
}

Below is an example /payments/details request to authorize the payment:

Make a /payments/details request
Expand view
Copy link to code block
Copy code
Copy code
curl https://checkout-test.adyen.com/checkout/v71/payments/details \
-H 'x-api-key: ADYEN_API_KEY' \
-H 'content-type: application/json' \
-d '{
"details: {
billingToken: null,
facilitatorAccessToken: "1WP6839J5ZKOIZ57aMZ",
payerID: "9DNS6DJFHS4NC",
orderID: "8515681150749290",
paymentID: "1WPF9J5ZKOIZH8MZ",
paymentSource: "paypal"
},
"paymentData":"ABC..."
}'

Add a payment review page

After the PayPal lightbox is closed, you can optionally display an order review page that contains the details of the payment, including the delivery method the shopper selected in the PayPal lightbox.

If you implement a review page, the onShopperDetails callback is triggered when the shopper proceeds to review the order instead of when the payment is completed in the PayPal lightbox.

Follow the steps below after you have followed the guide to set up PayPal express until the Submit additional payment details step.

Step 1: Enable the review page flow

In the PayPal configuration object, add the userAction: continue configuration to enable the review page flow.

Configure userAction
Expand view
Copy link to code block
Copy code
Copy code
const payPalConfiguration = {
isExpress: true,
userAction: 'continue'
// ... Your other configurations.
}

Step 2: Create a review page

Use the shopper details you collected to present a review page that contains:

  • An order summary
  • Delivery address and method
  • Details of the total amount, showing the breakdown of the order total and delivery fees
  • A Pay button to confirm the payment

Step 3: Redirect shopper to the review page

In your AdyenCheckout configuration, or in the paypalConfiguration object, implement the onAdditionalDetails event to collect the final payment data and to redirect your shopper to the review page. You then use the final payment data to finalize the payment in the review page.

Below is an example that uses the storePaymentData and redirectShopperToReviewPage functions.

When the onAdditionalDetails event is triggered, you get a state.data object. Store this value as you need it to submit additional payment details later.

Configure userAction
Expand view
Copy link to code block
Copy code
Copy code
onAdditionalDetails: async (state, component) => {
storePaymentData(state.data);
redirectShopperToReviewPage();
}

Step 4: Submit additional payment details

When the shopper selects the Pay button on the review page, make a POST /payments/details request with:

  • details: the state.data.details from the onAdditionalDetails event.
  • paymentData: the state.data.paymentData from the onAdditionalDetails event.
Make a /payments/details request
Expand view
Copy link to code block
Copy code
Copy code
curl https://checkout-test.adyen.com/checkout/v71/payments/details \
-H 'x-api-key: ADYEN_API_KEY' \
-H 'content-type: application/json' \
-d '{
"details: {
billingToken: null,
facilitatorAccessToken: "1WP6839J5ZKOIZ57aMZ",
payerID: "9DNS6DJFHS4NC",
orderID: "9914810184130050",
paymentID: "1WPF9J5ZKOIZH8MZ",
paymentSource: "paypal"
},
"paymentData":"ABC..."
}'

Recurring payments

PayPal Express Checkout supports tokenization for recurring payments.

We strongly recommend that you ask explicit permission from the shopper if you intend to make future recurring payments. Being transparent about the payment schedule and the charged amount reduces the risk of chargebacks.

When creating a token through a PayPal Express Checkout payment, keep in mind the following:

  • PayPal Express Checkout does not allow zero-value authorization requests to create a token.
  • Tokenization through a PayPal Express Checkout request fails if the PayPal configuration object includes intent: "tokenize".

Other than the above points, creating and using tokens for PayPal Express Checkout payments is the same as described for tokenization in general.

For instructions, see: