アルアカ - Arcadia Academia

Arcadia Academiaは「エンジニアリングを楽しむ」を合言葉に日本のデジタル競争力を高めることをミッションとするテックコミュニティです。

Next.js × Stripe API を活用したクレジットカード決済システムの構築

Featured image of the post

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アカウントを作成する必要があります。

Image in a image block

サインアップが完了するとサンドボックス環境が表示されるので開発者用のメニューからAPIを選択しAPI キーを確認してください。

また商品追加画面からテスト用の商品も追加しておきましょう。今回は買い切りテストなので支払いは1回限りで作成してください。

Image in a image block

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ボタンをクリックします。

Image in a image block

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

Image in a image block

以下のリンクよりテストカードの情報を入力し「支払う」をクリックしてください。

成功するとsuccessページにリダイレクトします。(successを事前に準備しておく必要があります)

Stripe の顧客管理や取引履歴でも確認できます。

Image in a image block

まとめ

Next.js と Stripe API を組み合わせることで、シンプルかつ強力な決済システムを構築できます。

特に、Next.js の API Routes を活用することで、バックエンドのセットアップなしにサーバーレスで決済処理を実装できるのが大きな魅力です。

✅ 今回のポイント

  • Next.js の API Routes を利用して Stripe の Checkout を実装
  • 環境変数で API キーを安全に管理

これで、Next.js × Stripe のカード決済システムの基礎は完成です!ぜひ自身のプロジェクトで活用してみてください。

あなたを爆速で成長させるメンタリングプログラムはこちらから↓↓

RUNTEQ(ランテック) - 実践型Webエンジニア養成プログラミングスクールの入会