PayPal

Overview

This guide will help you integrate the PayPal payment gateway into your Chec/Commerce.js storefront. PayPal works differently to other payment gateways supported in the Chec Platform in that it redirects the user off-site to PayPal in order to complete the transaction.

In this guide

  1. An overview of the flow between Commerce.js and PayPal
  2. An example implementation that shows how to use PayPal and capture the order with Commerce.js

Payment flow

The payment flow with PayPal differs from other payment methods. Instead of showing a credit card form, the user will need to be directed off-site to PayPal in order to complete the transaction. This can be done using PayPal's express checkout order API for example. Currently we support PayPal Checkout.js v1.

Example implementation

This implementation assumes you have already set up a PayPal account and generated test keys. You can follow the prerequisites listed in their guide for "Web integrations" to learn more.

This implementation also assumes you are familiar with some modern JavaScript features including async/await and object destructuring assignment.

Create PayPal checkout for authorization

The PayPal SDK can only be installed by adding their SDK available as a JavaScript file in a script tag to your webpage.

<script src="https://www.paypalobjects.com/api/checkout.js"></script>

Note that this must be served by PayPal for your site to remain PCI compliant.

We will also need to add a container for PayPal smart button to target.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <!-- PayPal SDK -->
    <script src="https://www.paypalobjects.com/api/checkout.js"></script>
  </head>
  <body>
    <noscript>
      <strong>We're sorry but the store doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="checkout">
      <!-- This is the div that we will target with the PayPal SDK -->
      <div id="paypal-button-container"></div>
    </div>
  </body>
</html>

To use PayPal as a payment method in Commerce.js, you need to add the field payment.paypal.action = 'authorize' to the checkout.capture() request payload:

// Create a Commerce.js instance using your sandbox key
const commerce = new Commerce('pk_test_commercejsKey');

// Create a function that will generate the PayPal approval URL to be called when the checkout loads.
async function getPaypalPaymentId() {
  try {
    // Use a checkout token ID that was generated earlier, and any order details that may have been collected
    // on this page.
    const paypalAuth = await commerce.checkout.capture(checkoutTokenId, {
      ...orderDetails,
      // Include PayPal action:
      payment: {
        gateway: 'paypal',
        paypal: {
          action: 'authorize',
        },
      },
    })

    // If we get here, we can now push the user to the PayPal URL.
    // An example of rendering the PayPal button is below
    renderPaypalButton(paypalAuth);
    return;
  } catch (response) {
    // There was an issue with capturing the order with Commerce.js
    console.log(response);
    alert(response.message);
    return;
  } finally {
    // Any loading state can be removed here.
  }
}

Commerce.js will respond with the data required for you to redirect the customer to PayPal in order to complete the transaction.

Response example

{
  "payment_redirect": true,
  "gateway": "paypal",
  "approval_url": "https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=EC-1UB873725N080641H",
  "payment_id": "PAY-51028384J84281644LGFZXJQ",
  "experience_profile_id": "TXP-3SD921203P6940911",
  "payment_token": "EC-1UB873725N080641H"
}

Create PayPal checkout

Next, use the payment_id from the response above to generate a PayPal express checkout using PayPal's order API.. An example of this can be found below:

function renderPaypalButton(paypalAuth) {
    paypal.Button.render({
      env: 'production', // Or 'sandbox',
      commit: true, // Show a 'Pay Now' button
      payment: function() {
        return paypalAuth.payment_id // The payment ID from earlier

      },
      onAuthorize: function(data, actions) {
        // Handler if customer DOES authorize payment (this is where you get the payment_id & payer_id you need to pass to Chec)
        captureOrder(data);
      },
      onCancel: function(data, actions) {
        // Handler if customer does not authorize payment
      }
    },
    '#paypal-button-container'
  );
}

If the customer approves the order, Paypal will return the payer_id & payment_id_.

Capture the PayPal payment & order

Finally, add the payer_id & payment_id_ to the Commerce.js checkout.capture() call, and change the PayPal action from 'authorize' to 'capture'.

// Create a function that can be called when the PayPal payment has been authorized.
async function captureOrder() {
  try {
    // Complete capturing the order.
    const order = await commerce.checkout.capture(checkoutTokenId, {
      ...orderDetails,
      // We have now changed the action to "capture" as well as included the "payment_id and "payer_id"
      payment: {
        gateway: 'paypal',
        paypal: {
          action: 'capture',
          payment_id: 'PAY-51028384J84281644LGFZXJQ',
          payer_id: 'VE57TQRTVER5Y',
        },
      },
    })

    // If we get here, the order has been successfully captured and the order detail is part of the `order` variable
    console.log(order);
    return;
  } catch (response) {
    // There was an issue capturing the order with Commerce.js
    console.log(response);
    alert(response.message);
    return;
  } finally {
    // Any loading state can be removed here.
  }
}
Edit this page on GitHub