How to add PayPal checkout payments to your React app
Tags: webdev, javascript, react, tutorial
Published: 2022-11-02 17:25:59

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](https://www.paypal.com/us/home) as your checkout payment solution for your ReactJS app using the [react-paypal-js](https://www.npmjs.com/package/@paypal/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

- **[Part 1: PayPal Developer sandbox App](#part-1-paypal-developer-sandbox-app)**
  - Creating an app using the PayPal sandbox
- **[Part 2: Adding PayPal to your React App](#part-2-adding-paypal-to-your-react-app)**
  -  Add the PayPal NPM package
  -  Working with the `PayPalScriptProvider`
  -  Loading state with the `usePayPalScriptReducer`
  -  Adding the PayPal buttons
- **[Part 3: Testing the PayPal Checkout](#part-3-testing-the-paypal-checkout)**
  - Testing the PayPal Checkout

This tutorial requires the following:
- A PayPal Developer Account
- A ReactJS application (I'm using [create react app](https://create-react-app.dev/) for this example).

You can find the source code to this guide in our [PayPal React Sample App](https://github.com/paypaldev/PayPal-React-Checkout-Sample) 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](https://developer.paypal.com/home) 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yohdrnoqb0q5zn63gxg4.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mqmj54vyxjgmvntpzsgq.png)

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](https://www.paypal.com/signin?returnUri=https%3A%2F%2Fdeveloper.paypal.com%2Fdeveloper%2Fapplications&_ga=1.9387580.841672670.1664266268).

![Copy the Client ID generated for your PayPal app](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x7k65xm92t6kalkap4xj.png)

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](https://www.npmjs.com/package/@paypal/react-paypal-js) 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](https://reactjs.org/docs/context.html) 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](https://github.com/paypal/react-paypal-js/issues).

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:

```javascript
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](https://developer.paypal.com/docs/business/javascript-sdk/javascript-sdk-configuration/).

```javascript
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.

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

Your `App.js` component should look like this:

```jsx
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`.

```javascript
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()`;

```javascript
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.

```javascript
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:

```jsx
{
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](https://developer.paypal.com/sdk/js/reference/#style): This attribute allows you to style the PayPal button E.g color, shape, layout, and more.
- [createOrder](https://developer.paypal.com/docs/api/orders/v2/#orders-create-request-body): This attribute allows you to create the request of your order with the following properties: item_total, purchase_units, and more.
- [onApprove](https://developer.paypal.com/docs/api/orders/v2/#orders_get): 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.

```javascript
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:

```jsx
<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:

```javascript
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](http://localhost:3000) to view the app in your browser.

You should see the following:

![React app with PayPal checkout buttons](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xxuabyfb8ubwnh3la98m.png)

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](https://developer.paypal.com/dashboard/creditCardGenerator) inside of your [PayPal Developer Dashboard](https://www.paypal.com/signin?returnUri=https%3A%2F%2Fdeveloper.paypal.com%2Fdeveloper%2Fapplications&_ga=1.9387580.841672670.1664266268.).
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](https://github.com/paypaldev/PayPal-React-Checkout-Sample) 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.

* Website: [developer.paypal.com](https://developer.paypal.com)
* Twitter: [@paypaldev](https://twitter.com/paypaldev)
* Github:  [@paypal developer](https://github.com/paypaldev)