# Upgrade your Checkout integration (/v5/expanded/upgrade)

Upgrade to Expanded Checkout to get dynamic payment buttons, custom styles, and support for PayPal, cards, Pay Later, Venmo, and more on your site.



If you have an [Express Checkout](/archive/express-checkout) or [PayPal Checkout](/v5/checkout/getting-started) integration, PayPal recommends upgrading to Expanded Checkout using the [JavaScript SDK](/sdk/js/configuration/).

The JavaScript SDK has the following benefits:

* Dynamically renders payment buttons instead of using static images.
* Launches payment flow in a pop-up window instead of redirecting to a new page.
* Supports greater control over payment button styles.

Visit the [Eligibility](/expanded/eligibility/) page to learn more about the countries, currencies, and card brands that Expanded Checkout supports.

## Getting started [#getting-started]

Integrate Expanded Checkout to present custom credit and debit card fields to your payers so they can pay with PayPal, debit and credit cards, Pay Later options, Venmo, and alternative payment methods, using your site's branding.

### 1. Review current integration [#1-review-current-integration]

Your current integration determines whether you need to gather information to integrate with Expanded Checkout. Select **Paypal Checkout** or **Express Checkout**:

#### PayPal Checkout

PayPal Checkout uses the same APIs as Expanded Checkout. You don't need to change your API calls or collect parameter information about your current PayPal Checkout integration when you upgrade to Expanded Checkout.

#### Express Checkout

If you have an Express Checkout integration, collect information about your current integration, such as API calls and parameters, so you can set up your new integration.

#### 1. Identify core API Calls [#1-identify-core-api-calls]

You need information from the core API calls in your current integration. Locate the endpoint URLs in your code that manage starting, reviewing, and completing payments. Check the API requests for the following `METHOD` parameter values:

* [`SetExpressCheckout`](/api/nvp-soap/set-express-checkout-nvp/)
* [`GetExpressCheckoutDetails`](/api/nvp-soap/get-express-checkout-details-nvp/)
* [`DoExpressCheckoutPayment`](/api/nvp-soap/do-express-checkout-payment-nvp/)

#### 2. Document parameters [#2-document-parameters]

Review the core API calls from your current integration and make a list of the [parameters](/api/nvp-soap/nvp/), such as `PAYMENTREQUEST_0_AMT`.

#### 3. Parameter mapping tool [#3-parameter-mapping-tool]

Map these parameters to the new API using our [parameter mapping tool](/api) in our **PayPal API Transformer**.

### 2. Set up your sandbox [#2-set-up-your-sandbox]

#### Sign up for a developer account [#sign-up-for-a-developer-account]

You need a [PayPal developer account](/dashboard/) to get sandbox credentials.

#### Get your credentials [#get-your-credentials]

[Follow this onboarding document](/api/rest/) to get a client ID, client secret, access token, and sandbox account credentials:

* **Client ID:** Authenticates your account with PayPal and identifies an app in your sandbox.
* **Client secret:** Authorizes an app in your sandbox. Keep this secret safe and don't share it.
* **Access token:** Authenticates your app when calling PayPal REST APIs.

#### Set up your sandbox account [#set-up-your-sandbox-account]

This integration requires a [sandbox business account](/dashboard/) with the Expanded Credit and Debit Card Payments capability. Your sandbox business account should automatically have this capability.

To confirm that Expanded Credit and Debit Card Payments are enabled for you, check your sandbox business account as follows:

1. Log into the [**PayPal Developer Dashboard**](/dashboard/), toggle **Sandbox**, and go to **Apps & Credentials**.
2. In **REST API apps**, select the name of your app.
3. Go to **Features** > **Accept payments**.
4. Select the **Expanded Credit and Debit Card Payments** checkbox and select **Save Changes**.

**Note:** If you created a sandbox business account through [sandbox.paypal.com](https://www.sandbox.paypal.com/?_ga=1.130510220.248280996.1670866755), and the Expanded Credit and Debit Card Payments status for the account is disabled, [complete the sandbox onboarding steps](https://www.sandbox.paypal.com/bizsignup/?_ga=1.130510220.248280996.1670866755#/checkAccount).

## Integrate Expanded Checkout [#integrate-expanded-checkout]

Before beginning your integration, you need to set up your development environment. See the preceding **Getting started** section for details.

## 1. Set up front end [#1-set-up-front-end]

Set up your front end for Expanded Checkout. Select **PayPal Checkout** or **Express Checkout**:

#### PayPal Checkout

Set up your front end to use PayPal card fields and payment buttons in Expanded Checkout. Include `components=buttons,card-fields` in your JavaScript SDK `<script>` tag:

* The `card-fields` component renders the card fields.
* The `buttons` component renders the PayPal buttons.

#### Paypal Checkout JavaScript SDK Script Tag [#paypal-checkout-javascript-sdk-script-tag]

```text lineNumbers
<script src="https://www.paypal.com/sdk/js?currency=USD&client-id=YOUR_SANDBOX_CLIENT_ID"></script>
```

#### Update SDK Script Tag to Expanded Checkout JavaScript [#update-sdk-script-tag-to-expanded-checkout-javascript]

```text lineNumbers
<script src="https://www.paypal.com/sdk/js?currency=USD&client-id=YOUR_SANDBOX_CLIENT_ID&components=buttons,card-fields"></script>
```

#### Express Checkout

Set up your front end to use PayPal payment buttons in Expanded Checkout. Follow the integration instructions for your current integration:

### NVP/SOAP API-only integration [#nvpsoap-api-only-integration]

#### Integrate PayPal's latest JavaScript SDK [#integrate-paypals-latest-javascript-sdk]

PayPal's JavaScript SDK supports how you want to accept payments on your website. Our SDK handles displaying the buttons for PayPal and other payment methods, so your customers can pay with whatever method they choose. See
[Getting started](/v5/checkout/getting-started) for more information.

1. Follow steps 1-5 in the [Integrate PayPal Checkout guide](/v5/checkout/one-time) to set up and customize your PayPal payment buttons with JavaScript SDK v5.
2. Afterwards, update the JavaScript SDK `<script>` tag with the following code sample to enable Expanded Checkout payments:

```text lineNumbers
<script src="https://www.paypal.com/sdk/js?client-id=YOUR_CLIENT_ID&components=buttons,card-fields"></script>
```

### NVP/SOAP API and JavaScript SDK v4 [#nvpsoap-api-and-javascript-sdk-v4]

#### Upgrade your legacy JavaScript SDK from v4 to v5 [#upgrade-your-legacy-javascript-sdk-from-v4-to-v5]

If you are using a previous version of PayPal's Javascript SDK, upgrade your SDK to access the full range of features offered by PayPal Complete Payments.

1. Follow this guide to [upgrade your SDK to the most recent version](/sdk/js/set-up).
2. Afterwards, update the JavaScript SDK `<script>` tag with the following code sample to enable Expanded Checkout payments:

```text lineNumbers
<script src="https://www.paypal.com/sdk/js?client-id=YOUR_CLIENT_ID&components=buttons,card-fields"></script>
```

## 2. Create and render card fields and payment buttons [#2-create-and-render-card-fields-and-payment-buttons]

Set up your front end to use PayPal card fields and start accepting credit and debit card payments. Select &#x2A;*PayPal\*\***&#x43;heckout\*\* or \*\*Express Checkout\*\*:

#### PayPal Checkout

Update your HTML code by replacing your PayPal Checkout button code with the **Expanded Checkout card fields and payment button** code sample:

### Original PayPal Checkout payment button, HTML [#original-paypal-checkout-payment-button-html]

```text lineNumbers
<div id="paypal-button-container"></div>
<script>
  paypal.Buttons({
    // Button configuration and event handlers
  }).render('#paypal-button-container');
</script>
```

### Expanded Checkout card fields and payment button, HTML [#expanded-checkout-card-fields-and-payment-button-html]

```text lineNumbers
<div id="paypal-button-container"></div>
<div class="card-fields-container">
  <div id="card-fields" class="card-fields"></div>
  <button id="card-fields-submit">Submit</button>
</div>
<script>
  paypal.Buttons({
    // Button configuration and event handlers
  }).render('#paypal-button-container');
  paypal.CardFields({
    createOrder: function() {
      return fetch('/create-order', {
        method: 'post'
      }).then(function(res) {
        return res.json();
      }).then(function(orderData) {
        return orderData.id; // Use the order ID to create the order
      });
    }
  }).render('#card-fields'); // Render the card fields into #card-fields
  // Handle the submit button for card fields
  document.getElementById('card-fields-submit').addEventListener('click', function() {
    paypal.CardFields().submit().then(function(result) {
      alert('Payment authorized');
    }).catch(function(err) {
      console.error('Payment authorization failed:', err);
      alert('Payment authorization failed');
    });
  });
</script>
```

#### Express Checkout

Copy and paste the following code sample into your app file to add Expanded Checkout PayPal card fields and payment buttons:

```text lineNumbers
// Render the card fields
paypal.CardFields({
  createOrder: function() {
    return fetch('/create-order', {
      method: 'post'
    }).then(function(res) {
      return res.json();
    }).then(function(orderData) {
      return orderData.id; // Use the order ID to create the order
    });
  }
}).render('#card-fields'); // Render the card fields into #card-fields
// Handle the submit button for card fields
document.getElementById('card-fields-submit').addEventListener('click', function() {
  paypal.CardFields().submit().then(function(result) {
    alert('Payment authorized');
  }).catch(function(err) {
    console.error('Payment authorization failed:', err);
    alert('Payment authorization failed');
  });
});
```

## Expanded Checkout card fields and payment buttons example [#expanded-checkout-card-fields-and-payment-buttons-example]

For a more detailed example, see [Integrate PayPal buttons and Card Fields](/platforms/checkout/advanced/integrate).

## 3. Set up server-side processing [#3-set-up-server-side-processing]

You may need to set up server-side processing for your integration. Select **PayPal Checkout** or **Express Checkout**:

#### PayPal Checkout

You don't need to set up server-side processing when you upgrade from PayPal Checkout to Expanded Checkout.

#### Express Checkout

If you have an Express Checkout integration, you must set up server-side
processing. You'll need to generate an access token, upgrade your NVP/SOAP API
integration to the
[Orders v2 API](/api/orders/v2), and set up a listener to handle API responses.

### Generate access token [#generate-access-token]

The NVP/SOAP API handles authentication using API credentials, such as
`USER`, `PWD`, and `SIGNATURE`. These
credentials are passed directly in the request.

In contrast, the Orders v2 REST API uses OAuth 2.0 for authentication, which
requires an
[access token](/api/rest/authentication/). To generate an access
token:

1. Declare a `generateAccessToken()` function that makes a `POST` call to the `/v1/oauth2/` token endpoint. This call returns an access token.
2. Set up an `auth` parameter to combine the `PAYPAL_CLIENT_ID` and `PAYPAL_CLIENT_SECRET` as a key-value pair.
3. Establish a data object that captures the `response.json` data from the request and returns the `access_token`.

This example shows a `generateAccessToken()` function:

```text lineNumbers
const generateAccessToken = async () => {
  try {
    if (!PAYPAL_CLIENT_ID || !PAYPAL_CLIENT_SECRET) {
      throw new Error("MISSING_API_CREDENTIALS");
    }
    const auth = Buffer.from(
      PAYPAL_CLIENT_ID + ":" + PAYPAL_CLIENT_SECRET
    ).toString("base64");
    const response = await fetch(`${base}/v1/oauth2/token`, {
      method: "POST",
      body: "grant_type=client_credentials",
      headers: {
        Authorization: `Basic ${auth}`,
      },
    });
    const data = await response.json();
    return data.access_token;
  } catch (error) {
    console.error("Failed to generate Access Token:", error);
  }
};
```

### Upgrade your NVP/SOAP API integration to Orders v2 [#upgrade-your-nvpsoap-api-integration-to-orders-v2]

Use the Orders v2 API to create, update, retrieve, authorize, and capture
orders. Use the Payments v2 API for post-payment actions. The following table
shows how a one-time payment request in NVP/SOAP APIs maps to an Expanded Checkout request in the Orders v2 REST API:

| **NVP/SOAP API**<br />            | **Orders v2 REST API**<br />                         |
| --------------------------------- | ---------------------------------------------------- |
| `METHOD=SetExpressCheckout`<br /> | `POST /v2/checkout/orders`<br />                     |
| `METHOD=GetExpressCheckout`<br /> | `GET /v2/checkout/orders/{order_id}`<br />           |
| `METHOD=DoExpressCheckout`<br />  | `PATCH /v2/checkout/orders/{order_id}/capture`<br /> |
| `METHOD=DoExpressCheckout`<br />  | `POST /v2/checkout/orders/{order_id}`<br />          |

To help you construct the request body to support the Orders v2 format, copy
and paste your NVP/SOAP request body into our
[API Transformer tool](/api).

#### Changing order details between request and capture [#changing-order-details-between-request-and-capture]

The NVP/SOAP integration uses the `DoExpressCheckout` API to
process both order updates and capture order requests. When you need to change
the order details, such as the address or amount, after your original
`SetExpressCheckout` call, you can make a single
`DoExpressCheckout` call to simultaneously change the order details
and capture the payment.

To change the order details between request and capture using Expanded Checkout, you need to make 2 calls to the Orders V2 API: an
[Update order](/api/orders/v2/orders-patch)
`PATCH` request to update the order, and a
[Capture payment for order](/api/orders/v2/orders-capture)
request to finalize the checkout flow.

#### Example payloads [#example-payloads]

The following are examples of NVP/SOAP API request payloads and how they map
to an [Expanded Checkout](/v5/expanded/overview/) request in the Orders v2 REST API:

**1. SetExpressCheckout to CreateOrders**

Deprecated NVP Request:

```text lineNumbers
USER=xxxxxxxx
&PWD=xxxxxxx
&SIGNATURE=xxxxxxxxx
&METHOD=SetExpressCheckout
&VERSION=124.0
&RETURNURL=http://mywebsite.com/return
&CANCELURL=http://mywebsite.com/cancel
&PAYMENTREQUEST_0_PAYMENTACTION=Sale
&PAYMENTREQUEST_0_AMT=111.11
```

Deprecated SOAP Request:

```text lineNumbers
<soap:envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:header>
        <ns2:requestercredentials xmlns:ns2="urn:ebay:api:PayPalAPI" xsi:type="ebl:CustomSecurityHeaderType">
            <credentials xmlns="urn:ebay:apis:eBLBaseComponents" xsi:type="ebl:UserIdPasswordType">
                <username>xxxxx</username>
                <password>xxxxx</password>
                <signature>xxxxx</signature>
                <subject></subject>
            </credentials>
        </ns2:requestercredentials>
    </soap:header>
    <soap:body>
        <ns2:setexpresscheckoutreq xmlns="urn:ebay:apis:eBLBaseComponents" xmlns:ns2="urn:ebay:api:PayPalAPI" xmlns:ns3="urn:ebay:apis:EnhancedDataTypes">
            <ns2:setexpresscheckoutrequest>
                <version>204.0</version>
                <setexpresscheckoutrequestdetails>
                    <returnurl>http://mywebsite.com/return</returnurl>
                    <cancelurl>http://mywebsite.com/cancel</cancelurl>
                    <noshipping>0</noshipping>
                    <addressoverride>0</addressoverride>
                    <localecode>en_US</localecode>
                    <paymentdetails>
                        <ordertotal currencyid="USD">60.00</ordertotal>
                        <itemtotal currencyid="USD">20.00</itemtotal>
                        <shippingtotal currencyid="USD">20.00</shippingtotal>
                        <taxtotal currencyid="USD">20.00</taxtotal>
                        <shiptoaddress>
                            <name>John Doe</name>
                            <street1>630 Allendale Road</street1>
                            <street2>Building A</street2>
                            <cityname>Philadelphia</cityname>
                            <stateorprovince>PA</stateorprovince>
                            <country>US</country>
                            <postalcode>19019</postalcode>
                        </shiptoaddress>
                        <paymentdetailsitem>
                            <name>Shirt</name>
                            <number>1</number>
                            <quantity>2</quantity>
                            <amount currencyid="USD">10.00</amount>
                        </paymentdetailsitem>
                        <paymentaction>Sale</paymentaction>
                    </paymentdetails>
                </setexpresscheckoutrequestdetails>
            </ns2:setexpresscheckoutrequest>
        </ns2:setexpresscheckoutreq>
    </soap:body>
</soap:envelope>
```

Upgrade to Expanded Checkout REST API request:

```text lineNumbers
curl -X POST 'https://api-m.sandbox.paypal.com/v2/checkout/orders' \
-H 'Content-Type: application/json' \
-H 'Prefer: return=representation' \
-H 'Authorization: Bearer bearer_access_token' \
-d '{
  "intent": "CAPTURE",
  "purchase_units": [
    {
      "amount": {
        "currency_code": "USD",
        "value": "111.11"
      }
    }
  ],
  "payment_source": {
    "paypal": {
      "experience_context": {
        "return_url": "http://mywebsite.com/return",
        "cancel_url": "http://mywebsite.com/cancel"
      }
    }
  }
}'
```

**2. SetExpressCheckout to GetOrderDetails**

Deprecated NVP Request:

```text lineNumbers
USER=xxxxxx
&PWD=xxxxxxxxx
&SIGNATURE=xxxxxxx
&METHOD=GetExpressCheckoutDetails
&VERSION=124.0
&TOKEN=EC-72D0681527109671C
```

Deprecated SOAP Request:

```text lineNumbers
<soap:envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:header>
        <ns2:requestercredentials xmlns:ns2="urn:ebay:api:PayPalAPI" xsi:type="ebl:CustomSecurityHeaderType">
            <credentials xmlns="urn:ebay:apis:eBLBaseComponents" xsi:type="ebl:UserIdPasswordType">
                <username>xxxxx</username>
                <password>xxxxx</password>
                <signature>xxxxx</signature>
                <subject></subject>
            </credentials>
        </ns2:requestercredentials>
    </soap:header>
    <soap:body>
    <ns2:getexpresscheckoutdetailsreq xmlns="urn:ebay:apis:eBLBaseComponents" xmlns:ns2="urn:ebay:api:PayPalAPI" xmlns:ns3="urn:ebay:apis:EnhancedDataTypes">
      <ns2:getexpresscheckoutdetailsrequest>
	<version>204.0</version>
        <token>EC-4T284721RX588924R</token>
      </ns2:getexpresscheckoutdetailsrequest>
    </ns2:getexpresscheckoutdetailsreq>
  </soap:body>
</soap:envelope>
```

Upgrade to Expanded Checkout REST API request:

```text lineNumbers
curl https://api-m.sandbox.paypal.com/v2/checkout/orders/2HX49812L18884342 \
-H 'Authorization: Bearer bearer_access_token'
```

**3. DoExpressCheckoutPayments to CaptureOrders**

Deprecated NVP Request:

```text lineNumbers
USER=xxxxxxxx
&PWD=xxxxxxxx
&SIGNATURE=xxxxx
&METHOD=DoExpressCheckoutPayments
&VERSION=124.0
&TOKEN=EC-72D0681527109671C
&PAYMENTREQUEST_0_PAYMENTACTION=Sale
&PAYMENTREQUEST_0_AMT=111.11
```

Deprecated SOAP Request:

```text lineNumbers
<soap:envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:header>
    <ns2:requestercredentials xmlns:ns2="urn:ebay:api:PayPalAPI" xmlns="urn:ebay:apis:eBLBaseComponents">
      <credentials>
        <username>xxxx</username>
        <password>xxxx</password>
        <signature>xxxx</signature>
      </credentials>
    </ns2:requestercredentials>
  </soap:header>
  <soap:body>
    <ns2:doexpresscheckoutpaymentreq xmlns="urn:ebay:apis:eBLBaseComponents" xmlns:ns2="urn:ebay:api:PayPalAPI" xmlns:ns3="urn:ebay:apis:EnhancedDataTypes">
      <ns2:doexpresscheckoutpaymentrequest>
        <version>204.0</version>
          <doexpresscheckoutpaymentrequestdetails>
            <token>EC-4T284721RX588924R</token>
            <payerid>YQ27B4JJCW92J</payerid>
            <paymentdetails>
	      <ordertotal currencyid="USD">60.00</ordertotal>
 	      <paymentaction>Sale</paymentaction>
	    </paymentdetails>
	  </doexpresscheckoutpaymentrequestdetails>
      </ns2:doexpresscheckoutpaymentrequest>
    </ns2:doexpresscheckoutpaymentreq>
  </soap:body>
</soap:envelope>
```

Upgrade to Expanded Checkout REST API request:

```text lineNumbers
curl -X POST 'https://api-m.sandbox.paypal.com/v2/checkout/orders/2HX49812L18884342/capture' \
-H 'Content-Type: application/json' \
-H 'Prefer: return=representation' \
-H 'Authorization: Bearer bearer_access_token'
```

### Handle responses [#handle-responses]

Create a `handleResponse` function to set up a listener that
returns an HTTP status code from the API response.

1. Set up `handleResponse` to make a `POST` call to the `/api/orders` endpoint and return an HTTP status code response.
2. Declare an `errorMessage` object that shows an error message when `handleResponse` returns an error code.

This example shows a `handleResponse()` function:

```text lineNumbers
async function handleResponse(response) {
  try {
    const jsonResponse = await response.json();
    return {
      jsonResponse,
      httpStatusCode: response.status,
    };
  } catch (err) {
    const errorMessage = await response.text();
    throw new Error(errorMessage);
  }
}
```

## 4. Fine-tune your checkout experience [#4-fine-tune-your-checkout-experience]

See [Customize your buyers' experience](/platforms/checkout/advanced/customize/) to configure the details of your integration.

## 5. Test integration [#5-test-integration]

Before going live, test your integration in the [sandbox environment](/sandbox-testing/overview). Learn more about [card testing](/sandbox-testing/card-testing), simulating successful payments using [test card numbers](/sandbox-testing/card-testing#test-generated-card-numbers) and generating card error scenarios using [rejection triggers](/sandbox-testing/card-testing#simulate-card-error-scenarios).

**Note:** Use the credit [card generator](/sandbox-testing/card-testing#credit-card-generator) to generate test credit cards for sandbox testing.

Test the following use cases before going live:

### PayPal Payment [#paypal-payment]

Test a purchase as a payer:

1. Select the PayPal button on your checkout page.
2. Log in using one of your [personal sandbox accounts](https://www.sandbox.paypal.com/bizsignup/). This ensures the payments will be sent to the correct account. Make sure that you use the sandbox business account that corresponds to the REST app you are using.
3. Note the purchase amount in the PayPal checkout window.
4. Approve the purchase with the **Pay Now button**. The PayPal window closes and redirects you to your page, indicating that the transaction was completed.

Confirm the money reached the business account:

1. Log in to [the PayPal sandbox](https://www.sandbox.paypal.com/signout) using the [sandbox business account](https://www.sandbox.paypal.com/signin) that received the payment. Remember that the SDK source now uses a sandbox client ID from one of [your REST apps](/dashboard/applications/sandbox), and not the default test ID.
2. In **Recent Activity**, confirm that the sandbox business account received the money, subtracting any fees.
3. Log out of the account.

### Card payment [#card-payment]

1. Go to the checkout page for your integration.
2. Generate a test card using the credit [card generator](/sandbox-testing/card-testing#credit-card-generator).
3. Enter the card details in the hosted field, including the name on the card, billing address, and 2-character [country code](/api/codes/country-region). Then, submit the order.
4. Confirm that the order was processed.
5. Log in to your merchant sandbox account and navigate to the activity page to ensure the payment amount shows up in the account.

## 6. Go live [#6-go-live]

Follow this checklist to take your application live:

1. Log into the PayPal Developer Dashboard with your PayPal business account.
2. Obtain your live credentials.
3. Include the new credentials in your integration and Update your PayPal endpoint.

See [Move your app to production](/reference/production/) for more details.
