Back to Community Blog

How to add PayPal checkout payments to your React app

authorImage

Patricio Vargas

Mar 06, 2023

67 min read

featuredImage

Have you always wondered how to monetize your web applications 🤑? Time to start making those benjamins 💸💸. In this how-to guide, you will learn how to integrate PayPal as your checkout payment solution for your ReactJS app using the react-paypal-js npm package.

What is PayPal? Paypal is a payment processing product that helps you process payments for your mobile and web applications. We provide a fast and easy way to handle online payments, whether it's for a digital media property or an online merchant of any kind in over 100 countries.

Guide Overview

This tutorial requires the following:

  • A PayPal Developer Account
  • A ReactJS application (I'm using create react app for this example).

You can find the source code to this guide in our PayPal React Sample App in our Github Org.

Part 1: PayPal Developer sandbox app


First, we need to create a PayPal app. To do this, navigate to the PayPal Developer Dashboard and login into your PayPal developer account. Once you are inside the PayPal Developer dashboard, make sure you are in the My Apps & Credentials page. Inside this page, click on the blue button Create App.

Create,a,PayPal,app,inside,the,PayPal,developer,Dashboard

Enter the name of the PayPal app you are creating. In my case, I named my app React-checkout. Now, select the App Type to be a Merchant, and click on the blue button Create App.

Name,your,new,PaPal,Developer,App

After creating your PayPal app, you will see a screen similar to mine. In this screen, you will see your Client ID. Copy this ID and save it somewhere (We will use it later on in this tutorial).

You can always get this Client ID by navigating to the app you just created inside of the PayPal Developer Dashboard.

Copy,the,Client,ID,generated,for,your,PayPal,app

Note: Client ID is Class 4 data. Client ID is non-sensitive data, but still be prudent about sharing or posting it. We recommend putting the Client ID in an environment variable in an .env file.

Part 2: Adding PayPal to your React App


Add the PayPal NPM package

To install the react-paypal-js npm package run the following command inside of your project's terminal.

npm install @paypal/react-paypal-js

The PayPal npm package consists of 2 main parts:

  • The Context Provider, this <PayPalScriptProvider/> is responsible for the PayPal JS SDK script. This provider uses the native React Context API for managing the state and communicating with child components. It also supports reloading the script when parameters change.

  • The PayPal SDK Components, components like <PayPalButtons/> are used to render the UI for PayPal products served by the JS SDK.

If you have any issues with this npm package, please report them in its GitHub repo.

After you have installed the react-paypal-js npm package, open your root file, in my case my root file is the App.js file.

In this app, the App.js component is responsible for loading the PayPal script and rendering the <Checkout/> component. The <Checkout/> component will be created later in this tutorial.

In this file, you will import the PayPalScriptProvider from the PayPal npm package.

At the top of the file, add the following line of code:

import { PayPalScriptProvider } from "@paypal/react-paypal-js";

In this file we are adding the initialOptions object, these options can be changed with other configuration parameters. To learn more about the other configuration options look at the PayPal SDK docs.

const initialOptions = {
  "client-id": "YOUR-CLIENT-ID-HERE",
  currency: "USD",
  intent: "capture",
};

Now, make sure you replace the text from the client-id property with the Client ID from your PayPal app.

Working with the PayPalScriptProvider

Finally, inside the App.js, we add the <PayPalScriptProvider/>. Notice we have inside the provider the <Checkout/> component where we have the PayPal components. We now add the options prop to the PayPalScriptProvider to configure the JS SDK. It accepts an object for passing query parameters and data attributes to the JS SDK script.

<PayPalScriptProvider options={initialOptions}>
        <Checkout/>
</PayPalScriptProvider>

Your App.js component should look like this:

import Checkout from './Checkout';
import { PayPalScriptProvider } from "@paypal/react-paypal-js";

const initialOptions = {
  "client-id": "YOUR-CLIENT-ID-HERE",
  currency: "USD",
  intent: "capture",
};

function App() {
  return (
    <PayPalScriptProvider options={initialOptions}>
        <Checkout/>
    </PayPalScriptProvider>
  );
}

export default App;

In our React app, we are giving the user the option to select between 2 currencies (USD and Euro) to make a payment. When the user changes the currency, the value will be passed to the PayPal script thanks to the usePayPalScriptReducer().

Time to create a new Checkout.js component inside of your React application. This file is responsible for loading the PayPal components such as the PayPal buttons.

At the top of the Checkout.js file, add the following line to include the PayPalButtons and the usePayPalScriptReducer.

import { PayPalButtons, usePayPalScriptReducer } from "@paypal/react-paypal-js";

Loading state with the usePayPalScriptReducer

The usePayPalScriptReducer will show a spinner when the PayPal script is loading and can be used to change the values of the options of the PayPal script and at the same time reload the script with the updated parameters.

The PayPal script has several loading states and with the usePayPalScriptReducer we can track it in an easier way. This state can be used to show a loading spinner while the script loads or an error message if it fails to load.

Loading states:

  • isInitial - not started (only used when passing deferLoading={true})
  • isPending - loading (default)
  • isResolved - successfully loaded
  • isRejected - failed to load

In this sample app, we used the isPending state to render the rest of the UI including the PayPalButtons.

Inside your Checkout component add the code below. This code will extract the options, the loading state (isPending), and the dispatch to dispatch an action to our usePayPalScriptReducer();

const [{ options, isPending }, dispatch] = usePayPalScriptReducer();

Adding The Currency Selectors

In the Checkout component, you will add the code to update the state with the new currency the user selects and this will dispatch an action to the usePayPalScriptReducer to update the PayPal script.

const [currency, setCurrency] = useState(options.currency);

    const onCurrencyChange = ({ target: { value } }) => {
        setCurrency(value);
        dispatch({
            type: "resetOptions",
            value: {
                ...options,
                currency: value,
            },
        });
    }

Now, your UI will look like this:

{
isPending ? <p>LOADING...</p> : (
  <>
    <select value={currency} onChange={onCurrencyChange}>
      <option value="USD">đź’µ USD</option>
      <option value="EUR">đź’¶ Euro</option>
    </select>
  </>
 )
}

Adding the PayPal buttons

To start using the PayPal buttons, all you have to do is add the <PayPalButtons/> component to your JSX. The magic comes when you extend the functionality of the PayPal buttons by passing the following props available:

  • style: This attribute allows you to style the PayPal button E.g color, shape, layout, and more.
  • createOrder: This attribute allows you to create the request of your order with the following properties: item_total, purchase_units, and more.
  • onApprove: This attribute allows doing something with the order details after the order has been created.

Inside of your <Checkout/> component, after the onCurrencyChange function add the following functions to be called with the onCreateOrder and onApprove props of the PayPal button.

const onCreateOrder = (data,actions) => {
        return actions.order.create({
            purchase_units: [
                {
                    amount: {
                        value: "8.99",
                    },
                },
            ],
        });
    }

const onApproveOrder = (data,actions) => {
  return actions.order.capture().then((details) => {
  const name = details.payer.name.given_name;
    alert(`Transaction completed by ${name}`);
  });
}

Now we will add the <PayPalButtons/> component to your <Checkout/> component. Your JSX code should look like this:

<div className="checkout">
  {isPending ? <p>LOADING...</p> : 
    (
      <>
        <select value={currency} onChange={onCurrencyChange}>
          option value="USD">đź’µ USD</option>
          <option value="EUR">đź’¶ Euro</option>
        </select>
        <PayPalButtons 
          style={{ layout: "vertical" }}
          createOrder={(data, actions) => onCreateOrder(data, actions)}
          onApprove={(data, actions) => onApproveOrder(data, actions)}
        />
     </>
   )}
</div>

The Final code of the Checkout.js file will look like this:

import React, { useState } from 'react';
import './Checkout.css';
import { PayPalButtons, usePayPalScriptReducer } from "@paypal/react-paypal-js";

const Checkout = () => {
    const [{ options, isPending }, dispatch] = usePayPalScriptReducer();
    const [currency, setCurrency] = useState(options.currency);

    const onCurrencyChange = ({ target: { value } }) => {
        setCurrency(value);
        dispatch({
            type: "resetOptions",
            value: {
                ...options,
                currency: value,
            },
        });
    }

    const onCreateOrder = (data,actions) => {
        return actions.order.create({
            purchase_units: [
                {
                    amount: {
                        value: "8.99",
                    },
                },
            ],
        });
    }

    const onApproveOrder = (data,actions) => {
        return actions.order.capture().then((details) => {
            const name = details.payer.name.given_name;
            alert(`Transaction completed by ${name}`);
        });
    }

    return (
        <div className="checkout">
            {isPending ? <p>LOADING...</p> : (
                <>
                    <select value={currency} onChange={onCurrencyChange}>
                            <option value="USD">đź’µ USD</option>
                            <option value="EUR">đź’¶ Euro</option>
                    </select>
                    <PayPalButtons 
                        style={{ layout: "vertical" }}
                        createOrder={(data, actions) => onCreateOrder(data, actions)}
                        onApprove={(data, actions) => onApproveOrder(data, actions)}
                    />
                </>
            )}
        </div>
    );
}

export default Checkout;

Part 3: Testing the PayPal Checkout


Testing the PayPal Checkout

Inside your project run in the terminal the npm start command to run your ReactJS application.

Open http://localhost:3000 to view the app in your browser.

You should see the following:

React,app,with,PayPal,checkout,buttons

Finally, click on the Debit or Credit Card button to make a payment! You can use the sample card below to test the guest checkout experience with the credit cards.

Sample Card

You can create sample credit card numbers using the PayPal Credit Card Generator inside of your PayPal Developer Dashboard.

Card Type: Visa

Card Number: 4032039534213337

Expiration Date: 03/2026

CVV: 952

Online payments have grown exponentially in the past years, especially during the COVID-19 pandemic. The number of online payment transactions will continue to grow as the years go by. We know that online payments are not going anywhere, but now it’s up to you to get on this trend so your business continues to make money and PayPal is here to help you with this.

You can find the source code to guide in our PayPal React Sample App in our Github Org.

S/O to Greg Jopa for his content that help me write this how-to guide :)

PayPal Developer Community

The PayPal Developer community helps you build your career, while also improving PayPal products and the developer experience. You’ll be able to contribute code and documentation, meet new people and learn from the open source community.

Recommended