DEV Community


Posted on • Updated on

How to collect payments with PayPal in your React application

I recently built a project that required integrating with Paypal to collect payments from users. After spending hours trying to implement Paypal payments using the Paypal JavaScript SDK, I realized that this was going to be a uphill task. Thankfully, I found an NPM package that already abstracted the SDK into React components for us to use. In this article, I’ll show you exactly how to collect payments using Paypal in your React application.

Getting started - setup your Paypal account

First steps first. Head over to paypal to create an account. Once done, head to the paypal developer screen.

Getting your credentials

Next step is to grab your credentials i.e your clientId.

Navigate to Dashboard > My Apps & Credentials .

Click the Sandbox tab. Then click the on the Default Application link. It will bring you to a page containing your clientId.

Your sandbox account will be an email address that you can use to make test payments while your client ID is what Paypal uses to connect your Application to your paypal account.

Setup your react project

For this example, our React project will be built using NextJS.

If you’ll like to follow along, you can skip the next couple of steps by simply cloning my repo. Run the git clone command to do so. Then checkout to the starter branch with git checkout starter . If you clone the starter repo, you can skip to the Setup project structure section.

Otherwise, here are the steps to follow.

We’ll be using one of the NextJS example projects with tailwindcss already configured.

Run the command yarn create next-app --example with-tailwindcss next-paypal-example to create a NextJS application with Tailwindcss already configured.

Setup Project Structure

We’ll create a new folder in our current project called utils. Inside our utils folder, we’ll create a constants folder. Within the constants folder, add an index.js file.

Your folder structure should now look like

Enter fullscreen mode Exit fullscreen mode

Install the Paypal package
Install the react paypal package using yarn add @paypal/react-paypal-js@4.1.0.
Make sure to use the package at version 4.1.0 as i've found that people are having issues with the later version. I haven't had the time to try out later versions yet.

Collect Payments

Time to start collecting Payments!

In your utils/constants/index.js file, add your clientId.

export const PAYPAL_CLIENT_ID = {
    clientId: 'ATVzbN_TdDnGGVfyPxu6J-5ddFftdqu8l6tFpIy5TEZ7hjbx7y9Q4TY0ICI0Pot2dBBABc-myxZgYOfj'
Enter fullscreen mode Exit fullscreen mode

In your _app.js file, bring in the PayPalScriptProvider using import { PayPalScriptProvider } from "@paypal/react-paypal-js";.

Then, wrap your Components with that tag.

import { PayPalScriptProvider } from "@paypal/react-paypal-js";
    import {PAYPAL_CLIENT_ID} from '../utils/constants'
    function MyApp({ Component, pageProps }) {
        <PayPalScriptProvider options= {{"client-id": PAYPAL_CLIENT_ID.clientId }}>
            <Component {...pageProps} />
    export default MyApp
Enter fullscreen mode Exit fullscreen mode

Next, head into pages/index.js to create the page that collects the payments and bring in the PayPal Button.

Let’s create some state to hold data.

      const [succeeded, setSucceeded] = useState(false);
      const [paypalErrorMessage, setPaypalErrorMessage] = useState("");
      const [orderID, setOrderID] = useState(false);
      const [billingDetails, setBillingDetails] = useState("");

Enter fullscreen mode Exit fullscreen mode

The orderId is the most important piece of state we care about. When the user clicks the Pay with PayPal button, Paypal will generate an orderId for the order and return that back to us. In the createOrder function below, we can see this in action.

      // creates a paypal order
      const createOrder = (data, actions) => {
        return actions.order
            purchase_units: [
                amount: {
                  // charge users $499 per order
                  value: 499,
            // remove the applicaiton_context object if you need your users to add a shipping address
            application_context: {
              shipping_preference: "NO_SHIPPING",
          .then((orderID) => {
            return orderID;
Enter fullscreen mode Exit fullscreen mode

Along with the createOrder function, we need another function that runs when the payment is approved - onApprove

      // handles when a payment is confirmed for paypal
      const onApprove = (data, actions) => {
        return actions.order.capture().then(function (details) {
          const {payer} = details;
        }).catch(err=> setPaypalErrorMessage("Something went wrong."));

Enter fullscreen mode Exit fullscreen mode

Lastly, we can plugin out PayPal button from our react-paypal-js package to handle the payments.

                  color: "blue",
                  shape: "pill",
                  label: "pay",
                  tagline: false,
                  layout: "horizontal",

Enter fullscreen mode Exit fullscreen mode

Paypal will redirect the user to a new window to complete the payment.

You can test this out using the sandbox email provided on the Paypal developer dashboard.

The full repo for the code is here.

Top comments (8)

jai_type profile image
Jai Sandhu

I'm getting this in Next Js, Uncaught DOMException: Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded. I think it might only work with regular React

debosthefirst profile image

This example was written with NextJS so it should work. Have you tried using the example code in the Git repo I provided? Also make sure you're using the react-paypal version I specified in this example.

jai_type profile image
Jai Sandhu

Awesome, downgrading it worked. Thanks!!

vinnychase28 profile image
Vincent Gauthier

im getting Unhandled Runtime Error
ReferenceError: PayPalButtons is not defined

any solution?

debosthefirst profile image

Did you try downgrading the PayPal package?

dagoosemancomet profile image

How would you pass a dynamic variable to the 'amount' section instead of using 449? Seems when I try it with a setState it maintains a default value.

tadjerounimohamedadel profile image
Adel Mohamed Tadjerouni

Thanks for this awesome post.
I just have a note: why you saved your clientId on a js file, I think is better to use .env or .env.local and save it as an environment variable
Thanks again

debosthefirst profile image

Hey. Thanks for leaving a comment. The clientId will be exposed on the client side either ways so exposing it isn't too much of a security risk as PayPal handles ensuring that it's secure.