Stripeオーソリ機能を使ったお試し商品申し込みシステムの実装
はじめに
高額商品(28万円)のお試し申し込みシステムを構築する際に、Stripeのオーソリ(与信枠確保)機能を活用した実装を行いました。この記事では、お試し商品の申し込みから与信枠確保、手動決済までの一連の流れを実装した経験をまとめます。
システム概要
要件
- 高額商品(¥280,000)のお試し申し込み
- 与信枠確保による決済リスクの軽減
- お試し期間終了後の手動決済対応
- 顧客情報の管理とメール通知
技術スタック
- フロントエンド: HTML, CSS, JavaScript, Stripe Elements
- バックエンド: PHP
- 決済: Stripe API
実装のポイント
1. Stripeオーソリ機能の活用
// create-payment-intent.php
$paymentIntent = $stripe->paymentIntents->create([
'amount' => 308000, // 税込金額
'currency' => 'jpy',
'capture_method' => 'manual', // 与信のみ(手動決済)
'payment_method_types' => ['card'],
'customer' => $customer->id,
'setup_future_usage' => 'off_session',
'description' => 'お試し商品 - 与信枠確保',
'metadata' => [
'trial_product' => 'true',
'customer_name' => $customerData['name'],
'customer_email' => $customerData['email'],
// ... その他のメタデータ
],
]);
ポイント:
-
capture_method: 'manual'で与信枠のみ確保 -
setup_future_usage: 'off_session'で支払い方法を保存 - メタデータで顧客情報を管理
2. フロントエンドでの決済処理
// カード情報の確認とオーソリ
const { error: stripeError, paymentIntent } = await stripe.confirmCardPayment(client_secret, {
payment_method: {
card: cardElement,
billing_details: {
name: customerData.name,
email: customerData.email,
},
}
});
if (paymentIntent.status === 'requires_capture') {
// 与信枠確保成功
console.log('与信枠確保完了:', paymentIntent);
}
ポイント:
-
confirmCardPaymentでオーソリを実行 -
requires_captureステータスで与信枠確保を確認 - エラーハンドリングで顧客データのクリーンアップ
3. 住所自動入力機能
// 郵便番号API連携
const response = await fetch(`https://zipcloud.ibsnet.co.jp/api/search?zipcode=${postalCode}`);
const data = await response.json();
if (data.status === 200 && data.results && data.results.length > 0) {
const result = data.results[0];
const address = `${result.address1}${result.address2}${result.address3}`;
addressInput.value = address;
}
ポイント:
- 郵便番号API(zipcloud)を活用
- 7桁入力で自動入力ボタンを有効化
- エラーハンドリングで手動入力にフォールバック
4. American Express除外機能
今回の要件は、与信確保期間を日本国内での最大30日間に対応させるため、Amexの場合は手続きが進めないようにしました。
// カードブランドの検出と除外
cardElement.on('change', function(event) {
if (event.brand === 'amex') {
displayError.textContent = 'American Express カードはご利用いただけません。';
submitBtn.disabled = true;
return;
}
// 通常のエラー処理...
});
ポイント:
- Stripe Elementsの
changeイベントでブランド検出 - Amex検出時にフォーム送信を無効化
- ユーザーに分かりやすいエラーメッセージを表示
今回のポイント
1. API Key管理
近年の推奨方針に従い、public_html 配下にはキー情報を保存せず、設定ファイル(例:config/stripe_key.php)で定義しています。
// config/stripe_key.php
define('STRIPE_SECRET_KEY', 'sk_test_...');
define('STRIPE_PUBLISHABLE_KEY', 'pk_test_...');
2. 決済失敗時の顧客データクリーンアップ
顧客を作成してから、決済を実行する必要があるため、決済が失敗した場合にどうしても顧客が貯まりやすい状態になります。そのため、決済が失敗した場合に当該顧客を削除する処理を追加しました。
// 決済失敗時に顧客を削除
if (customer_id) {
try {
await fetch('./delete-customer.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ customer_id: customer_id })
});
console.log('Customer deleted due to payment failure:', customer_id);
} catch (deleteError) {
console.warn('Failed to delete customer:', deleteError);
}
}
手動決済の流れ
- Stripe Dashboardにログイン
- **「支払い」→「Payment Intents」**を選択
- 該当のPaymentIntentを検索
- 「Capture」ボタンをクリックして決済完了
テスト用カード情報
- カード番号: 4242 4242 4242 4242
- 有効期限: 12/34
- CVC: 123
学んだこと
1. Stripeオーソリ機能の活用
- 高額商品のリスク軽減に有効
- 手動決済による柔軟な対応が可能
2. ユーザー体験の向上
- 住所自動入力で入力負荷を軽減
- リアルタイムなエラーフィードバック
3. エラーハンドリングの重要性
- 決済失敗時のデータクリーンアップ
- ユーザーに分かりやすいエラーメッセージ
まとめ
Stripeのオーソリ機能を活用することで、高額商品のお試し申し込みシステムを安全に構築できました。与信枠確保により決済リスクを軽減し、手動決済で柔軟な対応が可能になりました。
また、住所自動入力やAmerican Express除外など、ユーザー体験を向上させる機能も実装し、包括的なエラーハンドリングで安定したシステムを構築できました。
参考リンク
この実装を通じて、決済システムの構築におけるベストプラクティスを学ぶことができました。同じような要件がある方の参考になれば幸いです。