プログラマーじゃないエンジニアがClaudeだけで決済システム付きWebアプリを作りました
はじめに
機械系エンジニアの私が、コードをほぼ書かずにClaudeとの会話だけで振動解析Webアプリ「WaveAxis」を作りました。
前回の記事(無料版開発編):https://zenn.dev/g3o5/articles/bc6bed6b8ab3d4
以前の記事では無料版の開発についてまとめましたが、今回はいよいよStripe決済システムを組み込んでProプランを公開するまでの話をします。
「決済システムなんて難しそう」と思っていましたが、結論から言うとClaudeに聞きながら進めれば、プログラマーじゃなくても実装できます。
素人なのでもちろんスムーズにいきませんが、必要なのは折れない心だと思いました。
WaveAxisとは
ブラウザで動く振動解析Webアプリです。大手メーカーのアプリほど高機能ではないですが、手軽にFFTしたい、フィルタの挙動を確認したい、などのライトユーザーに向けて開発しました。自分が業務で使用しているものをベースにしているので、業務でもお使いいただけます。ある程度細かく設定でき、手軽に解析できるのが最大の特徴です。
- 無料版:合成サイン波、ランダム振動波のFFT解析、フィルタ処理、スペクトログラム表示
- Pro版:実測データのCSV読み込みによる解析(複数チャンネル対応)
Pro版の最大の特徴はデータがブラウザ内で処理されること。CSVファイルが外部サーバーに送信されないので、機密データを扱う産業用途でも安心して使えます。
👉 https://waveaxis-pro.vercel.app
使った技術スタック
| 役割 | 技術 |
|---|---|
| フロントエンド | React / Vite / Vercel |
| バックエンド | Python / FastAPI / Render |
| 認証 | Supabase |
| 決済 | Stripe |
| データベース | Supabase(PostgreSQL) |
すべて無料プランから始められます。
仕組みの全体像
ユーザー
↓ ① ログイン
Supabase(認証・プラン管理)
↓ ② Proプランか確認
WaveAxisアプリ(CSV機能の表示/非表示)
↓ ③ アップグレードボタンを押す
Stripe Checkout(決済ページ)
↓ ④ 決済完了
Stripe Webhook → バックエンド → Supabaseのplanをproに更新
↓ ⑤ 再ログイン
PRO PLANバッジが表示される
ポイントはStripeがお金の処理を全部やってくれること。カード情報は自分のサーバーには一切触れません。
フリーミアム構造の設計
最初はProプランを完全に別アプリとして作ろうとしていましたが、Claudeに相談して同じアプリ内でプランを切り替えるフリーミアム構造に変更しました。
同じURL(waveaxis-pro.vercel.app)
├── 未ログイン・無料ユーザー → CSV機能は鍵アイコンで表示
└── Proユーザー → CSV機能が解放される
この構造のメリットは、ユーザーが無料版を使いながら「実データを入れたい」と思った瞬間にアップグレードを促せること。
苦労したこと
1. Supabaseのライブラリ問題
Supabaseの公式Pythonライブラリ(supabase)をインストールしようとしたら、依存関係でpyicebergというライブラリが必要になり、これのビルドにMicrosoft Visual C++ 14.0以上が必要でインストールできませんでした。
解決策:Supabaseライブラリを使わず、httpxで直接REST APIを叩く方法に切り替えました。結果的にコードがシンプルになってよかったです。
# Supabaseライブラリを使わずにHTTPで直接叩く
async with httpx.AsyncClient() as client:
res = await client.patch(
f"{SUPABASE_URL}/rest/v1/profiles?id=eq.{user_id}",
json={"plan": "pro"},
headers=headers,
)
2. StripeオブジェクトのKeyError
Stripe WebhookでCheckoutセッションのデータを取得しようとしたらKeyError: 'get'エラーが発生。Stripeが返すオブジェクトは通常のPython辞書と違い、.get()メソッドが使えませんでした。
解決策:Stripeオブジェクトを使わず、受信したJSONペイロードを直接パースする方法に切り替えました。
# Stripeオブジェクトではなく生のJSONを使う
payload_dict = json.loads(payload)
session = payload_dict["data"]["object"]
user_id = session.get("metadata", {}).get("user_id")
3. SupabaseのRLS権限エラー
Webhookでプランを更新しようとしたら403 permission deniedエラー。RLS(行レベルセキュリティ)がservice_roleのアクセスも拒否していました。
解決策:SQL Editorで権限を明示的に付与。
grant select, insert, update on public.profiles to service_role;
4. Stripeの日本独自の審査(KYB)
本番環境に切り替えるにはクレジット取引セキュリティ対策措置状況申告書の提出が必要でした。これは日本独自の要件で、セキュリティ対策のチェックリストに答える形式です。難しい質問もあるのでClaudeに各項目の回答を相談しながら進めました。審査は今回1日で通りました。
セキュリティについて
決済システムを組み込むにあたって気になるセキュリティについてまとめます。
カード情報
カード情報はStripeのサーバーで処理されます。自分のサーバーには一切触れないので、PCI DSSへの対応は不要です。
ユーザー認証
Supabaseが担当。パスワードはSupabaseが安全にハッシュ化して管理します。メール認証も自動で対応しています。

こんなメールが自動で送られます。
データベース
RLS(行レベルセキュリティ)を設定しているので、ユーザーは自分のデータしか読めません。
APIキー
.envファイルで管理し、.gitignoreで除外しています。フロントエンドに公開するキーはStripeの公開可能キーとSupabaseのPublishableキーのみです。
CSVデータ
Pro版のCSV読み込みはブラウザ内で完結します。生データは外部サーバーに送信されません。
かかった時間
| 作業 | 時間 |
|---|---|
| Supabase・Stripeの設定 | 約2時間 |
| バックエンドの実装(認証・決済) | 約3時間 |
| フロントエンドの実装(ログイン画面・プラン制御) | 約2時間 |
| デプロイ・環境変数設定 | 約2時間 |
| デバッグ・動作確認 | 約3時間 |
| Stripeの本番審査 | 約1日 |
| 合計(コーディング部分) | 約12時間 |
コーディングの経験がなくても、Claudeに聞きながら進めれば1〜2日で実装できます。
まとめ
プログラマーじゃなくても、Claudeと対話しながら進めることで決済システム付きWebアプリを作ることができました。
決済システムというと難しそうに聞こえますが、StripeとSupabaseを使えばセキュリティも含めてほとんどのことをサービス側が面倒を見てくれます。残るのは「誰がProユーザーか」を管理する仕組みだけで、それもSupabaseのデータベースで簡単に実現できます。
Webアプリを作ってみたいエンジニアの方の参考になれば嬉しいです。
Discussion