Use Cases

Stripe Checkout Implementation: Claude Code 활용 가이드

stripe checkout implementation: Claude Code 활용. 실용적인 팁과 코드 예시를 포함합니다.

Stripe Checkout구현をClaude Code로 효율화하기

Stripe Checkoutはホスト타입の決済UIで、PCI DSS準拠の手間を最小限に抑えながら安全な決済を구현할 수 있습니다。Claude Code를 활용하면 複雑な決済フローの구축もスムーズに進められます。

Checkout 세션の생성

> Stripe Checkout세션を생성するAPI를 구현해줘。
> 単品購入とサブスクリプション両方に대응して。
// src/api/checkout.ts
import Stripe from 'stripe';

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
  apiVersion: '2024-12-18.acacia',
});

// 単品購入のCheckout세션
export async function createCheckoutSession(
  priceId: string,
  customerId?: string
) {
  const session = await stripe.checkout.sessions.create({
    mode: 'payment',
    payment_method_types: ['card'],
    customer: customerId,
    line_items: [
      {
        price: priceId,
        quantity: 1,
      },
    ],
    success_url: `${process.env.APP_URL}/success?session_id={CHECKOUT_SESSION_ID}`,
    cancel_url: `${process.env.APP_URL}/cancel`,
    metadata: {
      source: 'web',
    },
  });

  return session;
}

// サブスクリプションのCheckout세션
export async function createSubscriptionSession(
  priceId: string,
  customerId?: string
) {
  const session = await stripe.checkout.sessions.create({
    mode: 'subscription',
    payment_method_types: ['card'],
    customer: customerId,
    line_items: [
      {
        price: priceId,
        quantity: 1,
      },
    ],
    subscription_data: {
      trial_period_days: 14,
      metadata: { plan: 'pro' },
    },
    success_url: `${process.env.APP_URL}/dashboard?session_id={CHECKOUT_SESSION_ID}`,
    cancel_url: `${process.env.APP_URL}/pricing`,
  });

  return session;
}

Webhook処理

> StripeのWebhookを処理する엔드포인트를 구현해줘。
> 署名검증と主要な이벤트ハンドリングをして。
// src/api/webhook.ts
import Stripe from 'stripe';

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET!;

export async function handleWebhook(
  body: string | Buffer,
  signature: string
) {
  let event: Stripe.Event;

  try {
    event = stripe.webhooks.constructEvent(body, signature, webhookSecret);
  } catch (err) {
    throw new Error(`Webhook signature verification failed`);
  }

  switch (event.type) {
    case 'checkout.session.completed': {
      const session = event.data.object as Stripe.Checkout.Session;
      await handleCheckoutComplete(session);
      break;
    }
    case 'invoice.payment_succeeded': {
      const invoice = event.data.object as Stripe.Invoice;
      await handlePaymentSucceeded(invoice);
      break;
    }
    case 'customer.subscription.deleted': {
      const subscription = event.data.object as Stripe.Subscription;
      await handleSubscriptionCanceled(subscription);
      break;
    }
    default:
      console.log(`Unhandled event type: ${event.type}`);
  }

  return { received: true };
}

async function handleCheckoutComplete(session: Stripe.Checkout.Session) {
  const customerId = session.customer as string;
  const customerEmail = session.customer_details?.email;
  // DBに사용자情報を저장、メール전송など
  console.log(`Checkout completed for ${customerEmail}`);
}

async function handlePaymentSucceeded(invoice: Stripe.Invoice) {
  // サブスクリプションの업데이트処理
  console.log(`Payment succeeded: ${invoice.id}`);
}

async function handleSubscriptionCanceled(subscription: Stripe.Subscription) {
  // アクセス権の무효化処理
  console.log(`Subscription canceled: ${subscription.id}`);
}

프론트엔드の구현

> Next.jsで가격表페이지とCheckout버튼を作って。
// app/pricing/page.tsx
'use client';

import { useState } from 'react';

const plans = [
  { name: 'Basic', price: '¥980/月', priceId: 'price_basic_monthly' },
  { name: 'Pro', price: '¥2,980/月', priceId: 'price_pro_monthly' },
  { name: 'Enterprise', price: '¥9,800/月', priceId: 'price_enterprise_monthly' },
];

export default function PricingPage() {
  const [loading, setLoading] = useState<string | null>(null);

  const handleCheckout = async (priceId: string) => {
    setLoading(priceId);
    try {
      const res = await fetch('/api/checkout', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ priceId }),
      });
      const { url } = await res.json();
      window.location.href = url;
    } catch (error) {
      console.error('Checkout error:', error);
    } finally {
      setLoading(null);
    }
  };

  return (
    <div className="grid grid-cols-3 gap-6 max-w-4xl mx-auto p-8">
      {plans.map((plan) => (
        <div key={plan.priceId} className="border rounded-lg p-6 text-center">
          <h3 className="text-xl font-bold">{plan.name}</h3>
          <p className="text-3xl font-bold my-4">{plan.price}</p>
          <button
            onClick={() => handleCheckout(plan.priceId)}
            disabled={loading === plan.priceId}
            className="bg-indigo-600 text-white px-6 py-2 rounded-lg"
          >
            {loading === plan.priceId ? '処理中...' : '購入する'}
          </button>
        </div>
      ))}
    </div>
  );
}

정리

Stripe Checkoutを使えば、安全で高品質な決済体験を빠르게구축할 수 있습니다。Claude Codeを활용すれば、WebhookやサブスクリプションなどのStripe固有の구현パターンも효율적으로進められます。決済통합の基本Webhook구현가이드도 참고하세요.

Stripe의 상세 정보는Stripe공식 문서를 참고하세요.

#Claude Code #Stripe #payments #Checkout #subscription