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
- When the shopper selects the PayPal Express Checkout button, the Component makes a /payments request.
- The Component shows a PayPal lightbox either with the delivery methods for the shopper's default delivery address or without delivery methods.
- 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.
- If the final payment amount changes, you update the amount and send it to Adyen.
- The Component makes a /payments/details request to authorize the payment.
- 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 |
![]() |
The pspReference from the /payments response. |
paymentData |
![]() |
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 |
![]() |
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.
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:
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.
{ "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.
{ "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.
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.
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.
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 |
|
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.
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
: thestate.data.details
from theonAdditionalDetails
event.paymentData
: thestate.data.paymentData
from theonAdditionalDetails
event.
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:
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.
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.
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
: thestate.data.details
from theonAdditionalDetails
event.paymentData
: thestate.data.paymentData
from theonAdditionalDetails
event.
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: