Stripe is a popular payment processing platform that provides APIs for handling payments, subscriptions, and more. In this tutorial, we will walk through the process of integrating Stripe into a Next.js application. We'll cover setting up your Stripe account, creating a basic checkout page, and handling webhooks to update subscription statuses.
Before you begin, ensure you have the following:
First, we need to install the necessary packages for integrating Stripe into our Next.js application. Run the following command in your project directory:
npm install @stripe/stripe-js @stripe/react-stripe-js stripe
These packages provide the tools needed to interact with Stripe's APIs and handle payments.
Create a file named stripe.js in your project's root directory. This file will be used to initialize the Stripe client:
// stripe.js
import Stripe from 'stripe';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY, {
apiVersion: '2020-08-27',
});
export default stripe;
Make sure to add your STRIPE_SECRET_KEY to your environment variables. You can find this key in your Stripe dashboard under Developers > API keys.
Next, we'll create a checkout page where users can enter their payment information and complete the purchase. Create a new file named checkout.js inside the pages directory:
// pages/checkout.js
import { loadStripe } from '@stripe/stripe-js';
import { Elements } from '@stripe/react-stripe-js';
import CheckoutForm from '../components/CheckoutForm';
const stripePromise = loadStripe(process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY);
export default function Checkout() {
return (
<Elements stripe={stripePromise}>
<CheckoutForm />
</Elements>
);
}
Here, we're using the loadStripe function to initialize Stripe with your publishable key. The Elements component wraps our form and provides the necessary context for Stripe components.
Create a new file named CheckoutForm.js inside the components directory:
// components/CheckoutForm.js
import React, { useState } from 'react';
import { CardElement, useStripe, useElements } from '@stripe/react-stripe-js';
export default function CheckoutForm() {
const stripe = useStripe();
const elements = useElements();
const [error, setError] = useState(null);
const [success, setSuccess] = useState(false);
const handleSubmit = async (event) => {
event.preventDefault();
if (!stripe || !elements) {
// Stripe.js has not loaded yet. Make sure to disable form submission until Stripe.js has loaded.
return;
}
const cardElement = elements.getElement(CardElement);
const { error, paymentMethod } = await stripe.createPaymentMethod({
type: 'card',
card: cardElement,
});
if (error) {
setError(error.message);
} else {
setSuccess(true);
}
};
return (
<form onSubmit={handleSubmit}>
<CardElement />
{error && <div>{error}</div>}
{success && <div>Payment successful!</div>}
<button type="submit" disabled={!stripe}>
Pay
</button>
</form>
);
}
In this component, we use the useStripe and useElements hooks to interact with Stripe. The handleSubmit function creates a payment method using the card information provided by the user.
Webhooks are essential for handling events like successful payments or subscription changes. First, set up a webhook endpoint in your Next.js application:
// pages/api/webhook.js
export default async (req, res) => {
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
let event;
try {
event = stripe.webhooks.constructEvent(
req.body,
req.headers['stripe-signature'],
process.env.STRIPE_WEBHOOK_SECRET
);
} catch (err) {
return res.status(400).send(`Webhook Error: ${err.message}`);
}
// Handle the event
switch (event.type) {
case 'payment_intent.succeeded':
const paymentIntent = event.data.object;
console.log('PaymentIntent was successful!');
break;
case 'payment_intent.payment_failed':
const failedPaymentIntent = event.data.object;
console.log('PaymentIntent was unsuccessful.');
break;
// ... handle other event types
default:
console.log(`Unhandled event type ${event.type}`);
}
res.json({ received: true });
};
Make sure to add your STRIPE_WEBHOOK_SECRET to your environment variables. You can find this secret in your Stripe dashboard under Developers > Webhooks.
Before going live, test your integration thoroughly using Stripe's test mode. Use the following test card numbers:
These cards will help you simulate different payment scenarios.
By following this guide, you have successfully integrated Stripe into your Next.js application. You can now handle payments securely and efficiently. Remember to regularly update your dependencies and stay informed about any changes in the Stripe API or best practices for payment processing.