ANTIGRAVITY LABEN
記事一覧/連携・プラグイン
連携・プラグイン/2026-03-10中級

Stripe × Antigravity 決済実装ガイド — AI アシストで課金機能を構築する

Antigravity の AI エージェントを活用して Stripe 決済機能を効率的に実装する方法を、コード例付きで解説します。

Stripe14決済課金2SaaS10実装2

SaaS プロダクト、EC サイト、サブスクリプションサービス — ビジネスが成長するほど、決済機能の実装精度が重要になります。しかし Stripe の API は複雑で、セキュリティ上の落とし穴も多いです。

Antigravity の AI エージェントを活用することで、Stripe の複雑さを大幅に軽減できます。API リファレンスの自動参照、ウェブフック処理の自動生成、エラーハンドリングの自動実装など、AI が面倒な部分をカバーします。

Stripe の基本概念

決済フロー全体の理解

Stripe を使った決済システムは、以下のコンポーネントから構成されます:

  1. Customer — 顧客情報(メール、カード情報など)
  2. Payment Method — 支払い方法(クレジットカード、デジタルウォレット)
  3. Checkout Session — 購入セッション(商品、金額、メタデータ)
  4. Subscription — 定期課金(請求周期、キャンセル方法)
  5. Invoice — 請求書(支払い履歴、請求日)
  6. Webhook — イベント通知(成功、失敗、キャンセルなど)

Stripe のコア概念図

顧客がプロダクトを選択
    ↓
Checkout Session 作成
    ↓
Stripe Checkout ページへリダイレクト
    ↓
支払い方法を入力
    ↓
Stripe がカード情報を処理(PCI コンプライアンス)
    ↓
Payment Intent 成功
    ↓
Webhook: payment_intent.succeeded
    ↓
サーバー: 購入を確定、メール送信、アクセス付与

Antigravity での実装環境構築

ステップ 1: Stripe API キーの設定

# プロジェクトルートの .env.local に追加
STRIPE_PUBLISHABLE_KEY=pk_test_xxxxxxxxxxxxx
STRIPE_SECRET_KEY=sk_test_xxxxxxxxxxxxx
STRIPE_WEBHOOK_SECRET=whsec_xxxxxxxxxxxxx

Antigravity 上での設定ファイル:

# .antigravity/integrations/stripe.yml
stripe:
  enabled: true
  environment: "test"  # test または production
 
  # API キーは環境変数から自動読み込み
  api_keys:
    publishable: "${STRIPE_PUBLISHABLE_KEY}"
    secret: "${STRIPE_SECRET_KEY}"
    webhook: "${STRIPE_WEBHOOK_SECRET}"
 
  # AI エージェントが参照するドキュメント
  docs:
    api_reference: "https://stripe.com/docs/api"
    libraries:
      nodejs: "https://github.com/stripe/stripe-node"
      python: "https://github.com/stripe/stripe-python"
 
  # テスト用のテストカード情報
  test_data:
    success_card: "4242 4242 4242 4242"
    failure_card: "4000 0000 0000 0002"
    expired_card: "4000 0000 0000 0069"

ステップ 2: Stripe AI エージェントの初期化

# Stripe 統合用のカスタムエージェントを作成
antigravity agents create stripe-agent \
  --template stripe-integration \
  --language typescript \
  --framework nextjs

生成されたエージェント構造:

agents/stripe-agent/
├── skills.sh                    # Stripe 関連スキル
├── payment-methods.ts           # 支払い方法の処理
├── subscriptions.ts             # サブスクリプション管理
├── webhooks.ts                  # ウェブフック処理
├── customer-portal.ts           # 顧客ポータル
└── testing.ts                   # テストユーティリティ

実装パターン

パターン 1: ワンタイム支払い(Checkout Sessions)

最もシンプルな実装パターンです。

// api/checkout.ts
import Stripe from 'stripe';
 
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
 
export async function createCheckoutSession(
  userId: string,
  productId: string,
  quantity: number
) {
  // 商品情報を取得
  const product = await getProductFromDatabase(productId);
 
  // Checkout Session を作成
  const session = await stripe.checkout.sessions.create({
    // 支払い方法
    payment_method_types: ['card'],
 
    // 商品情報
    line_items: [
      {
        price_data: {
          currency: 'jpy',
          product_data: {
            name: product.name,
            images: [product.image_url],
            description: product.description
          },
          unit_amount: Math.round(product.price * 100) // 円をセント単位に
        },
        quantity: quantity
      }
    ],
 
    // メタデータ(データベース連携用)
    metadata: {
      userId: userId,
      productId: productId
    },
 
    // URLs
    success_url: `${process.env.DOMAIN}/success?session_id={CHECKOUT_SESSION_ID}`,
    cancel_url: `${process.env.DOMAIN}/cancel`,
 
    // メール
    customer_email: (await getUserEmail(userId)),
 
    // 支払い後の動作
    mode: 'payment',
    payment_intent_data: {
      setup_future_usage: 'off_session'  // 将来の支払いに備える
    }
  });
 
  return session;
}

Antigravity での使用:

ユーザー: "Checkout Session を作成するコードを生成して"

Antigravity AI:
1. Stripe API リファレンスを参照
2. TypeScript 用 stripe-node ライブラリの最新署名を確認
3. 上記のコードを自動生成
4. エラーハンドリングを追加
5. テストコードを自動生成

パターン 2: サブスクリプション実装

定期課金はより複雑です。Antigravity が大きな価値を発揮します。

// api/subscriptions/create.ts
import Stripe from 'stripe';
 
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
 
export async function createSubscription(
  userId: string,
  priceId: string,  // 定期課金商品の ID
  paymentMethodId: string
) {
  // 既存の顧客を確認、なければ作成
  let customer = await stripe.customers.list({
    email: (await getUserEmail(userId)),
    limit: 1
  });
 
  let customerId: string;
 
  if (customer.data.length > 0) {
    customerId = customer.data[0].id;
  } else {
    const newCustomer = await stripe.customers.create({
      email: (await getUserEmail(userId)),
      metadata: { userId: userId }
    });
    customerId = newCustomer.id;
  }
 
  // 支払い方法をアタッチ
  await stripe.paymentMethods.attach(paymentMethodId, {
    customer: customerId
  });
 
  // デフォルト支払い方法を設定
  await stripe.customers.update(customerId, {
    invoice_settings: {
      default_payment_method: paymentMethodId
    }
  });
 
  // サブスクリプションを作成
  const subscription = await stripe.subscriptions.create({
    customer: customerId,
    items: [{ price: priceId }],
 
    // 設定
    payment_settings: {
      save_default_payment_method: 'on_subscription'
    },
 
    // メタデータ
    metadata: {
      userId: userId
    },
 
    // 試用期間(オプション)
    trial_period_days: 14,
 
    // キャンセル時の動作
    cancel_at_period_end: false
  });
 
  // データベースに保存
  await saveSubscriptionToDatabase({
    userId,
    stripeSubscriptionId: subscription.id,
    status: subscription.status
  });
 
  return subscription;
}

キャンセル処理:

// api/subscriptions/cancel.ts
export async function cancelSubscription(
  userId: string,
  subscriptionId: string
) {
  // 権限確認
  const subscription = await stripe.subscriptions.retrieve(subscriptionId);
  if (subscription.metadata?.userId !== userId) {
    throw new Error('Unauthorized');
  }
 
  // キャンセル
  const cancelled = await stripe.subscriptions.update(
    subscriptionId,
    {
      cancel_at_period_end: true  // 現在の請求期間終了時にキャンセル
    }
  );
 
  // ユーザーに通知
  await sendCancellationEmail(userId, cancelled.current_period_end);
 
  return cancelled;
}

パターン 3: ウェブフック処理

ウェブフック処理は Antigravity の AI が特に力を発揮する領域です。

// api/webhooks/stripe.ts
import { NextRequest, NextResponse } from 'next/server';
import Stripe from 'stripe';
 
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET;
 
// Stripe イベント型を定義
interface StripeEvent extends Stripe.Event {
  type:
    | 'payment_intent.succeeded'
    | 'payment_intent.payment_failed'
    | 'customer.subscription.created'
    | 'customer.subscription.deleted'
    | 'customer.subscription.updated'
    | 'invoice.payment_succeeded'
    | 'invoice.payment_failed';
}
 
// ウェブフックハンドラーマップ
const eventHandlers: Record<
  string,
  (event: Stripe.Event) => Promise<void>
> = {
  'payment_intent.succeeded': handlePaymentIntentSucceeded,
  'payment_intent.payment_failed': handlePaymentIntentFailed,
  'customer.subscription.created': handleSubscriptionCreated,
  'customer.subscription.deleted': handleSubscriptionDeleted,
  'customer.subscription.updated': handleSubscriptionUpdated,
  'invoice.payment_succeeded': handleInvoicePaymentSucceeded,
  'invoice.payment_failed': handleInvoicePaymentFailed
};
 
export async function POST(request: NextRequest) {
  const body = await request.text();
  const signature = request.headers.get('stripe-signature');
 
  let event: Stripe.Event;
 
  try {
    // Stripe 署名を検証
    event = stripe.webhooks.constructEvent(
      body,
      signature,
      webhookSecret
    );
  } catch (error) {
    console.error('⚠️  Webhook signature verification failed', error);
    return NextResponse.json(
      { error: 'Invalid signature' },
      { status: 400 }
    );
  }
 
  // イベントハンドラーを実行
  const handler = eventHandlers[event.type];
  if (!handler) {
    console.warn(`Unhandled event type: ${event.type}`);
    return NextResponse.json({ received: true });
  }
 
  try {
    await handler(event);
  } catch (error) {
    console.error(`Error handling ${event.type}:`, error);
    // エラーログは保存するが、200 OK を返す(Stripe は再試行しない)
    // または、デッドレターキューに入れる
  }
 
  return NextResponse.json({ received: true });
}
 
async function handlePaymentIntentSucceeded(event: Stripe.Event) {
  const paymentIntent = event.data.object as Stripe.PaymentIntent;
 
  // 購入を確定
  const userId = paymentIntent.metadata?.userId;
  await confirmPurchase(userId, paymentIntent.id);
 
  // メール送信
  const user = await getUserById(userId);
  await sendOrderConfirmationEmail(user.email, paymentIntent);
 
  // アクセス権を付与
  if (paymentIntent.metadata?.productId) {
    await grantProductAccess(userId, paymentIntent.metadata.productId);
  }
}
 
async function handlePaymentIntentFailed(event: Stripe.Event) {
  const paymentIntent = event.data.object as Stripe.PaymentIntent;
  const userId = paymentIntent.metadata?.userId;
 
  // 支払い失敗をログ
  await logPaymentFailure(userId, paymentIntent);
 
  // ユーザーに通知
  const user = await getUserById(userId);
  await sendPaymentFailureEmail(
    user.email,
    paymentIntent.last_payment_error?.message
  );
}
 
async function handleSubscriptionCreated(event: Stripe.Event) {
  const subscription = event.data.object as Stripe.Subscription;
  const userId = subscription.metadata?.userId;
 
  // サブスクリプションをデータベースに保存
  await saveSubscriptionToDatabase({
    userId,
    stripeSubscriptionId: subscription.id,
    status: subscription.status,
    currentPeriodStart: new Date(subscription.current_period_start * 1000),
    currentPeriodEnd: new Date(subscription.current_period_end * 1000)
  });
 
  // アクセス権を付与
  const priceId = (subscription.items.data[0].price.id);
  const planName = await getPlanNameByPriceId(priceId);
  await grantSubscriptionAccess(userId, planName);
}
 
async function handleSubscriptionDeleted(event: Stripe.Event) {
  const subscription = event.data.object as Stripe.Subscription;
  const userId = subscription.metadata?.userId;
 
  // サブスクリプションをキャンセル
  await cancelUserSubscription(userId);
 
  // アクセス権を削除
  await revokeSubscriptionAccess(userId);
 
  // メール送信
  const user = await getUserById(userId);
  await sendSubscriptionCancelledEmail(user.email);
}

パターン 4: 顧客ポータル

Stripe Customer Portal は、顧客が自分で支払い方法やサブスクリプションを管理できるホストされたページです。

// api/customer-portal.ts
export async function createCustomerPortalSession(userId: string) {
  const user = await getUserById(userId);
 
  // Stripe 顧客 ID を取得
  const customers = await stripe.customers.list({
    email: user.email,
    limit: 1
  });
 
  if (customers.data.length === 0) {
    throw new Error('Customer not found in Stripe');
  }
 
  const customerId = customers.data[0].id;
 
  // ポータルセッションを作成
  const portalSession = await stripe.billingPortal.sessions.create({
    customer: customerId,
    return_url: `${process.env.DOMAIN}/account/billing`,
 
    // 利用可能な機能を制限(オプション)
    configuration: process.env.STRIPE_PORTAL_CONFIG_ID
  });
 
  return portalSession.url;
}

Stripe Dashboard で Porter Configuration を作成し、以下を設定:

  • インボイス履歴の表示
  • 支払い方法の管理
  • サブスクリプション管理(キャンセル、プランの変更など)

Stripe CLI を使ったローカル開発

# Stripe CLI をインストール
brew install stripe/stripe-cli/stripe
 
# API キーでログイン
stripe login
 
# ウェブフックをシミュレート
stripe listen --forward-to localhost:3000/api/webhooks/stripe
 
# テストイベントを送信
stripe trigger payment_intent.succeeded
stripe trigger customer.subscription.created

Antigravity での自動テスト生成:

ユーザー: "Stripe CLI を使ったウェブフックテストを生成して"

Antigravity AI:
1. Stripe CLI のドキュメントを参照
2. 全ウェブフックイベントのテストケースを生成
3. テスト用のモックデータを作成
4. Jest テストスイートを自動生成

生成されるテスト例:

// api/webhooks/__tests__/stripe.test.ts
describe('Stripe Webhooks', () => {
  it('handles payment_intent.succeeded', async () => {
    const event = {
      id: 'evt_test_123',
      type: 'payment_intent.succeeded',
      data: {
        object: {
          id: 'pi_test_123',
          amount: 5000,
          metadata: { userId: '123' }
        }
      }
    };
 
    const response = await POST(
      createMockRequest('stripe', event)
    );
 
    expect(response.status).toBe(200);
    // 購入が確定されたことを確認
    const purchase = await getPurchase('123', 'pi_test_123');
    expect(purchase.status).toBe('confirmed');
  });
});

セキュリティベストプラクティス

絶対に避けるべきこと

// ❌ カード情報をサーバーで処理
export async function processPayment(cardDetails) {
  // サーバーは絶対にカード情報を見てはいけない
  const response = await stripe.charges.create({
    amount: 5000,
    currency: 'jpy',
    card: cardDetails  // 危険!PCI 違反
  });
}
 
// ✅ Stripe.js でトークン化
// クライアントサイドで実行
const { token } = await stripe.createToken(cardElement);
 
// サーバーはトークンのみ処理
export async function processPayment(token) {
  const charge = await stripe.charges.create({
    amount: 5000,
    currency: 'jpy',
    source: token  // 安全
  });
}

セキュリティチェックリスト

security_checklist:
  - ✅ Stripe API キーを環境変数に(ハードコード禁止)
  - ✅ クライアントサイドでは Publishable Key のみ使用
  - ✅ サーバーサイドでは Secret Key のみ使用
  - ✅ ウェブフック署名を必ず検証
  - ✅ HTTPS を必須化
  - ✅ PCI コンプライアンスの確認
  - ✅ Webhook イベントは冪等に処理(重複実行に対応)
  - ✅ エラーメッセージで詳細情報を露出させない
  - ✅ Rate Limiting を実装(ブルートフォース対策)
  - ✅ ログに機密情報を記録しない

トラブルシューティング

よくあるエラーと対応

エラー: "No such customer"

原因: Stripe 顧客が存在しない
対策: stripe.customers.create() で新規作成

エラー: "Webhook signature verification failed"

原因: 環境変数 STRIPE_WEBHOOK_SECRET が間違っている
対策: Dashboard から正しい値をコピー

エラー: "Your card was declined"

原因: テストカード情報が間違っているか、Stripe の要件を満たしていない
対策: テスト用カード(4242...)を使用、または 3D Secure で認証

全体を振り返って

Antigravity を活用することで、Stripe 決済実装は以下のように効率化されます:

  • 実装時間 60-70% 削減 — API リファレンス自動参照、コード自動生成
  • セキュリティ向上 — ベストプラクティスの自動適用
  • テスト完全自動化 — テストケース生成、CI/CD 統合
  • トラブルシューティング高速化 — エラーの原因を即座に特定

Stripe + Antigravity の組み合わせで、安全で信頼性の高い決済システムを、スピーディーに構築できます。今すぐプロジェクトに組み込みましょう。

シェア

お読みいただきありがとうございます

Antigravity Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

Agents & Manager2026-05-03
Antigravity Agents × Stripeで自動化SaaSを月額課金化する実装ガイド — 2026年版
Antigravityのエージェント機能・Stripe・Cloudflare Workersを組み合わせて自動化SaaSを月額課金化する完全実装ガイドです。タスクキューイング・並列実行制御・Webhook・KVアクセス制御まで本番で動く形で解説します。
Agents & Manager2026-05-05
AgentKit 2.0 でサブスク型AIエージェントサービスを作る — Stripe課金から月次収益設計まで
AgentKit 2.0を使ったサブスクリプション型AIエージェントサービスの構築方法を完全解説。Stripe課金統合・マルチエージェント設計・プライシング戦略・解約防止まで、月次収益を安定させる実装ガイドです。
Agents & Manager2026-04-26
Antigravity マルチエージェントで継続課金 SaaS を作る — エージェント分担と購読収益の実装パターン
Antigravity のマルチエージェントを継続課金 SaaS の中核に据えるための実装と運用パターン。役割分担・タスクキュー・Stripe サブスク連携・コスト制御まで、動くコードと判断軸を体系的にまとめました。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →