DEV Community ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป

DEV Community ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป is a community of 963,864 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

Create account Log in
Cover image for How to start with stripe
Roopali Singh
Roopali Singh

Posted on • Updated on

How to start with stripe

Hi there๐Ÿ‘‹,

In this guide we will be learning how to integrate a payment gateway in our web application using stripe.

We are working with React for the frontend and Node & Express for the backend. To make api calls we are using axios library.

For simplicity we will not be focusing on design.
To start we are using create-react-app.

1. After getting our project bootstrapped with create-react-app, in your React code we need to add two dependencies.

npm install --save @stripe/react-stripe-js @stripe/stripe-js
Enter fullscreen mode Exit fullscreen mode

2. Now in App.js file, call the loadStripe function to pass the stripe test publishable key which you can get from the stripe dashboard.
(it is safe to share the stripe publishable key, they arenโ€™t secret).

import { loadStripe } from "@stripe/stripe-js";
const stripePromise = loadStripe(STRIPE_PUBLISHABLE_KEY);

// Make sure to call `loadStripe` outside of a componentโ€™s render 
// to avoid recreating the `Stripe` object on every render.
Enter fullscreen mode Exit fullscreen mode

3. Next, we will pass the returned promise from loadStripe function to Elements provider which is a wrapper that allows us to access Stripe object in any nested component.

import { Elements } from "@stripe/react-stripe-js";
import { loadStripe } from "@stripe/stripe-js";

const stripePromise = loadStripe(STRIPE_PUBLISHABLE_KEY);

function App() {
  return (
    <Elements stripe={stripePromise}>
      <CheckoutPage />
    </Elements>
  );
};
// Render an Elements provider at the root of your React app
// so that it is available everywhere you need it.
export default App;
Enter fullscreen mode Exit fullscreen mode

4. In the CheckoutPage component, we're going to add a CardElement which is a flexible single-line input that collects all necessary card details.

import { CardElement } from "@stripe/react-stripe-js";

function CheckoutPage() {

  function paymentHandler() {
    // We're going to make the function async in the next step
    // handling the payment
  }

  return (
    <div>
      <Form onSubmit={paymentHandler}>
        <CardElement />
        <button>Pay Now</button>
      </Form>
    </div>
  );
};

export default CheckoutPage;
Enter fullscreen mode Exit fullscreen mode

The CardElement will look something like this:
CardElement

5. Now we are going to use these two powerful hooks: useStripe and useElements.

useElements is used to safely pass the payment information collected by the Payment Element to the Stripe API.
useStripe hook returns a reference to the Stripe instance passed to the Elements provider (we're going to use it to confirm payments).

import { CardElement, useElements, useStripe } 
from "@stripe/react-stripe-js";

function CheckoutPage() {
  const stripe = useStripe();
  const elements = useElements();

  async function paymentHandler() {
    if (!stripe || !elements) {
      // Stripe.js has not yet loaded.
      // Make sure to disable form submission until Stripe.js has
      // loaded.
        return;
    }
      // hadling the payment
   }

 return (
   <div>
     <Form onSubmit={paymentHandler}>
       <CardElement />
         <button disabled={!stripe || !elements}>Pay Now</button>
     </Form>
   </div>
  );
};

export default CheckoutPage;
Enter fullscreen mode Exit fullscreen mode

Now to complete payment with stripe, we need a clientSecret which is unique for every payment.

For this we have to create a paymentIntent by providing it with the amount and currency.

This code will be in the backend so let's move to our Node.js code.

6. First, we will install stripe in the backend.

npm install stripe
Enter fullscreen mode Exit fullscreen mode

7. For this step, we will need the stripe test secret key which we can get from the dashboard.

โ–ถ๏ธ(Remember: You must keep your secret API keys confidential. Do not just put it on any version control platform)

import express from "express";
import Stripe from "stripe";

const stripeSecret = new Stripe(STRIPE_SECRET_KEY);

///////////// Getting client secret /////////////

app.post(
  "/api/payment/create", async (request, response) => {
   const total = request.query.total;
   const paymentIntent = await 
stripeSecret.paymentIntents.create({
      amount: total,
      currency: "inr",
    });
    response.status(201).send({
      clientSecret: paymentIntent.client_secret
    });
  }
);
Enter fullscreen mode Exit fullscreen mode

๐Ÿ˜ƒWhoa!
If you have reached up till here then you have covered more than half of the journey. Just a couple more steps to go ๐Ÿ”ฅ

Half way through

So we have written our function to get the clientSecret at the backend.

Now back to frontend.

In the CheckoutPage component, we need to make a request to our server to create a new paymentIntent as soon as the page loads.

import React, { useEffect } from "react";

const [clientSecret, setClientSecret] = useState("");
const [errorMsg, setErrorMsg] = useState("");

useEffect(() => {
  async function getClientSecret(total) {
    try {
      const { data } = await axios.post(
        `/api/payment/create?total=${total * 100}`
      );
      // All API requests expect amounts to be provided
      // in a currencyโ€™s smallest unit.

      setClientSecret(data.clientSecret);
    } catch (error) {
      setErrorMsg(error.message);
    }
  }
  getClientSecret(the_amount);
  }, [the_amount]);
Enter fullscreen mode Exit fullscreen mode

We have now received our clientSecret.

Now there's one last step to complete the payment handler function and do some error handling.

In the CheckoutPage component, we will check if the payment is completed by calling stripe.confirmPayment().

import React, { useEffect, useState } from "react";

function CheckoutPage({ amount }) {
  const [clientSecret, setClientSecret] = useState("");
  const [errorMsg, setErrorMsg] = useState("");
  const [processing, setProcessing] = useState(false);
  const [success, setSuccess] = useState(false);

  useEffect(() => {
      .
      .
      .
    getClientSecret(the_amount);
    }, [the_amount]);

  async function paymentHandler(e) {
      e.preventDefault();
      if (!stripe || !elements || errorMsg) {
        return;
      } else {
        setProcessing(true);
        await stripe.confirmCardPayment(clientSecret, {
            payment_method: {
              card: elements.getElement(CardElement),
            },
          })
          .then(({ paymentIntent }) => {
            setErrorMsg(false);
            setProcessing(false);
            setSuccess(true);
          })
          .catch((error) => {
            setErrorMsg(error.message);
            setProcessing(false);
            setSuccess(false);
          });
      }
    }

  return (
    <div>
      <Form onSubmit={paymentHandler}>
        <CardElement />
        {errorMsg && <div className="errorMsg">{errorMsg}</div>}
        <button disabled={
          !stripe || !elements || processing || success
        }>
          Pay Now
        </button>
      </Form>
    </div>
  );
};

export default CheckoutPage;
Enter fullscreen mode Exit fullscreen mode

We have successfully integrated the payment gateway in our webapp using stripe.

Note: You need to change the test publishable key and test secret key with the live publishable and secret key to use it in the production enviroment.

Here's a demo that I have made with some styling:

I call it Moon with Stripes

Finally Done!

Top comments (7)

Collapse
 
aliraza944 profile image
Ali Raza

Great article... One thing I'd like to suggest is the title, please change it something like Stripe integration in MERN stack or something like that, so that it is easily accessible to the targeted audience.

Collapse
 
roopalisingh profile image
Roopali Singh Author

I appreciate your advice.
I'm new to this platform and this is my first blog. Considering this I've checked my stats and I am getting good amount of reads on this. Still I'll try to change the title, it might reach even more audience.

Collapse
 
cathalmacdonnacha profile image
Cathal Mac Donnacha ๐Ÿš€

Nice job ๐Ÿ‘

Collapse
 
zippcodder profile image
Deon Rich

Nice article!

Collapse
 
roopalisingh profile image
Roopali Singh Author

๐Ÿ˜ŠThank you so much for the feedback. It's the first blog that I have ever written.

Collapse
 
arunim_io profile image
Mugdha Arunim Ahmed

This article is really great. I was trying to add Stripe to my e-commerce website. Thanks to you, I know what to do now.

Collapse
 
roopalisingh profile image
Roopali Singh Author • Edited on

I'm glad that you find it valuable.

๐ŸŒš Life is too short to browse without dark mode