--- title: "PayPal Express Checkout" description: "Render a PayPal Express Checkout button for one-click checkout." url: "https://docs.adyen.com/payment-methods/paypal/web-component/express-checkout" source_url: "https://docs.adyen.com/payment-methods/paypal/web-component/express-checkout.md" canonical: "https://docs.adyen.com/payment-methods/paypal/web-component/express-checkout" last_modified: "2023-04-04T16:13:00+02:00" language: "en" --- # PayPal Express Checkout Render a PayPal Express Checkout button for one-click checkout. [View source](/payment-methods/paypal/web-component/express-checkout.md) 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. ## Requirements Implement the [PayPal Web Component](/payment-methods/paypal/web-component). PayPal Express Checkout is supported from [v5.59.0](/online-payments/release-notes?integration_type=web\&version=5.59.0#releaseNote=2024-02-26-web-componentsdrop-in-5.59.0) and later. ## How it works ### Tab: Sessions flow 1. You create a payment session with a [/sessions](https://docs.adyen.com/api-explorer/Checkout/latest/post/sessions) request. 2. When the shopper selects the PayPal Express Checkout button, the Component shows a PayPal lightbox either with the delivery methods (**Shipping method** in the PayPal lightbox) 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. When the shopper completes the payment in the PayPal lightbox, the Component receives the shopper's payment information from PayPal. ### Tab: Advanced flow 1. When the shopper selects the PayPal Express Checkout button, the Component makes a [/payments](https://docs.adyen.com/api-explorer/Checkout/latest/post/payments) request. 2. The Component shows a PayPal lightbox either with the delivery methods (**Shipping method** in the PayPal lightbox) 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](https://docs.adyen.com/api-explorer/Checkout/latest/post/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](#review-page). **PayPal Lightbox with delivery methods:** ![](/user/pages/docs/08.payment-methods/70.paypal/02.web-component/express-checkout/with.png) **PayPal Lightbox without delivery methods:** ![](/user/pages/docs/08.payment-methods/70.paypal/02.web-component/express-checkout/without.png) ## Set up PayPal express ### Tab: Sessions flow ### 1. Create a session 1. Make a POST [/sessions](https://docs.adyen.com/api-explorer/Checkout/latest/post/sessions) request.\ You get a response that contains a `sessionId`. 2. Store the `sessionId` in your back end. When you set up your Web Component integration, you [created a global configuration object](/online-payments/build-your-integration/sessions-flow/?platform=Web\&integration=Components#configure) that passes your `session.id` and `session.sessionData` to `AdyenCheckout`. After passing your session, you create the PayPal Component. For the Express Checkout flow, you do this the same way as the standard [PayPal Web Component](/payment-methods/paypal/web-component/#component-configuration). ### 2. Implement the API endpoint to update PayPal orders You need to integrate an additional endpoint to update PayPal orders when the amount changes. Depending on how you present the PayPal lightbox, the final payment amount can change: * **PayPal lightbox with delivery methods**: if your shopper changes their delivery address (**Ship to** address in the PayPal lightbox), or selects a different delivery method, the delivery fees can change the final payment amount. * **PayPal lightbox without delivery methods**: if your shopper changes their delivery address (**Ship to** address in the PayPal lightbox), the final payment amount can 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: 1. Make a POST  [/paypal/updateOrder](https://docs.adyen.com/api-explorer/Checkout/latest/post/paypal/updateOrder) request, including the following parameters: | Parameter | Required | Description | | ---------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `sessionId` | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | The `sessionId` from the [/sessions](https://docs.adyen.com/api-explorer/Checkout/latest/post/sessions) response. | | `paymentData` | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | The `paymentData` blob that you received on your front end. For the first request to the `/paypal/updateOrder` endpoint, this is the `paymentData` you received when you [created the session](#create-sessions). If you need to update the amount again and make a second `/paypal/updateOrder` request, this is the `paymentData` you received for your first `/paypal/updateOrder` request, and so on.Always use the latest `paymentData` blob. | | `amount` | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | The `currency` and `value` of the final payment amount including the delivery fees and any taxes, in [minor units](/development-resources/currency-codes/). If taxes are applicable, in addition pass the total tax amount separately in the `taxTotal` object. | | [deliveryMethods](https://docs.adyen.com/api-explorer/Checkout/latest/post/paypal/updateOrder#request-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**. PayPal calls this shipping method. | | [taxTotal](https://docs.adyen.com/api-explorer/Checkout/latest/post/paypal/updateOrder#request-taxTotal) | | An object containing an `amount` object with the `currency` and `value` of the total tax amount. If you specify `taxTotal`, you must also add the tax amount to the payment amount. | The following example shows how to update the payment amount if you present the PayPal lightbox with delivery methods. In this example, the item costs USD 110 including USD 10 in taxes, and the shopper selected a delivery method that is excluded from taxes and adds USD 10 in costs. **Update payment amount with delivery methods** #### curl ```bash curl https://checkout-test.adyen.com/v72/paypal/updateOrder \ -H 'x-api-key: ADYEN_API_KEY' \ -H 'content-type: application/json' \ -d '{ "sessionId": "CS12345679", "paymentData": "XYZ...", "amount": { "currency": "USD", "value": 12000 }, "deliveryMethods": [ { "reference": "1", "description": "Express Shipping", "type": "Shipping", "amount": { "currency": "USD", "value": 1000 }, "selected": true }, { "reference": "2", "description": "Standard Ground", "type": "Shipping", "amount": { "currency": "USD", "value": 500 }, "selected": false } ] }' ``` #### Java ```java // Adyen Java API Library v27.0.0 import com.adyen.Client; import com.adyen.enums.Environment; import com.adyen.model.checkout.*; import java.time.OffsetDateTime; import java.util.*; import com.adyen.model.RequestOptions; import com.adyen.service.checkout.*; // For the live environment, additionally include your liveEndpointUrlPrefix. Client client = new Client("ADYEN_API_KEY", Environment.TEST); // Create the request object(s) Amount deliveryMethodAmount1 = new Amount() .currency("EUR") .value(1000L); Amount deliveryMethodAmount2 = new Amount() .currency("EUR") .value(500L); Amount amount = new Amount() .currency("EUR") .value(12000L); DeliveryMethod deliveryMethod1 = new DeliveryMethod() .reference("1") .amount(deliveryMethodAmount1) .description("Express Shipping") .type(DeliveryMethod.TypeEnum.SHIPPING) .selected(true); DeliveryMethod deliveryMethod2 = new DeliveryMethod() .reference("2") .amount(deliveryMethodAmount2) .description("Standard Ground") .type(DeliveryMethod.TypeEnum.SHIPPING) .selected(false); PaypalUpdateOrderRequest paypalUpdateOrderRequest = new PaypalUpdateOrderRequest() .amount(amount) .paymentData("XYZ...") .sessionId("CS12345679") .deliveryMethods(Arrays.asList(deliveryMethod1, deliveryMethod2)); // Send the request UtilityApi service = new UtilityApi(client); PaypalUpdateOrderResponse response = service.updatesOrderForPaypalExpressCheckout(paypalUpdateOrderRequest, new RequestOptions().idempotencyKey("UUID")); ``` #### PHP ```php // Adyen PHP API Library v19.0.0 use Adyen\Client; use Adyen\Environment; use Adyen\Model\Checkout\Amount; use Adyen\Model\Checkout\DeliveryMethod; use Adyen\Model\Checkout\PaypalUpdateOrderRequest; use Adyen\Service\Checkout\UtilityApi; $client = new Client(); $client->setXApiKey("ADYEN_API_KEY"); // For the live environment, additionally include your liveEndpointUrlPrefix. $client->setEnvironment(Environment::TEST); // Create the request object(s) $deliveryMethodAmount1 = new Amount(); $deliveryMethodAmount1 ->setCurrency("EUR") ->setValue(1000); $deliveryMethodAmount2 = new Amount(); $deliveryMethodAmount2 ->setCurrency("EUR") ->setValue(500); $amount = new Amount(); $amount ->setCurrency("EUR") ->setValue(12000); $deliveryMethod1 = new DeliveryMethod(); $deliveryMethod1 ->setReference("1") ->setAmount($deliveryMethodAmount1) ->setDescription("Express Shipping") ->setType("Shipping") ->setSelected(true); $deliveryMethod2 = new DeliveryMethod(); $deliveryMethod2 ->setReference("2") ->setAmount($deliveryMethodAmount2) ->setDescription("Standard Ground") ->setType("Shipping") ->setSelected(false); $paypalUpdateOrderRequest = new PaypalUpdateOrderRequest(); $paypalUpdateOrderRequest ->setAmount($amount) ->setPaymentData("XYZ...") ->setSessionId("CS12345679") ->setDeliveryMethods(array($deliveryMethod1, $deliveryMethod2)); $requestOptions['idempotencyKey'] = 'UUID'; // Send the request $service = new UtilityApi($client); $response = $service->updatesOrderForPaypalExpressCheckout($paypalUpdateOrderRequest, $requestOptions); ``` #### C\# ```cs // Adyen .net API Library v17.0.0 using Adyen; using Environment = Adyen.Model.Environment; using Adyen.Model; using Adyen.Model.Checkout; using Adyen.Service.Checkout; // For the live environment, additionally include your liveEndpointUrlPrefix. var config = new Config() { XApiKey = "ADYEN_API_KEY", Environment = Environment.Test }; var client = new Client(config); // Create the request object(s) Amount deliveryMethodAmount1 = new Amount { Currency = "EUR", Value = 1000 }; Amount deliveryMethodAmount2 = new Amount { Currency = "EUR", Value = 500 }; Amount amount = new Amount { Currency = "EUR", Value = 12000 }; DeliveryMethod deliveryMethod1 = new DeliveryMethod { Reference = "1", Amount = deliveryMethodAmount1, Description = "Express Shipping", Type = DeliveryMethod.TypeEnum.Shipping, Selected = true }; DeliveryMethod deliveryMethod2 = new DeliveryMethod { Reference = "2", Amount = deliveryMethodAmount2, Description = "Standard Ground", Type = DeliveryMethod.TypeEnum.Shipping, Selected = false }; PaypalUpdateOrderRequest paypalUpdateOrderRequest = new PaypalUpdateOrderRequest { Amount = amount, PaymentData = "XYZ...", SessionId = "CS12345679", DeliveryMethods = new List{ deliveryMethod1, deliveryMethod2 } }; // Send the request var service = new UtilityService(client); var response = service.UpdatesOrderForPaypalExpressCheckout(paypalUpdateOrderRequest, requestOptions: new RequestOptions { IdempotencyKey = "UUID"}); ``` #### NodeJS (JavaScript) ```js // Adyen Node API Library v18.0.0 // Require the parts of the module you want to use const { Client, CheckoutAPI } = require('@adyen/api-library'); // Initialize the client object // For the live environment, additionally include your liveEndpointUrlPrefix. const client = new Client({apiKey: "ADYEN_API_KEY", environment: "TEST"}); // Create the request object(s) const paypalUpdateOrderRequest = { sessionId: "CS12345679", 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 } ] } // Send the request const checkoutAPI = new CheckoutAPI(client); const response = checkoutAPI.UtilityApi.updatesOrderForPaypalExpressCheckout(paypalUpdateOrderRequest, { idempotencyKey: "UUID" }); ``` #### Go ```go // Adyen Go API Library v10.4.0 import ( "context" "github.com/adyen/adyen-go-api-library/v9/src/common" "github.com/adyen/adyen-go-api-library/v9/src/adyen" "github.com/adyen/adyen-go-api-library/v9/src/checkout" ) // For the live environment, additionally include your liveEndpointUrlPrefix. client := adyen.NewClient(&common.Config{ ApiKey: "ADYEN_API_KEY", Environment: common.TestEnv, }) // Create the request object(s) deliveryMethodAmount1 := checkout.Amount{ Currency: "EUR", Value: 1000, } deliveryMethodAmount2 := checkout.Amount{ Currency: "EUR", Value: 500, } amount := checkout.Amount{ Currency: "EUR", Value: 12000, } deliveryMethod1 := checkout.DeliveryMethod{ Reference: common.PtrString("1"), Amount: &deliveryMethodAmount1, Description: common.PtrString("Express Shipping"), Type: common.PtrString("Shipping"), Selected: common.PtrBool(true), } deliveryMethod2 := checkout.DeliveryMethod{ Reference: common.PtrString("2"), Amount: &deliveryMethodAmount2, Description: common.PtrString("Standard Ground"), Type: common.PtrString("Shipping"), Selected: common.PtrBool(false), } paypalUpdateOrderRequest := checkout.PaypalUpdateOrderRequest{ Amount: &amount, PaymentData: common.PtrString("XYZ..."), SessionId: common.PtrString("CS12345679"), DeliveryMethods: []checkout.DeliveryMethod{ deliveryMethod1, deliveryMethod2, }, } // Send the request service := client.Checkout() req := service.UtilityApi.UpdatesOrderForPaypalExpressCheckoutInput().IdempotencyKey("UUID").PaypalUpdateOrderRequest(paypalUpdateOrderRequest) res, httpRes, err := service.UtilityApi.UpdatesOrderForPaypalExpressCheckout(context.Background(), req) ``` #### Python ```py # Adyen Python API Library v12.5.1 import Adyen adyen = Adyen.Adyen() adyen.client.xapikey = "ADYEN_API_KEY" # For the live environment, additionally include your liveEndpointUrlPrefix. adyen.client.platform = "test" # The environment to use library in. # Create the request object(s) json_request = { "sessionId": "CS12345679", "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 } ] } # Send the request result = adyen.checkout.utility_api.updates_order_for_paypal_express_checkout(request=json_request, idempotency_key="UUID") ``` #### Ruby ```rb # Adyen Ruby API Library v9.5.1 require "adyen-ruby-api-library" adyen = Adyen::Client.new adyen.api_key = 'ADYEN_API_KEY' # For the live environment, additionally include your liveEndpointUrlPrefix. adyen.env = :test # Set to "live" for live environment # Create the request object(s) request_body = { :sessionId => 'CS12345679', :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 } ] } # Send the request result = adyen.checkout.utility_api.updates_order_for_paypal_express_checkout(request_body, headers: { 'Idempotency-Key' => 'UUID' }) ``` #### NodeJS (TypeScript) ```ts // Adyen Node API Library v18.0.0 // Require the parts of the module you want to use import { Client, CheckoutAPI, Types } from "@adyen/api-library"; // Initialize the client object // For the live environment, additionally include your liveEndpointUrlPrefix. const client = new Client({apiKey: "ADYEN_API_KEY", environment: "TEST"}); // Create the request object(s) const deliveryMethodAmount1: Types.checkout.Amount = { currency: "EUR", value: 1000 }; const deliveryMethodAmount2: Types.checkout.Amount = { currency: "EUR", value: 500 }; const amount: Types.checkout.Amount = { currency: "EUR", value: 12000 }; const deliveryMethod1: Types.checkout.DeliveryMethod = { reference: "1", amount: deliveryMethodAmount1, description: "Express Shipping", type: Types.checkout.DeliveryMethod.TypeEnum.Shipping, selected: true }; const deliveryMethod2: Types.checkout.DeliveryMethod = { reference: "2", amount: deliveryMethodAmount2, description: "Standard Ground", type: Types.checkout.DeliveryMethod.TypeEnum.Shipping, selected: false }; const paypalUpdateOrderRequest: Types.checkout.PaypalUpdateOrderRequest = { amount: amount, paymentData: "XYZ...", sessionId: "CS12345679", deliveryMethods: [deliveryMethod1, deliveryMethod2] }; // Send the request const checkoutAPI = new CheckoutAPI(client); const response = checkoutAPI.UtilityApi.updatesOrderForPaypalExpressCheckout(paypalUpdateOrderRequest, { idempotencyKey: "UUID" }); ``` The next example shows the same amount update if you present the PayPal lightbox without delivery methods. **Update payment amount without delivery methods** #### curl ```bash curl https://checkout-test.adyen.com/v72/paypal/updateOrder \ -H 'x-api-key: ADYEN_API_KEY' \ -H 'content-type: application/json' \ -d '{ "sessionId":"CS12345678", "paymentData": "XYZ...", "amount": { "currency": "USD", "value": 12000 } }' ``` #### Java ```java // Adyen Java API Library v27.0.0 import com.adyen.Client; import com.adyen.enums.Environment; import com.adyen.model.checkout.*; import java.time.OffsetDateTime; import java.util.*; import com.adyen.model.RequestOptions; import com.adyen.service.checkout.*; // For the live environment, additionally include your liveEndpointUrlPrefix. Client client = new Client("ADYEN_API_KEY", Environment.TEST); // Create the request object(s) Amount amount = new Amount() .currency("EUR") .value(12000L); PaypalUpdateOrderRequest paypalUpdateOrderRequest = new PaypalUpdateOrderRequest() .amount(amount) .paymentData("XYZ...") .sessionId("CS12345678"); // Send the request UtilityApi service = new UtilityApi(client); PaypalUpdateOrderResponse response = service.updatesOrderForPaypalExpressCheckout(paypalUpdateOrderRequest, new RequestOptions().idempotencyKey("UUID")); ``` #### PHP ```php // Adyen PHP API Library v19.0.0 use Adyen\Client; use Adyen\Environment; use Adyen\Model\Checkout\Amount; use Adyen\Model\Checkout\PaypalUpdateOrderRequest; use Adyen\Service\Checkout\UtilityApi; $client = new Client(); $client->setXApiKey("ADYEN_API_KEY"); // For the live environment, additionally include your liveEndpointUrlPrefix. $client->setEnvironment(Environment::TEST); // Create the request object(s) $amount = new Amount(); $amount ->setCurrency("EUR") ->setValue(12000); $paypalUpdateOrderRequest = new PaypalUpdateOrderRequest(); $paypalUpdateOrderRequest ->setAmount($amount) ->setPaymentData("XYZ...") ->setSessionId("CS12345678"); $requestOptions['idempotencyKey'] = 'UUID'; // Send the request $service = new UtilityApi($client); $response = $service->updatesOrderForPaypalExpressCheckout($paypalUpdateOrderRequest, $requestOptions); ``` #### C\# ```cs // Adyen .net API Library v17.0.0 using Adyen; using Environment = Adyen.Model.Environment; using Adyen.Model; using Adyen.Model.Checkout; using Adyen.Service.Checkout; // For the live environment, additionally include your liveEndpointUrlPrefix. var config = new Config() { XApiKey = "ADYEN_API_KEY", Environment = Environment.Test }; var client = new Client(config); // Create the request object(s) Amount amount = new Amount { Currency = "EUR", Value = 12000 }; PaypalUpdateOrderRequest paypalUpdateOrderRequest = new PaypalUpdateOrderRequest { Amount = amount, PaymentData = "XYZ...", SessionId = "CS12345678" }; // Send the request var service = new UtilityService(client); var response = service.UpdatesOrderForPaypalExpressCheckout(paypalUpdateOrderRequest, requestOptions: new RequestOptions { IdempotencyKey = "UUID"}); ``` #### NodeJS (JavaScript) ```js // Adyen Node API Library v18.0.0 // Require the parts of the module you want to use const { Client, CheckoutAPI } = require('@adyen/api-library'); // Initialize the client object // For the live environment, additionally include your liveEndpointUrlPrefix. const client = new Client({apiKey: "ADYEN_API_KEY", environment: "TEST"}); // Create the request object(s) const paypalUpdateOrderRequest = { sessionId: "CS12345678", paymentData: "XYZ...", amount: { currency: "EUR", value: 12000 } } // Send the request const checkoutAPI = new CheckoutAPI(client); const response = checkoutAPI.UtilityApi.updatesOrderForPaypalExpressCheckout(paypalUpdateOrderRequest, { idempotencyKey: "UUID" }); ``` #### Go ```go // Adyen Go API Library v10.4.0 import ( "context" "github.com/adyen/adyen-go-api-library/v9/src/common" "github.com/adyen/adyen-go-api-library/v9/src/adyen" "github.com/adyen/adyen-go-api-library/v9/src/checkout" ) // For the live environment, additionally include your liveEndpointUrlPrefix. client := adyen.NewClient(&common.Config{ ApiKey: "ADYEN_API_KEY", Environment: common.TestEnv, }) // Create the request object(s) amount := checkout.Amount{ Currency: "EUR", Value: 12000, } paypalUpdateOrderRequest := checkout.PaypalUpdateOrderRequest{ Amount: &amount, PaymentData: common.PtrString("XYZ..."), SessionId: common.PtrString("CS12345678"), } // Send the request service := client.Checkout() req := service.UtilityApi.UpdatesOrderForPaypalExpressCheckoutInput().IdempotencyKey("UUID").PaypalUpdateOrderRequest(paypalUpdateOrderRequest) res, httpRes, err := service.UtilityApi.UpdatesOrderForPaypalExpressCheckout(context.Background(), req) ``` #### Python ```py # Adyen Python API Library v12.5.1 import Adyen adyen = Adyen.Adyen() adyen.client.xapikey = "ADYEN_API_KEY" # For the live environment, additionally include your liveEndpointUrlPrefix. adyen.client.platform = "test" # The environment to use library in. # Create the request object(s) json_request = { "sessionId": "CS12345678", "paymentData": "XYZ...", "amount": { "currency": "EUR", "value": 12000 } } # Send the request result = adyen.checkout.utility_api.updates_order_for_paypal_express_checkout(request=json_request, idempotency_key="UUID") ``` #### Ruby ```rb # Adyen Ruby API Library v9.5.1 require "adyen-ruby-api-library" adyen = Adyen::Client.new adyen.api_key = 'ADYEN_API_KEY' # For the live environment, additionally include your liveEndpointUrlPrefix. adyen.env = :test # Set to "live" for live environment # Create the request object(s) request_body = { :sessionId => 'CS12345678', :paymentData => 'XYZ...', :amount => { :currency => 'EUR', :value => 12000 } } # Send the request result = adyen.checkout.utility_api.updates_order_for_paypal_express_checkout(request_body, headers: { 'Idempotency-Key' => 'UUID' }) ``` #### NodeJS (TypeScript) ```ts // Adyen Node API Library v18.0.0 // Require the parts of the module you want to use import { Client, CheckoutAPI, Types } from "@adyen/api-library"; // Initialize the client object // For the live environment, additionally include your liveEndpointUrlPrefix. const client = new Client({apiKey: "ADYEN_API_KEY", environment: "TEST"}); // Create the request object(s) const amount: Types.checkout.Amount = { currency: "EUR", value: 12000 }; const paypalUpdateOrderRequest: Types.checkout.PaypalUpdateOrderRequest = { amount: amount, paymentData: "XYZ...", sessionId: "CS12345678" }; // Send the request const checkoutAPI = new CheckoutAPI(client); const response = checkoutAPI.UtilityApi.updatesOrderForPaypalExpressCheckout(paypalUpdateOrderRequest, { idempotencyKey: "UUID" }); ``` 2. From the response, get the updated `paymentData` and pass this new value to your front end.\ With each update, the `paymentData` value changes. To complete the payment, the Component needs the latest value. **Example successful update response** ```bash { "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** ```bash { "status": 422, "errorCode": "000", "message": "Only 1 deliveryMethod should be selected", "errorType": "validation", "pspReference": "993617895204576J" } ``` ### 3. Add additional PayPal configuration In the PayPal configuration object, set the property `isExpress` to **true**. **Configure isExpress** ```js const payPalConfiguration = { isExpress: true, // ... Your other configurations. } ``` ### 4. Handle delivery address changes Implement the [`onShippingAddressChange` ](https://developer.paypal.com/sdk/js/reference/#link-onshippingaddresschange)event in your PayPal configuration object. The event is triggered when the PayPal lightbox opens. You make an initial [POST `/paypal/updateOrder` request](#update-paypal-orders-sessions). * **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](#handle-delivery-method-changes-sessions). For the PayPal lightbox without delivery methods, you make a POST  [/paypal/updateOrder](https://docs.adyen.com/api-explorer/Checkout/latest/post/paypal/updateOrder) request to update the final amount. Implement your own function to make a POST [/paypal/updateOrder](https://docs.adyen.com/api-explorer/Checkout/latest/post/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** ```js 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. } ``` #### Handle errors If an error occurs, PayPal returns an error in the `data` object that you must pass to `action.reject()`. You can optionally use the included error message for some validation scenarios. ### 5. Handle delivery method changes This step is only required if you present default delivery methods when the PayPal lightbox opens. PayPal labels the delivery method the `ShippingOption`. Implement the [`onShippingOptionsChange` ](https://developer.paypal.com/sdk/js/reference/#link-onshippingoptionschange)event in your PayPal configuration object to handle situations where the shopper selects a different delivery method. Make a POST [/paypal/updateOrder](https://docs.adyen.com/api-explorer/Checkout/latest/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** ```js 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. ``` ### 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 that you use: ### 7. Complete the payment The Component makes an authorization request to complete the payment. Use the `onPaymentCompleted` callback to redirect the shopper to the payment confirmation page. ### Tab: Advanced flow ### 1. Store the PSP reference When the shopper selects the PayPal Express Checkout button, the [`onSubmit` ](/payment-methods/paypal/web-component?tab=pp-risk-payments_2#step-2-create-an-instance-of-the-component)callback is triggered and your server makes a [/payments](https://docs.adyen.com/api-explorer/Checkout/latest/post/payments) request. The [/payments](https://docs.adyen.com/api-explorer/Checkout/latest/post/payments) response contains the `pspReference` field. Store the PSP reference in your back end. ### 2. Implement the API endpoint to update PayPal orders You need to integrate an additional endpoint to update PayPal orders for changes in the amount. Depending on how you present the PayPal lightbox, the final payment amount can change: * **PayPal lightbox with delivery methods**: 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**: 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: 1. Make a POST  [/paypal/updateOrder](https://docs.adyen.com/api-explorer/Checkout/latest/post/paypal/updateOrder) request, including the following parameters: | Parameter | Required | Description | | ---------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `pspReference` | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | The `pspReference` from the [/payments](https://docs.adyen.com/api-explorer/Checkout/latest/post/payments) response. | | `paymentData` | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | The `paymentData` blob that you received on your front end. For the first request to the `/paypal/updateOrder` endpoint, this is the `paymentData` you received when you [made the /payments request](#store-pspreference). If you need to update the amount again and make a second `/paypal/updateOrder` request, this is the `paymentData` you received for your first `/paypal/updateOrder` request, and so on.Always use the latest `paymentData` blob. | | `amount` | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | The `currency` and `value` of the final payment amount including the delivery fees and any taxes, in [minor units](/development-resources/currency-codes/). If taxes are applicable, in addition pass the total tax amount separately in the `taxTotal` object. | | [deliveryMethods](https://docs.adyen.com/api-explorer/Checkout/latest/post/paypal/updateOrder#request-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**. | | [taxTotal](https://docs.adyen.com/api-explorer/Checkout/latest/post/paypal/updateOrder#request-taxTotal) | | An object containing an `amount` object with the `currency` and `value` of the total tax amount. If you specify `taxTotal`, you must also add the tax amount to the payment amount. | The following example shows how to update the payment amount if you present the PayPal lightbox with delivery methods. In this example, the item costs USD 110 including USD 10 in taxes, and the shopper selected a delivery method that is excluded from taxes and adds USD 10 in costs. **Update payment amount with delivery methods** #### curl ```bash curl https://checkout-test.adyen.com/v72/paypal/updateOrder \ -H 'x-api-key: ADYEN_API_KEY' \ -H 'content-type: application/json' \ -d '{ "pspReference":"DZ4DPSHB4WD2WN82", "paymentData":"XYZ...", "amount":{ "currency":"USD", "value":12000 }, "deliveryMethods":[ { "reference":"1", "description":"Express Shipping", "type":"Shipping", "amount":{ "currency":"USD", "value":1000 }, "selected":true }, { "reference":"2", "description":"Standard Ground", "type":"Shipping", "amount":{ "currency":"USD", "value":500 }, "selected":false } ] }' ``` #### Java ```java // Adyen Java API Library v27.0.0 import com.adyen.Client; import com.adyen.enums.Environment; import com.adyen.model.checkout.*; import java.time.OffsetDateTime; import java.util.*; import com.adyen.model.RequestOptions; import com.adyen.service.checkout.*; // For the live environment, additionally include your liveEndpointUrlPrefix. Client client = new Client("ADYEN_API_KEY", Environment.TEST); // Create the request object(s) Amount deliveryMethodAmount1 = new Amount() .currency("EUR") .value(1000L); Amount deliveryMethodAmount2 = new Amount() .currency("EUR") .value(500L); Amount amount = new Amount() .currency("EUR") .value(12000L); DeliveryMethod deliveryMethod1 = new DeliveryMethod() .reference("1") .amount(deliveryMethodAmount1) .description("Express Shipping") .type(DeliveryMethod.TypeEnum.SHIPPING) .selected(true); DeliveryMethod deliveryMethod2 = new DeliveryMethod() .reference("2") .amount(deliveryMethodAmount2) .description("Standard Ground") .type(DeliveryMethod.TypeEnum.SHIPPING) .selected(false); PaypalUpdateOrderRequest paypalUpdateOrderRequest = new PaypalUpdateOrderRequest() .amount(amount) .paymentData("XYZ...") .deliveryMethods(Arrays.asList(deliveryMethod1, deliveryMethod2)) .pspReference("DZ4DPSHB4WD2WN82"); // Send the request UtilityApi service = new UtilityApi(client); PaypalUpdateOrderResponse response = service.updatesOrderForPaypalExpressCheckout(paypalUpdateOrderRequest, new RequestOptions().idempotencyKey("UUID")); ``` #### PHP ```php // Adyen PHP API Library v19.0.0 use Adyen\Client; use Adyen\Environment; use Adyen\Model\Checkout\Amount; use Adyen\Model\Checkout\DeliveryMethod; use Adyen\Model\Checkout\PaypalUpdateOrderRequest; use Adyen\Service\Checkout\UtilityApi; $client = new Client(); $client->setXApiKey("ADYEN_API_KEY"); // For the live environment, additionally include your liveEndpointUrlPrefix. $client->setEnvironment(Environment::TEST); // Create the request object(s) $deliveryMethodAmount1 = new Amount(); $deliveryMethodAmount1 ->setCurrency("EUR") ->setValue(1000); $deliveryMethodAmount2 = new Amount(); $deliveryMethodAmount2 ->setCurrency("EUR") ->setValue(500); $amount = new Amount(); $amount ->setCurrency("EUR") ->setValue(12000); $deliveryMethod1 = new DeliveryMethod(); $deliveryMethod1 ->setReference("1") ->setAmount($deliveryMethodAmount1) ->setDescription("Express Shipping") ->setType("Shipping") ->setSelected(true); $deliveryMethod2 = new DeliveryMethod(); $deliveryMethod2 ->setReference("2") ->setAmount($deliveryMethodAmount2) ->setDescription("Standard Ground") ->setType("Shipping") ->setSelected(false); $paypalUpdateOrderRequest = new PaypalUpdateOrderRequest(); $paypalUpdateOrderRequest ->setAmount($amount) ->setPaymentData("XYZ...") ->setDeliveryMethods(array($deliveryMethod1, $deliveryMethod2)) ->setPspReference("DZ4DPSHB4WD2WN82"); $requestOptions['idempotencyKey'] = 'UUID'; // Send the request $service = new UtilityApi($client); $response = $service->updatesOrderForPaypalExpressCheckout($paypalUpdateOrderRequest, $requestOptions); ``` #### C\# ```cs // Adyen .net API Library v17.0.0 using Adyen; using Environment = Adyen.Model.Environment; using Adyen.Model; using Adyen.Model.Checkout; using Adyen.Service.Checkout; // For the live environment, additionally include your liveEndpointUrlPrefix. var config = new Config() { XApiKey = "ADYEN_API_KEY", Environment = Environment.Test }; var client = new Client(config); // Create the request object(s) Amount deliveryMethodAmount1 = new Amount { Currency = "EUR", Value = 1000 }; Amount deliveryMethodAmount2 = new Amount { Currency = "EUR", Value = 500 }; Amount amount = new Amount { Currency = "EUR", Value = 12000 }; DeliveryMethod deliveryMethod1 = new DeliveryMethod { Reference = "1", Amount = deliveryMethodAmount1, Description = "Express Shipping", Type = DeliveryMethod.TypeEnum.Shipping, Selected = true }; DeliveryMethod deliveryMethod2 = new DeliveryMethod { Reference = "2", Amount = deliveryMethodAmount2, Description = "Standard Ground", Type = DeliveryMethod.TypeEnum.Shipping, Selected = false }; PaypalUpdateOrderRequest paypalUpdateOrderRequest = new PaypalUpdateOrderRequest { Amount = amount, PaymentData = "XYZ...", DeliveryMethods = new List{ deliveryMethod1, deliveryMethod2 }, PspReference = "DZ4DPSHB4WD2WN82" }; // Send the request var service = new UtilityService(client); var response = service.UpdatesOrderForPaypalExpressCheckout(paypalUpdateOrderRequest, requestOptions: new RequestOptions { IdempotencyKey = "UUID"}); ``` #### NodeJS (JavaScript) ```js // Adyen Node API Library v18.0.0 // Require the parts of the module you want to use const { Client, CheckoutAPI } = require('@adyen/api-library'); // Initialize the client object // For the live environment, additionally include your liveEndpointUrlPrefix. const client = new Client({apiKey: "ADYEN_API_KEY", environment: "TEST"}); // Create the request object(s) const paypalUpdateOrderRequest = { 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 } ] } // Send the request const checkoutAPI = new CheckoutAPI(client); const response = checkoutAPI.UtilityApi.updatesOrderForPaypalExpressCheckout(paypalUpdateOrderRequest, { idempotencyKey: "UUID" }); ``` #### Go ```go // Adyen Go API Library v10.4.0 import ( "context" "github.com/adyen/adyen-go-api-library/v9/src/common" "github.com/adyen/adyen-go-api-library/v9/src/adyen" "github.com/adyen/adyen-go-api-library/v9/src/checkout" ) // For the live environment, additionally include your liveEndpointUrlPrefix. client := adyen.NewClient(&common.Config{ ApiKey: "ADYEN_API_KEY", Environment: common.TestEnv, }) // Create the request object(s) deliveryMethodAmount1 := checkout.Amount{ Currency: "EUR", Value: 1000, } deliveryMethodAmount2 := checkout.Amount{ Currency: "EUR", Value: 500, } amount := checkout.Amount{ Currency: "EUR", Value: 12000, } deliveryMethod1 := checkout.DeliveryMethod{ Reference: common.PtrString("1"), Amount: &deliveryMethodAmount1, Description: common.PtrString("Express Shipping"), Type: common.PtrString("Shipping"), Selected: common.PtrBool(true), } deliveryMethod2 := checkout.DeliveryMethod{ Reference: common.PtrString("2"), Amount: &deliveryMethodAmount2, Description: common.PtrString("Standard Ground"), Type: common.PtrString("Shipping"), Selected: common.PtrBool(false), } paypalUpdateOrderRequest := checkout.PaypalUpdateOrderRequest{ Amount: &amount, PaymentData: common.PtrString("XYZ..."), DeliveryMethods: []checkout.DeliveryMethod{ deliveryMethod1, deliveryMethod2, }, PspReference: common.PtrString("DZ4DPSHB4WD2WN82"), } // Send the request service := client.Checkout() req := service.UtilityApi.UpdatesOrderForPaypalExpressCheckoutInput().IdempotencyKey("UUID").PaypalUpdateOrderRequest(paypalUpdateOrderRequest) res, httpRes, err := service.UtilityApi.UpdatesOrderForPaypalExpressCheckout(context.Background(), req) ``` #### Python ```py # Adyen Python API Library v12.5.1 import Adyen adyen = Adyen.Adyen() adyen.client.xapikey = "ADYEN_API_KEY" # For the live environment, additionally include your liveEndpointUrlPrefix. adyen.client.platform = "test" # The environment to use library in. # Create the request object(s) json_request = { "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 } ] } # Send the request result = adyen.checkout.utility_api.updates_order_for_paypal_express_checkout(request=json_request, idempotency_key="UUID") ``` #### Ruby ```rb # Adyen Ruby API Library v9.5.1 require "adyen-ruby-api-library" adyen = Adyen::Client.new adyen.api_key = 'ADYEN_API_KEY' # For the live environment, additionally include your liveEndpointUrlPrefix. adyen.env = :test # Set to "live" for live environment # Create the request object(s) request_body = { :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 } ] } # Send the request result = adyen.checkout.utility_api.updates_order_for_paypal_express_checkout(request_body, headers: { 'Idempotency-Key' => 'UUID' }) ``` #### NodeJS (TypeScript) ```ts // Adyen Node API Library v18.0.0 // Require the parts of the module you want to use import { Client, CheckoutAPI, Types } from "@adyen/api-library"; // Initialize the client object // For the live environment, additionally include your liveEndpointUrlPrefix. const client = new Client({apiKey: "ADYEN_API_KEY", environment: "TEST"}); // Create the request object(s) const deliveryMethodAmount1: Types.checkout.Amount = { currency: "EUR", value: 1000 }; const deliveryMethodAmount2: Types.checkout.Amount = { currency: "EUR", value: 500 }; const amount: Types.checkout.Amount = { currency: "EUR", value: 12000 }; const deliveryMethod1: Types.checkout.DeliveryMethod = { reference: "1", amount: deliveryMethodAmount1, description: "Express Shipping", type: Types.checkout.DeliveryMethod.TypeEnum.Shipping, selected: true }; const deliveryMethod2: Types.checkout.DeliveryMethod = { reference: "2", amount: deliveryMethodAmount2, description: "Standard Ground", type: Types.checkout.DeliveryMethod.TypeEnum.Shipping, selected: false }; const paypalUpdateOrderRequest: Types.checkout.PaypalUpdateOrderRequest = { amount: amount, paymentData: "XYZ...", deliveryMethods: [deliveryMethod1, deliveryMethod2], pspReference: "DZ4DPSHB4WD2WN82" }; // Send the request const checkoutAPI = new CheckoutAPI(client); const response = checkoutAPI.UtilityApi.updatesOrderForPaypalExpressCheckout(paypalUpdateOrderRequest, { idempotencyKey: "UUID" }); ``` The next example shows the same amount update if you present the lightbox without delivery methods. **Update payment amount without delivery methods** #### curl ```bash curl https://checkout-test.adyen.com/v72/paypal/updateOrder \ -H 'x-api-key: ADYEN_API_KEY' \ -H 'content-type: application/json' \ -d '{ "pspReference": "HWL5D5BDLSGLNK82", "paymentData": "XYZ...", "amount": { "currency": "USD", "value": 12000 } }' ``` #### Java ```java // Adyen Java API Library v27.0.0 import com.adyen.Client; import com.adyen.enums.Environment; import com.adyen.model.checkout.*; import java.time.OffsetDateTime; import java.util.*; import com.adyen.model.RequestOptions; import com.adyen.service.checkout.*; // For the live environment, additionally include your liveEndpointUrlPrefix. Client client = new Client("ADYEN_API_KEY", Environment.TEST); // Create the request object(s) Amount amount = new Amount() .currency("EUR") .value(12000L); PaypalUpdateOrderRequest paypalUpdateOrderRequest = new PaypalUpdateOrderRequest() .amount(amount) .paymentData("XYZ...") .pspReference("HWL5D5BDLSGLNK82"); // Send the request UtilityApi service = new UtilityApi(client); PaypalUpdateOrderResponse response = service.updatesOrderForPaypalExpressCheckout(paypalUpdateOrderRequest, new RequestOptions().idempotencyKey("UUID")); ``` #### PHP ```php // Adyen PHP API Library v19.0.0 use Adyen\Client; use Adyen\Environment; use Adyen\Model\Checkout\Amount; use Adyen\Model\Checkout\PaypalUpdateOrderRequest; use Adyen\Service\Checkout\UtilityApi; $client = new Client(); $client->setXApiKey("ADYEN_API_KEY"); // For the live environment, additionally include your liveEndpointUrlPrefix. $client->setEnvironment(Environment::TEST); // Create the request object(s) $amount = new Amount(); $amount ->setCurrency("EUR") ->setValue(12000); $paypalUpdateOrderRequest = new PaypalUpdateOrderRequest(); $paypalUpdateOrderRequest ->setAmount($amount) ->setPaymentData("XYZ...") ->setPspReference("HWL5D5BDLSGLNK82"); $requestOptions['idempotencyKey'] = 'UUID'; // Send the request $service = new UtilityApi($client); $response = $service->updatesOrderForPaypalExpressCheckout($paypalUpdateOrderRequest, $requestOptions); ``` #### C\# ```cs // Adyen .net API Library v17.0.0 using Adyen; using Environment = Adyen.Model.Environment; using Adyen.Model; using Adyen.Model.Checkout; using Adyen.Service.Checkout; // For the live environment, additionally include your liveEndpointUrlPrefix. var config = new Config() { XApiKey = "ADYEN_API_KEY", Environment = Environment.Test }; var client = new Client(config); // Create the request object(s) Amount amount = new Amount { Currency = "EUR", Value = 12000 }; PaypalUpdateOrderRequest paypalUpdateOrderRequest = new PaypalUpdateOrderRequest { Amount = amount, PaymentData = "XYZ...", PspReference = "HWL5D5BDLSGLNK82" }; // Send the request var service = new UtilityService(client); var response = service.UpdatesOrderForPaypalExpressCheckout(paypalUpdateOrderRequest, requestOptions: new RequestOptions { IdempotencyKey = "UUID"}); ``` #### NodeJS (JavaScript) ```js // Adyen Node API Library v18.0.0 // Require the parts of the module you want to use const { Client, CheckoutAPI } = require('@adyen/api-library'); // Initialize the client object // For the live environment, additionally include your liveEndpointUrlPrefix. const client = new Client({apiKey: "ADYEN_API_KEY", environment: "TEST"}); // Create the request object(s) const paypalUpdateOrderRequest = { pspReference: "HWL5D5BDLSGLNK82", paymentData: "XYZ...", amount: { currency: "EUR", value: 12000 } } // Send the request const checkoutAPI = new CheckoutAPI(client); const response = checkoutAPI.UtilityApi.updatesOrderForPaypalExpressCheckout(paypalUpdateOrderRequest, { idempotencyKey: "UUID" }); ``` #### Go ```go // Adyen Go API Library v10.4.0 import ( "context" "github.com/adyen/adyen-go-api-library/v9/src/common" "github.com/adyen/adyen-go-api-library/v9/src/adyen" "github.com/adyen/adyen-go-api-library/v9/src/checkout" ) // For the live environment, additionally include your liveEndpointUrlPrefix. client := adyen.NewClient(&common.Config{ ApiKey: "ADYEN_API_KEY", Environment: common.TestEnv, }) // Create the request object(s) amount := checkout.Amount{ Currency: "EUR", Value: 12000, } paypalUpdateOrderRequest := checkout.PaypalUpdateOrderRequest{ Amount: &amount, PaymentData: common.PtrString("XYZ..."), PspReference: common.PtrString("HWL5D5BDLSGLNK82"), } // Send the request service := client.Checkout() req := service.UtilityApi.UpdatesOrderForPaypalExpressCheckoutInput().IdempotencyKey("UUID").PaypalUpdateOrderRequest(paypalUpdateOrderRequest) res, httpRes, err := service.UtilityApi.UpdatesOrderForPaypalExpressCheckout(context.Background(), req) ``` #### Python ```py # Adyen Python API Library v12.5.1 import Adyen adyen = Adyen.Adyen() adyen.client.xapikey = "ADYEN_API_KEY" # For the live environment, additionally include your liveEndpointUrlPrefix. adyen.client.platform = "test" # The environment to use library in. # Create the request object(s) json_request = { "pspReference": "HWL5D5BDLSGLNK82", "paymentData": "XYZ...", "amount": { "currency": "EUR", "value": 12000 } } # Send the request result = adyen.checkout.utility_api.updates_order_for_paypal_express_checkout(request=json_request, idempotency_key="UUID") ``` #### Ruby ```rb # Adyen Ruby API Library v9.5.1 require "adyen-ruby-api-library" adyen = Adyen::Client.new adyen.api_key = 'ADYEN_API_KEY' # For the live environment, additionally include your liveEndpointUrlPrefix. adyen.env = :test # Set to "live" for live environment # Create the request object(s) request_body = { :pspReference => 'HWL5D5BDLSGLNK82', :paymentData => 'XYZ...', :amount => { :currency => 'EUR', :value => 12000 } } # Send the request result = adyen.checkout.utility_api.updates_order_for_paypal_express_checkout(request_body, headers: { 'Idempotency-Key' => 'UUID' }) ``` #### NodeJS (TypeScript) ```ts // Adyen Node API Library v18.0.0 // Require the parts of the module you want to use import { Client, CheckoutAPI, Types } from "@adyen/api-library"; // Initialize the client object // For the live environment, additionally include your liveEndpointUrlPrefix. const client = new Client({apiKey: "ADYEN_API_KEY", environment: "TEST"}); // Create the request object(s) const amount: Types.checkout.Amount = { currency: "EUR", value: 12000 }; const paypalUpdateOrderRequest: Types.checkout.PaypalUpdateOrderRequest = { amount: amount, paymentData: "XYZ...", pspReference: "HWL5D5BDLSGLNK82" }; // Send the request const checkoutAPI = new CheckoutAPI(client); const response = checkoutAPI.UtilityApi.updatesOrderForPaypalExpressCheckout(paypalUpdateOrderRequest, { idempotencyKey: "UUID" }); ``` 2. From the response, get the updated `paymentData` and pass the new value to your front end.\ With each update, the `paymentData` value changes. To complete the payment, the Component needs the latest value. **Example successful update response** ```bash { "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** ```bash { "status": 422, "errorCode": "000", "message": "Only 1 deliveryMethod should be selected", "errorType": "validation", "pspReference": "DZ4DPSHB4WD2WN82" } ``` ### 3. Add additional PayPal configuration In the PayPal configuration object, set the property `isExpress` to **true**. **Configure isExpress** ```js const payPalConfiguration = { isExpress: true // ... Your other configurations. } ``` ### 4. Handle delivery address changes Implement the [`onShippingAddressChange` ](https://developer.paypal.com/sdk/js/reference/#link-onshippingaddresschange)event in your PayPal configuration object. The event is triggered when the PayPal lightbox opens. You make an initial [POST **/paypal/updateOrder** request](#update-paypal-orders-advanced). * **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](#handle-delivery-method-changes-advanced). For the PayPal lightbox without delivery methods, you make a POST  [/paypal/updateOrder](https://docs.adyen.com/api-explorer/Checkout/latest/post/paypal/updateOrder) request to update the final amount. Implement your own function to make a [/paypal/updateOrder](https://docs.adyen.com/api-explorer/Checkout/latest/post/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** ```js 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. } ``` ### 5. Handle delivery method changes This step is only required if you present default delivery methods when the PayPal lightbox opens. PayPal labels the delivery method the `ShippingOption`. Implement the [`onShippingOptionsChange` ](https://developer.paypal.com/sdk/js/reference/#link-onshippingoptionschange)event in your PayPal configuration object to handle situations where the shopper selects a different delivery method. Make a POST [/paypal/updateOrder](https://docs.adyen.com/api-explorer/Checkout/latest/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** ```js 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. } ``` ### 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: ### 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](#review-page) instead. In your `AdyenCheckout` configuration, or in the `paypalConfiguration` object, implement the [`onAdditionalDetails` ](/online-payments/build-your-integration/sessions-flow/?platform=Web\&integration=Components#adyencheckout-configuration)callback, which makes a POST [/payments/details](https://docs.adyen.com/api-explorer/Checkout/latest/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** ```js onAdditionalDetails: async (state, component) => { const response = await makePaymentDetailsCall(state); // The rest of your implementation. } ``` Below is an example [/payments/details](https://docs.adyen.com/api-explorer/Checkout/latest/post/payments/details) request to authorize the payment: **Make a /payments/details request** ```bash curl https://checkout-test.adyen.com/v72/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 ### Tab: Sessions flow Adding a payment review page is not possible if your integration uses the Sessions flow. ### Tab: Advanced flow 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](#get-shopper-payment-information-advanced). Follow the steps below after you have followed the guide to [set up PayPal express](#set-up-paypal-express) until the [Submit additional payment details](#send-additional-payment-details-advanced) 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** ```js const payPalConfiguration = { isExpress: true, userAction: 'continue' // ... Your other configurations. } ``` ### 2. Create a review page Use the [shopper details you collected](#get-shopper-payment-information-advanced) 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 ### 3. Redirect shopper to the review page In your `AdyenCheckout` configuration, or in the `paypalConfiguration` object, implement the [`onAdditionalDetails` ](/online-payments/build-your-integration/sessions-flow/?platform=Web\&integration=Components#adyencheckout-configuration)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](#send-additional-payment-details) later. **Configure userAction** ```js onAdditionalDetails: async (state, component) => { storePaymentData(state.data); redirectShopperToReviewPage(); } ``` ### 4. Submit additional payment details When the shopper selects the **Pay** button on the review page, make a POST [/payments/details](https://docs.adyen.com/api-explorer/Checkout/latest/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** ```bash curl https://checkout-test.adyen.com/v72/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](/online-payments/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](/payment-methods/paypal/web-component/express-checkout/?tab=1#add-additional-paypal-configuration) 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 [Create tokens](/online-payments/tokenization/create-tokens) and [Make token payments](/online-payments/tokenization/make-token-payments).