Upgrade your Checkout integration

DocsCurrentLast updated: April 13th 2023, @ 2:08:54 pm


If you have older checkout integrations, such as Express Checkout or checkout.js, upgrade your integration to take advantage of the most recent JavaScript SDK integration. The JavaScript SDK keeps your integration current with button styles and payment features.

Know before you code

Before you start the upgrade, understand key concepts of the JavaScript SDK flow:

  • To render the payment buttons, use the JavaScript SDK instead of a static image.
  • The payment flow launches in a pop-up window instead of doing a full-page redirect.

Before you upgrade, complete the steps in Get started to get the following sandbox account information from the Developer Dashboard:

  • Your client ID
  • Your personal and business sandbox accounts

Use your client ID when adding payment options to your website. Use your sandbox accounts when testing the checkout options.

Use Postman to explore and test PayPal APIs.

How it works

After the payer authorizes the transaction, the payment buttons call your JavaScript callback rather than redirecting the payer to a return URL.

Buyer's checkout flow Your payer takes the following actions:

  1. Clicks a payment button.
  2. Logs into PayPal.
  3. Approves the transaction on PayPal.
  4. Returns to your site where you show the payer a confirmation page.

1. Add payment buttons

Add the JavaScript SDK and payment buttons to your page.

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- Ensures optimal rendering on mobile devices. -->
  </head>

  <body>
    <script src="https://www.paypal.com/sdk/js?client-id=YOUR_CLIENT_ID"> // Replace YOUR_CLIENT_ID with your sandbox client ID
    </script>

    <div id="paypal-button-container"></div>

  </body>
</html>

Modify the code

  1. Copy the sample JavaScript SDK code and paste it into the code of your checkout page.
  2. In the SDK code, replace YOUR_CLIENT_ID with your client ID.

See also

Add payment buttons.

2. Update script

Update the script tag to pass the correct parameters for your integration:

  • The currency of the transaction.
  • The intent of the transaction.
  • Whether the transaction is a commit with a Pay Now button or a Continue button.
  • Whether the transaction sets up a vault, including reference transactions or subscriptions.

See all parameters that you can pass to the script. For example:

<script src="https://www.paypal.com/sdk/js?client-id=YOUR_CLIENT_ID&currency=EUR&intent=order&commit=false&vault=true"></script>

3. Set up transaction

When your payer clicks the PayPal button, the script calls a createOrder() function that you define. In this function, return a promise for a token, payment ID, or order ID from the API you're calling:

Note: The createOrder() function in the JavaScript SDK integration replaces the payment() function in the checkout.js script.

NVP/SOAP integrations

Return the token value from an NVP/SOAP SetExpressCheckout response to the client. Then, return that token in the createOrder function:

paypal.Buttons({
  createOrder: function() {
    var SETEC_URL = 'https://mystore.com/api/paypal/set-express-checkout';

    return fetch(SETEC_URL, {
      method: 'post',
      headers: {
        'content-type': 'application/json'
      }
    }).then(function(res) {
      return res.json();
    }).then(function(data) {
      return data.token;
    });
  }
}).render('#paypal-button-container');

Notes:

  • The JavaScript SDK integration doesn't use the RETURNURL and CANCELURL values in the NVP/SOAP API.

    Pass https://www.paypal.com/checkoutnow/error as a placeholder value for these keys. To handle transaction success or failure, use onApprove, onCancel, and onError.

  • To customize the intent, currency, commit, vault and locale values, see the JavaScript SDK reference.

Server-side REST integrations with /v1/payments

Return the EC-XXXXX token from the REST API /v1/payments/payment response.

API endpoint used: Create payment

  1. Locate the token in the response links array, in the object where rel is "approval_url":

    "links": [{
      "href": "https://api-m.sandbox.paypal.com/v1/payments/payment/PAY-1B56960729604235TKQQIYVY",
      "rel": "self",
      "method": "GET"
    }, {
      "href": "https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=EC-60385559L1062554J",
      "rel": "approval_url",
      "method": "REDIRECT"
    }, {
      "href": "https://api-m.sandbox.paypal.com/v1/payments/payment/PAY-1B56960729604235TKQQIYVY/execute",
      "rel": "execute",
      "method": "POST"
      }]
    
  2. Extract the EC-XXXXXX token from the array:

    let token;
    
    for (let link of response.links) {
      if (link.rel === 'approval_url') {
        token = link.href.match(/EC-\w+/)[0];
      }
    }
    
    // Now return the `token` to the client
    
  3. Return the token to createOrder on the client side.

    The required token is EC-60385559L1062554J in this example:

    paypal.Buttons({
      createOrder: function() {
        var CREATE_PAYMENT_URL = 'https://mystore.com/api/paypal/create-payment';
    
        return fetch(CREATE_PAYMENT_URL, {
          method: 'post',
          headers: {
            'content-type': 'application/json'
          }
        }).then(function(res) {
          return res.json();
        }).then(function(data) {
          return data.token;
        });
      }
    }).render('#paypal-button-container');
    

    Notes:

    • The JavaScript SDK integration does not use return_url and cancel_url in the /v1/payments/payment endpoint.

      Pass https://www.paypal.com/checkoutnow/error as a placeholder value for these keys. To handle transaction success or failure, use onApprove, onCancel, and onError.

    • To customize the intent, currency, commit, vault, and locale values, see the JavaScript SDK reference.

Server-side REST integrations with /v2/orders

API endpoint used: Create order

Migrate the actions.payment.create() call to a server-side integration pattern with Orders Create.

See Add payment buttons.

  1. createOrder example (HTML)
  2. createOrder example (node.js)
1<!DOCTYPE html>
2<html>
3 <head>
4 <meta name="viewport" content="width=device-width, initial-scale=1">
5 </head>
6 <body>
7 <!-- Replace "TEST" with your own sandbox Business account app client ID -->
8 <script src="https://www.paypal.com/sdk/js?client-id=TEST&currency=USD"></script>
9 <!-- Set up a container element for the button -->
10 <div id="paypal-button-container"></div>
11 <script>
12 paypal.Buttons({
13 // Order is created on the server and the order id is returned
14 createOrder() {
15 return fetch("/my-server/create-paypal-order", {
16 method: "POST",
17 headers: {
18 "Content-Type": "application/json",
19 },
20 // use the "body" param to optionally pass additional order information
21 // like product skus and quantities
22 body: JSON.stringify({
23 cart: [
24 {
25 sku: "YOUR_PRODUCT_STOCK_KEEPING_UNIT",
26 quantity: "YOUR_PRODUCT_QUANTITY",
27 },
28 ],
29 }),
30 })
31 .then((response) => response.json())
32 .then((order) => order.id);
33 }
34 }).render('#paypal-button-container');
35 </script>
36 </body>
37</html>

4. Finalize payment

After your payer logs in to PayPal and authorizes the transaction, the script calls the onApprove() function, which finalizes the transaction.

Note: The onAuthorize() function from the checkout.js script is replaced by the onApprove() function in the JavaScript SDK integration.

NVP/SOAP integrations

  1. Call your server with the data.orderID and data.payerID values in a DoExpressCheckoutPayment NVP/SOAP API call:

    paypal.Buttons({
      onApprove: function(data) {
        var DOEC_URL = 'https://mystore.com/api/paypal/do-express-checkout';
    
        return fetch(DOEC_URL, {
          method: 'post',
          headers: {
            'content-type': 'application/json'
          },
          body: JSON.stringify({
            token:   data.orderID,
            payerID: data.payerID
          })
        });
      }
    }).render('#paypal-button-container');
    
  2. Call DoExpressCheckoutPayment on your server with the token and payerID.

Server-side REST integrations with /v1/payments

API endpoint used: Create payment

  1. If you have a call to the /v1/payments/payment/PAY-XXX/execute endpoint, call your server with the data.paymentID and data.payerID values:

    paypal.Buttons({
      onApprove: function(data) {
        var EXECUTE_URL = 'https://mystore.com/api/paypal/execute-payment';
    
        return fetch(EXECUTE_URL, {
          method: 'post',
          headers: {
            'content-type': 'application/json'
          },
          body: JSON.stringify({
            paymentID: data.paymentID,
            payerID:   data.payerID
          })
        });
      }
    }).render('#paypal-button-container');
    
  2. On your server, call /v1/payments/payment/PAY-XXX/execute with the paymentID and payerID.

Server-side REST integrations with /v2/orders

API endpoint used: Orders Capture

Migrate the actions.payment.execute() to a server-side integration with the Orders Capture endpoint.

See Set up standard payments.

  1. captureOrder example (HTML)
  2. captureOrder example (node.js)
1<!DOCTYPE html>
2<html>
3 <head>
4 <meta name="viewport" content="width=device-width, initial-scale=1">
5 </head>
6 <body>
7 <!-- Replace "TEST" with your own sandbox Business account app client ID -->
8 <script src="https://www.paypal.com/sdk/js?client-id=TEST&currency=USD"></script>
9 <!-- Set up a container element for the button -->
10 <div id="paypal-button-container"></div>
11 <script>
12 paypal.Buttons({
13 // Finalize the transaction on the server after payer approval
14 onApprove(data) {
15 return fetch("/my-server/capture-paypal-order", {
16 method: "POST",
17 body: JSON.stringify({
18 orderID: data.orderID
19 })
20 })
21 .then((response) => response.json())
22 .then((orderData) => {
23 // Successful capture! For dev/demo purposes:
24 console.log('Capture result', orderData, JSON.stringify(orderData, null, 2));
25 const transaction = orderData.purchase_units[0].payments.captures[0];
26 alert(`Transaction ${transaction.status}: ${transaction.id}\n\nSee console for all available details`);
27 // When ready to go live, remove the alert and show a success message within this page. For example:
28 // const element = document.getElementById('paypal-button-container');
29 // element.innerHTML = '<h3>Thank you for your payment!</h3>';
30 // Or go to another URL: window.location.href = 'thank_you.html';
31 });
32 }
33 }).render('#paypal-button-container');
34 </script>
35 </body>
36</html>

5. Fix deprecations

For checkout.js integrations, upgrade the deprecated integration to the current integration. Check your browser's JavaScript console for errors to debug issues.

Deprecated integrationUpgrade to integration

Add a script that points to paypalobjects.com/api/checkout.js.

Add a script that points to paypalobjects.com/sdk/js.

See Set up standard payments.

Add a client-side call to paypal.Button.render(, '#el');.

Add a client-side call to paypal.Buttons().render('#el');.

See Set up standard payments.

Add the payment() %7B ... %7B callback.

Add the createOrder() %7B ... %7B callback.

See Set up standard payments.

Add the actions.payment.create() call.

Add a server-side call to /v2/checkout/orders.

See Set up standard payments.

Add the onAuthorize() %7B ... %7B callback.

Add the onApprove() %7B ... %7B callback.

See Set up standard payments.

Add the actions.payment.execute() call.

Add a server-side call to /v2/checkout/orders/:id/capture.

See Set up standard payments.

Set style.size to small, medium, large, and responsive.

Set the container element to your preferred size.

See Customize the payment buttons.

Pass the client option in the paypal.Button.render() call.

Pass client-id=xyz to the /sdk/js script tag.

See Set up standard payments.

Pass the commit: true or commit: false option in the paypal.Button.render() call.

Pass commit=true or commit=false to the /sdk/js script tag.

See Commit.

Pass the env option in the paypal.Button.render() call.

Pass client-id=xyz to the /sdk/js script tag and auto-detect the environment.

See Client ID.

Pass the locale option in the paypal.Button.render() call.

Pass locale=xx_XX to the /sdk/js script tag.

See Locale.

Pass the style.fundingicons option in the paypal.Button.render() call.

The card buttons display automatically in the default integration.

See Set up standard payments.

Pass the funding.allowed option in the paypal.Button.render() call.

PayPal automatically decides on the optimal buttons to show to your buyers.

See Set up standard payments.

Pass the funding.disallowed option in the paypal.Button.render() call.

Pass disable-funding or disable-card to the /sdk/js script tag.

See Disable Funding and Disable card.

Use paypal.request, paypal.request.get, paypal.request.post.

Use the built-in browser fetch function, with a polyfill or your AJAX library of choice.

See Fetch.

Use paypal.Promise.

Use the built-in browser Promise, with a polyfill or your promise library of choice.

See Promise.

When you set up transaction, pass return and cancel URLs.

Call actions.redirect() in onAuthorize and onCancel.

When you set up transaction, do not pass return and cancel URLs.

Call window.location.href = 'done_page.html' in onApprove.

Call window.location.href = 'cancel_page.html' in onCancel.

See Redirect.

6. Test your integration

Test and go live with your upgraded integration.