Next.js は、React ベースのフレームワークとして、パフォーマンスや SEO に優れた Web アプリケーションを開発できる強力なツールです。一方、Stripe は、世界的に利用されているオンライン決済プラットフォームであり、簡単に決済機能を実装できる API を提供しています。
本記事では、Next.js と Stripe API を組み合わせて、シンプルな決済システムを構築する方法を解説します。
[目次を開く]
1. Next.js と Stripe API を組み合わせるメリット
🚀 Next.js の特徴
- SSR(サーバーサイドレンダリング)対応:SEO が向上し、高速なページ表示が可能
- API Routes の活用:バックエンドの構築が不要で、サーバーレスで処理可能
- 柔軟なデータフェッチ:SSG(静的サイト生成)や ISR(増分的静的再生成)にも対応
💳 Stripe の特徴
- 多様な決済手段に対応:クレジットカード、Apple Pay、Google Pay など
- シンプルな API:数行のコードで決済機能を実装可能
- 高いセキュリティ:PCI DSS に準拠し、安全な決済システムを提供
この 2 つを組み合わせることで、フルスタックな決済システムを短期間で構築できます。
2. Next.js で Stripe を導入する手順
🛠 環境構築
まずは Next.js プロジェクトを作成し、Stripe を導入します。
npx create-next-app@latest my-stripe-app
cd my-stripe-app
npm install stripe
Stripe の API を使用するために、.env.local
に秘密鍵を設定します。
STRIPE_SECRET_KEY=sk_test_XXXXXXXXXXXXXXXXXXXXXXXX
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_YYYYYYYYYYYYYYYYYYYYYYYY
🔹 注意:API キーは必ず環境変数として管理し、公開リポジトリに含めないようにしましょう。
以下のページよりサインアップしStripeアカウントを作成する必要があります。

サインアップが完了するとサンドボックス環境が表示されるので開発者用のメニューからAPIを選択しAPI キーを確認してください。
また商品追加画面からテスト用の商品も追加しておきましょう。今回は買い切りテストなので支払いは1回限りで作成してください。

3. Stripe Checkout を活用した決済フロー
Stripe の Checkout を使うと、簡単に決済フローを構築できます。
📝 API Route の作成
Next.js の app/api/checkout/
内に route.ts
を作成し、サーバーサイドで決済セッションを生成します。
// pages/api/checkout.ts
import { NextApiRequest, NextApiResponse } from "next";
import Stripe from "stripe";
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY as string, {
apiVersion: '2025-02-24.acacia',
});
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method !== "POST") {
return res.status(405).json({ error: "Method Not Allowed" });
}
try {
const session = await stripe.checkout.sessions.create({
payment_method_types: ["card"],
line_items: [
{
price_data: {
currency: "usd",
product_data: {
name: "Sample Product",
},
unit_amount: 1000, // 10 USD
},
quantity: 1,
},
],
mode: "payment",
success_url: `${req.headers.origin}/success`,
cancel_url: `${req.headers.origin}/cancel`,
});
res.status(200).json({ url: session.url });
} catch (err: any) {
res.status(500).json({ error: err.message });
}
}
この API は、Checkout セッションを作成し、ユーザーを Stripe の決済ページにリダイレクトする URL を返します。
api/products/route.ts
に商品を取得するAPIを作成しましょう。
// api/products/router.ts
import { NextRequest, NextResponse } from "next/server";
import Stripe from "stripe";
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY as string, {
apiVersion: '2025-02-24.acacia',
});
export async function GET(req: NextRequest) {
try {
const products = await stripe.products.list({
expand: ["data.default_price"],
});
return NextResponse.json(products.data);
} catch (err: any) {
console.error("API Error:", err);
return NextResponse.json({ error: err.message }, { status: 500 });
}
}
4. フロントエンドで決済処理
次に、フロントエンドで決済ボタンを設置し、API を呼び出して支払いを開始します。
// components/CheckoutButton.tsx
"use client";
import { useState } from "react";
const CheckoutButton = ({ productId }: { productId: string }) => {
const [loading, setLoading] = useState(false);
const handleCheckout = async () => {
setLoading(true);
try {
const res = await fetch("/api/checkout", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ productId }),
});
if (!res.ok) {
const errorData = await res.text();
console.error("Checkout API Error:", errorData);
return;
}
const data = await res.json();
if (data.url) {
window.location.href = data.url;
}
} catch (error) {
console.error("Fetch Error:", error);
}
setLoading(false);
};
return (
<button onClick={handleCheckout} disabled={loading}>
{loading ? "Processing..." : "Checkout"}
</button>
);
};
export default CheckoutButton;
このコンポーネントをページに組み込み、決済フローを完成させます。
// pages/index.tsx
"use client";
import { useEffect, useState } from "react";
import CheckoutButton from "../components/CheckoutButton";
interface Product {
id: string;
name: string;
description?: string;
images?: string[];
default_price?: {
id: string;
unit_amount: number;
};
}
export default function ProductsPage() {
const [products, setProducts] = useState<Product[]>([]);
useEffect(() => {
fetch("/api/products")
.then((res) => res.json())
.then((data) => setProducts(data))
.catch((err) => console.error("Error fetching products:", err));
}, []);
return (
<div>
<h1>Products</h1>
<ul>
{products.map((product) => (
<li key={product.id}>
<h2>{product.name}</h2>
{product.images && product.images.length > 0 && (
<img src={product.images[0]} alt={product.name} width={200} />
)}
<p>{product.description}</p>
<p>Price: \{(product.default_price?.unit_amount || 0)}</p>
<CheckoutButton productId={product.default_price?.id || ""} />
</li>
))}
</ul>
</div>
);
}
以下のような画面が表示されたらCheckoutボタンをクリックします。

問題がなければクレジットカード情報の入力画面に遷移します。

以下のリンクよりテストカードの情報を入力し「支払う」をクリックしてください。
成功するとsuccessページにリダイレクトします。(successを事前に準備しておく必要があります)
Stripe の顧客管理や取引履歴でも確認できます。

まとめ
Next.js と Stripe API を組み合わせることで、シンプルかつ強力な決済システムを構築できます。
特に、Next.js の API Routes を活用することで、バックエンドのセットアップなしにサーバーレスで決済処理を実装できるのが大きな魅力です。
✅ 今回のポイント
- Next.js の API Routes を利用して Stripe の Checkout を実装
- 環境変数で API キーを安全に管理
これで、Next.js × Stripe のカード決済システムの基礎は完成です!ぜひ自身のプロジェクトで活用してみてください。