Upgrade Your Checkout Integration

DocsLegacyLast updated: October 12th 2021, @ 6:58:00 pm


Upgrade your PayPal Checkout integration to the latest PayPal JavaScript SDK integration. The new code keeps you current with button styles and payment features.

1. Understand the JavaScript SDK checkout flow

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

  • To render the PayPal button, you must use the PayPal JavaScript SDK rather than a static image.
  • The PayPal Checkout flow now launches in a pop-up window rather than a full-page redirect.
  • After the buyer authorizes the transaction, the PayPal button calls your JavaScript callback rather than redirecting the buyer to a return URL.

Buyer's checkout flow

  1. Your buyer clicks the PayPal Smart Buttons.
  2. Your buyer logs into PayPal.
  3. Your buyer approves the transaction on PayPal.
  4. Your buyer returns to your site, and you show them a confirmation page.

2. Add the Smart Payment Buttons

To add the Smart Buttons to your page:

  1. Add the script to your page.
  2. Render the buttons to your page.

3. Update the 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>

4. Set up the transaction

When your buyer 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 PayPal API you're calling.

Note: The createOrder() function in the PayPal 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 PayPal JavaScript SDK integration does not use the RETURNURL and CANCELURL values that are present in the NVP/SOAP APIs.

    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 learn how to customize the intent, currency, commit, vault and locale values, see Customize PayPal JavaScript SDK script.

Server-side REST integrations with /v1/payments

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

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"
}]

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

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 PayPal JavaScript SDK integration does not usereturn_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.

  • For how to customize the intent, currency, commit, vault, and locale values, see Customize PayPal JavaScript SDK script.

Billing Agreement integrations with /v1/billing-agreements/agreement-tokens

First, update your script tag to pass vault=true.

<script src="https://www.paypal.com/sdk/js?client-id=YOUR_CLIENT_ID&vault=true"></script>

Then, return the BA-XXXXX token to createBillingAgreement from the response of the /v1/billing-agreements/agreement-tokens call:

paypal.Buttons({
  createBillingAgreement: function() {
    var CREATE_BILLING_AGREEMENT_URL = 'https://mystore.com/api/paypal/create-billing-agreement';

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

Notes:

  • The PayPal JavaScript SDK integration does not use the return_url and cancel_url values in the /v1/billing-agreements/agreement-tokens endpoint.

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

  • For how to customize the intent, currency, commit, vault and locale values, see Customize SDK.

checkout.js integrations with actions.payment.create()

Migrate the actions.payment.create() call to actions.order.create().

In the basic integration, see Set up the transaction.

paypal.Buttons({
  createOrder: function() {
    return actions.order.create({
      purchase_units: [{
        amount: {
          value: '220.00'
        }
      }]
    });
  }
}).render('#paypal-button-container');

5. Finalize payment

After your buyer logs in to PayPal and authorizes the transaction, the script calls the onApprove() function that you defined. This function finalizes the transaction.

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

NVP/SOAP integrations

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');

Invoke a DoExpressCheckoutPayment call on your server with the token and payerID.

Server-side REST integrations with /v1/payments

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');

Then on your server, invoke a /v1/payments/payment/PAY-XXX/execute call with the paymentID and payerID.

Billing Agreement integrations with /v1/billing-agreements/agreement-tokens

Call your server with the data.billingToken value in a REST API /v1/billing-agreements/agreements call.

paypal.Buttons({
  onApprove: function(data) {
    var FINALIZE_BILLING_URL = 'https://mystore.com/api/paypal/finalize-billing-agreement';

    return fetch(FINALIZE_BILLING_URL, {
      method: 'post',
      headers: {
        'content-type': 'application/json'
      },
      body: JSON.stringify({
        billingToken: data.billingToken
      })
    });
  }
}).render('#paypal-button-container');

Invoke a /v1/billing-agreements/agreements call on your server with the billingToken.

Client-side REST integrations with actions.payment.create()

Migrate the actions.payment.execute() to actions.order.capture(). In the basic integration, see Capture the transaction.

paypal.Buttons({
  onApprove: function(data, actions) {
    return actions.order.capture();
  }
}).render('#paypal-button-container');

6. Fix deprecations

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

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 Add script.

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

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

See Render buttons.

Add the payment() ... callback.

Add the createOrder() ... callback.

See Set up transaction.

Add the actions.payment.create() call.

Add the actions.order.create() call.

See Set up transaction.

Add the onAuthorize() ... callback.

Add the onApprove() ... callback.

See Capture transaction.

Add the actions.payment.execute() call.

Add the actions.order.capture() call.

See Capture transaction.

Add the actions.payment.get() call.

Add the actions.order.get() call.

See Show confirmation page.

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

Set the container element to your preferred size.

See Customize buttons.

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

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

See Add PayPal script.

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 Add buttons.

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

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

See Add buttons.

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 actions.redirect('/done-page'); in onApprove.

Call actions.redirect('/cancel-page'); in onCancel.

See Redirect.

7. Test your integration

Test your upgraded integration and launch it into production: