Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for Stripe Checkout With Next.js - The Complete Guide
ByteSlash profile imageAshik Chapagain
Ashik Chapagain forByteSlash

Posted on

     

Stripe Checkout With Next.js - The Complete Guide

Hello world

My name is Ashik Chapagain.

  • A full-stack web developer
  • Content Creator
  • College student
  • Nepalese

I'll walk you through the entire process of usingStripe Checkout withNext.js in this article.

Index

Introduction

Let's see the brief introduction ofStripe andStripe Checkout.

Stripe:Stripe is an online payment processing and credit card processing platform for businesses.

Stripe Checkout:Stripe Checkout is prebuilt, hosted payment page optimized for conversion.

Demo

Live Preview:https://stripe-checkout-next-js-demo.vercel.app/

Github:https://github.com/projectashik/stripe-checkout-next-js-demo

Let's Build

Installation

As mentioned in the title, we'll be usingNext.js for building this.

ForNext.js to work, we need to haveNode.js andnpm installed.

So, first, installNode.js if you haven't yet.
You can follow the following guides to installNode.js.

Optional:
If you want to useyarn, install it usingnpm.

npminstall--global yarn
Enter fullscreen modeExit fullscreen mode

Now, create a new Next.js app.

npx create-next-app stripe-checkoutyarn create next-app stripe-checkout
Enter fullscreen modeExit fullscreen mode

I have usedtailwindcss for styling the components. So, let's installtailwindcss too.

yarn add--dev tailwindcss@latest postcss@latest autoprefixer@latestnpminstall-D tailwindcss@latest postcss@latest autoprefixer@latest
Enter fullscreen modeExit fullscreen mode

Then run the following command to create tailwindcss config file and postcss config file.

npx tailwindcss init -p
Enter fullscreen modeExit fullscreen mode

Now open the project in your favorite text editor or IDE (Integrated Development Environment).

For me, it'sVisual Studio Code .

# Run the following command to open the project in VS Code.code.
Enter fullscreen modeExit fullscreen mode

Now, opentailwind.config.js and updatepurge option and addmode: 'jit'.

// tailwind.config.jsmodule.exports = {  purge: ['./pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'],  mode: 'jit',  ...};
Enter fullscreen modeExit fullscreen mode

Then, openstyles/globals.css and remove all the content and add the following content.

@tailwindbase;@tailwindutilities;@tailwindcomponents;
Enter fullscreen modeExit fullscreen mode

*Short Method: *
If you want to use the short process.
Just run the following command.

npx create-next-app-e with-tailwindcss stripe-checkoutyarn create next-app-e with-tailwindcss stripe-checkout
Enter fullscreen modeExit fullscreen mode

Now, start the dev server and start coding.

yarn devnpm run dev
Enter fullscreen modeExit fullscreen mode

Cleaning

Remove themain andfooter tags frompages/index.js.

If you want to edit thetitle anddescription in the<Head> tag. Then you can.

// pages/index.jsimportHeadfrom'next/head';importImagefrom'next/image';importstylesfrom'../styles/Home.module.css';exportdefaultfunctionHome(){return(<divclassName={styles.container}><Head><title>StripeCheckoutwithNext.js</title><metaname='description'content='Complete Step By Step Tutorial for integrating Stripe Checkout with Next.js'/><linkrel='icon'href='/favicon.ico'/></Head></div>);}
Enter fullscreen modeExit fullscreen mode

And remove all the styles except for.container instyles/Home.module.css.

/* styles/Home.module.css */.container{min-height:100vh;padding:00.5rem;display:flex;flex-direction:column;justify-content:center;align-items:center;height:100vh;}
Enter fullscreen modeExit fullscreen mode

Making UI

First, we'll build an index page in which we'll have one item that users can purchase.

Let's add details of an item to an object.

// pages/index.jsconst[item,setItem]=useState({name:'Apple AirPods',description:'Latest Apple AirPods.',image:'https://images.unsplash.com/photo-1572569511254-d8f925fe2cbb?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1400&q=80',quantity:0,price:999,});
Enter fullscreen modeExit fullscreen mode

Don't forget to import theuseState hook.

import{useState}from'react';
Enter fullscreen modeExit fullscreen mode

Since we're using Unsplash for images, so we need to configureimages.unsplash.com under theimages section innext.config.js.

module.exports={reactStrictMode:true,images:{domains:['images.unsplash.com'],},};
Enter fullscreen modeExit fullscreen mode

Now, let's display the following details in the UI and add buttons to increase and decrease the quantity users want to purchase.

In,pages/index.js

...<main><divclassName='shadow-lg border rounded p-2 '><Imagesrc={item.image}width={300}height={150}alt={item.name}/><h2className='text-2xl'>$ {item.price}</h2><h3className='text-xl'>{item.name}</h3><pclassName='text-gray-500'>{item.description}</p><pclassName='text-sm text-gray-600 mt-1'>Quantity:</p><divclassName='border rounded'><buttonclassName='bg-blue-500 py-2 px-4 text-white rounded hover:bg-blue-600'>        -</button><inputtype='number'className='p-2'defaultValue={item.quantity}/><buttonclassName='bg-blue-500 py-2 px-4 text-white rounded hover:bg-blue-600'>        +</button></div><p>Total: ${item.quantity * item.price}</p><buttondisabled={item.quantity===0}className='bg-blue-500 hover:bg-blue-600 text-white block w-full py-2 rounded mt-2 disabled:cursor-not-allowed disabled:bg-blue-100'>      Buy</button></div></main>...
Enter fullscreen modeExit fullscreen mode

Now your page should look like this.

UI demo

Now, let's make the button to increase and decrease the quantity working.

Now, we'll create theonQuantityPlus andonQuantityMinus functions to increase and decrease the item quantity on button clicks.

constchangeQuantity=(value:number)=>{// Don't allow the quantity less than 0, if the quantity is greater than value entered by user then the user entered quantity is used, else 0setItem({...item,quantity:Math.max(0,value)});};constonQuantityPlus=()=>{changeQuantity(item.quantity+1);};constonQuantityMinus=()=>{changeQuantity(item.quantity-1);};
Enter fullscreen modeExit fullscreen mode

Now, add this function in the onClick event of the respective buttons.

...<buttononClick={onQuantityMinus}className='bg-blue-500 py-2 px-4 text-white rounded hover:bg-blue-600'>  -</button>...<buttononClick={onQuantityPlus}className='bg-blue-500 py-2 px-4 text-white rounded hover:bg-blue-600'>  +</button>...
Enter fullscreen modeExit fullscreen mode

Now, let's add theonChange event on the input field to update the value of the item quantity and also don't forget to changedefaultValue tovalue.

...<inputtype='number'className='p-2'onChange={onInputChange}value={item.quantity}/>...
Enter fullscreen modeExit fullscreen mode

Now, let's createonInputChange function.

...//constonInputChange=(e)=>{changeQuantity(parseInt(e.target.value));};...
Enter fullscreen modeExit fullscreen mode

Demo of working item plus and minus

Creating the Backend

First, we'll start by installing thestripe library.

yarn add stripenpm install stripe
Enter fullscreen modeExit fullscreen mode

Now, let's add the requiredenvironment variables.
Create a new file.env.local in the root directory with the following data.

NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=YOUR_STRIPE_PUBLISHABLE_KEYSTRIPE_SECRET_KEY=YOUR_STRIPE_SECRET_KEY
Enter fullscreen modeExit fullscreen mode

You can get these credentials fromDashboard -> Developers -> API Keys.

Getting Stripe Credentials

Now, we need to build an API to get the session id that is required for redirecting the user to the checkout page.

Create a new file inapi/create-stripe-session.js. And add the following.

conststripe=require("stripe")(process.env.STRIPE_SECRET_KEY);exportdefaultasync(req,res)=>{const{item}=req.body;};
Enter fullscreen modeExit fullscreen mode

Here, we are getting item details via a post method that we will call on the front end.

Creating the shape for the item needed by Stripe.

There is a particular type of object which Stripe expects to get, this is the object. You should use your local currency instead of "usd" if you want.

consttransformedItem={price_data:{currency:'usd',product_data:{images:[item.image],name:item.name,},unit_amount:item.price*100,},description:item.description,quantity:item.quantity,};
Enter fullscreen modeExit fullscreen mode

*Creating Stripe Session in the backend: *

You will need to create a stripe session object where you need to define some data.

constsession=awaitstripe.checkout.sessions.create({payment_method_types:['card'],line_items:[transformedItem],mode:'payment',success_url:redirectURL+'?status=success',cancel_url:redirectURL+'?status=cancel',metadata:{images:item.image,},});res.json({id:session.id});
Enter fullscreen modeExit fullscreen mode
  • payment_method_type: In this, we add the payment methods to pay the price of the product.Click here to know more payment methods.

  • success_url: Insuccess_url, you define where the user will go after the payment is successful.

  • cancel_url: In thecancel_url, you define where the user will go if the user clicks the back button. It can be a cancel page or the checkout page as well.

  • metadata: Inmetadata, we will add images of the product, if you want you can add other options too.

For other options,click here to know.

Now, the finalcreate-stripe-session.js file should look like this.

conststripe=require('stripe')(process.env.STRIPE_SECRET_KEY);asyncfunctionCreateStripeSession(req,res){const{item}=req.body;constredirectURL=process.env.NODE_ENV==='development'?'http://localhost:3000':'https://stripe-checkout-next-js-demo.vercel.app';consttransformedItem={price_data:{currency:'usd',product_data:{images:[item.image],name:item.name,},unit_amount:item.price*100,},description:item.description,quantity:item.quantity,};constsession=awaitstripe.checkout.sessions.create({payment_method_types:['card'],line_items:[transformedItem],mode:'payment',success_url:redirectURL+'?status=success',cancel_url:redirectURL+'?status=cancel',metadata:{images:item.image,},});res.json({id:session.id});}exportdefaultCreateStripeSession;
Enter fullscreen modeExit fullscreen mode

Now, our backend is ready, now we have to send a POST request to API to get the session.

Redirecting to Stripe Checkout Page

For redirecting to Stripe Checkout Page. We have to install the following libraries.

yarn add @stripe/stripe-js axiosnpm install @stripe/stripe-js axios
Enter fullscreen modeExit fullscreen mode

First, we'll first create astripePromise variable.

constpublishableKey=process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY;conststripePromise=loadStripe(publishableKey);
Enter fullscreen modeExit fullscreen mode

Now, we'll createcreateCheckoutSession function to get the Stripe Session for the checkout.

constcreateCheckOutSession=async()=>{conststripe=awaitstripePromise;constcheckoutSession=awaitaxios.post('/api/create-stripe-session',{item:item,});constresult=awaitstripe.redirectToCheckout({sessionId:checkoutSession.data.id,});if(result.error){alert(result.error.message);}};
Enter fullscreen modeExit fullscreen mode

Don't forget to importloadStripe andaxios.

import{loadStripe}from'@stripe/stripe-js';importaxiosfrom'axios';
Enter fullscreen modeExit fullscreen mode

Now, we have to call this function while the user clicks theBuy button.
AndonClick={createCheckoutSession}

<buttondisabled={item.quantity===0}onClick={createCheckOutSession}className='bg-blue-500 hover:bg-blue-600 text-white block w-full py-2 rounded mt-2 disabled:cursor-not-allowed disabled:bg-blue-100'>  Buy</button>
Enter fullscreen modeExit fullscreen mode

Now, let's test the checkout.

Since we have updatednext.config.js and added the.env.local file, so restart the dev server.

yarn devnpm run dev
Enter fullscreen modeExit fullscreen mode

Now, the result should look like this.

Credit Card Payment Demo

Displaying Success and Cancel Message

If you guys remember, then we have used?status= query parameter insuccess_url andcancel_url.

// pages/api/create-stripe-session.js...const session = await stripe.checkout.sessions.create({    ...    success_url: redirectURL + '?status=success',    cancel_url: redirectURL + '?status=cancel',    ...  });...
Enter fullscreen modeExit fullscreen mode

So, with this query parameter, we'll know, whether the payment is successful or canceled. And show the respective message.

First, let's fetch the status.

// pages/index.jsimport { useRouter } from 'next/router';...const router = useRouter();const { status } = router.query;
Enter fullscreen modeExit fullscreen mode

Now, add the following below the starting main tag, to display the message.

// pages/index.js{status && status === 'success' && (  <div className='bg-green-100 text-green-700 p-2 rounded border mb-2 border-green-700'>    Payment Successful  </div>)}{status && status === 'cancel' && (  <div className='bg-red-100 text-red-700 p-2 rounded border mb-2 border-red-700'>    Payment Unsuccessful  </div>)}
Enter fullscreen modeExit fullscreen mode

Now, the result should be like this.

Alert Message Demo

Our app took some time to assign a stripe session. So, during that time, let's displayProcessing... instead ofBuy inside the button as shown in the demo.

For that,
Create a new state named loading with default valuefalse.

const [loading, setLoading] = useState(false);
Enter fullscreen modeExit fullscreen mode

Then, updateloading value totrue, while creating Stripe Session. and again updateloading value tofalse when the stripe session is created.

const createCheckOutSession = async () => {  setLoading(true);  ...  setLoading(false);};
Enter fullscreen modeExit fullscreen mode

And now, update theBuy Button.

<button  disabled={item.quantity === 0 || loading}  onClick={createCheckOutSession}  className='bg-blue-500 hover:bg-blue-600 text-white block w-full py-2 rounded mt-2 disabled:cursor-not-allowed disabled:bg-blue-100'>  {loading ? 'Processing...' : 'Buy'}</button>
Enter fullscreen modeExit fullscreen mode

Here, we're disabling the button while loading and displayingProcessing... while loading.

Now, the result should be following:

Button Processing Demo

All done.

Files

At last, yourpages/index.js file should look like below:

importHeadfrom'next/head';importImagefrom'next/image';importstylesfrom'../styles/Home.module.css';import{useState}from'react';import{loadStripe}from'@stripe/stripe-js';importaxiosfrom'axios';import{useRouter}from'next/router';exportdefaultfunctionHome(){constrouter=useRouter();const{status}=router.query;const[loading,setLoading]=useState(false);const[item,setItem]=useState({name:'Apple AirPods',description:'Latest Apple AirPods.',image:'https://images.unsplash.com/photo-1572569511254-d8f925fe2cbb?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1400&q=80',quantity:0,price:999,});constchangeQuantity=(value)=>{// Don't allow the quantity less than 0, if the quantity is greater than value entered by user then the user entered quantity is used, else 0setItem({...item,quantity:Math.max(0,value)});};constonInputChange=(e)=>{changeQuantity(parseInt(e.target.value));};constonQuantityPlus=()=>{changeQuantity(item.quantity+1);};constonQuantityMinus=()=>{changeQuantity(item.quantity-1);};constpublishableKey=process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY;conststripePromise=loadStripe(publishableKey);constcreateCheckOutSession=async()=>{setLoading(true);conststripe=awaitstripePromise;constcheckoutSession=awaitaxios.post('/api/create-stripe-session',{item:item,});constresult=awaitstripe.redirectToCheckout({sessionId:checkoutSession.data.id,});if(result.error){alert(result.error.message);}setLoading(false);};return(<divclassName={styles.container}><Head><title>Stripe Checkout with Next.js</title><metaname='description'content='Complete Step By Step Tutorial for integrating Stripe Checkout with Next.js'/><linkrel='icon'href='/favicon.ico'/></Head><main>{status&&status==='success'&&(<divclassName='bg-green-100 text-green-700 p-2 rounded border mb-2 border-green-700'>            Payment Successful</div>)}{status&&status==='cancel'&&(<divclassName='bg-red-100 text-red-700 p-2 rounded border mb-2 border-red-700'>            Payment Unsuccessful</div>)}<divclassName='shadow-lg border rounded p-2 '><Imagesrc={item.image}width={300}height={150}alt={item.name}/><h2className='text-2xl'>${item.price}</h2><h3className='text-xl'>{item.name}</h3><pclassName='text-gray-500'>{item.description}</p><pclassName='text-sm text-gray-600 mt-1'>Quantity:</p><divclassName='border rounded'><buttononClick={onQuantityMinus}className='bg-blue-500 py-2 px-4 text-white rounded hover:bg-blue-600'>              -</button><inputtype='number'className='p-2'onChange={onInputChange}value={item.quantity}/><buttononClick={onQuantityPlus}className='bg-blue-500 py-2 px-4 text-white rounded hover:bg-blue-600'>              +</button></div><p>Total: ${item.quantity*item.price}</p><buttondisabled={item.quantity===0||loading}onClick={createCheckOutSession}className='bg-blue-500 hover:bg-blue-600 text-white block w-full py-2 rounded mt-2 disabled:cursor-not-allowed disabled:bg-blue-100'>{loading?'Processing...':'Buy'}</button></div></main></div>);}
Enter fullscreen modeExit fullscreen mode

Andpages/api/create-stripe-sessoin.js should look like this.

conststripe=require('stripe')(process.env.STRIPE_SECRET_KEY);

asyncfunctionCreateStripeSession(req,res){
const{item}=req.body;

constredirectURL=
process.env.NODE_ENV==='development'
?'http://localhost:3000'
:'https://stripe-checkout-next-js-demo.vercel.app';

consttransformedItem={
price_data:{
currency:'usd',
product_data:{
images:[item.image],
name:item.name,
},
unit_amount:item.price*100,
},
description:item.description,
quantity:item.quantity,
};

constsession=awaitstripe.checkout.sessions.create({
payment_method_types:['card'],
line_items:[transformedItem],
mode:'payment',
success_url:redirectURL+'?status=success',
cancel_url:redirectURL+'?status=cancel',
metadata:{
images:item.image,
},
});

res.json({id:session.id});
}

exportdefaultCreateStripeSession;

Enter fullscreen modeExit fullscreen mode




Conclusion

So, we have came to end. Hope you like this article. Please consider giving feedback on my writing.

Important Links

Credits

Connect with me:

Top comments(2)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss
CollapseExpand
 
developerridoy profile image
Ridoy (mern stack)
  • Joined

you didn't add webhook to actually handle the order

CollapseExpand
 
creative555_dev profile image
Creative
  • Joined

This article is very helpfull.
Thank you.

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Community for Builders

ByteSlash is where Designers & Developers build together 🚀. Join the community for builders now:

More fromByteSlash

DEV Community

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

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp