Skip to content

3Dセキュアとは

3Dセキュア(3D Secure)は、オンライン決済における追加認証プロトコルです。クレジットカード決済時に、カード発行銀行による追加認証を行うことで、不正利用を防ぎます。

🎯 なぜ3Dセキュアが重要なのか

Section titled “🎯 なぜ3Dセキュアが重要なのか”

💡 実際の事例:

2020年、あるECサイトで3Dセキュアを導入していませんでした:

  • 🔥 問題: クレジットカードの不正利用が多発
  • 🔥 結果: 約1000件の不正取引が発生し、約5000万円の損害
  • 💸 影響:
    • チャージバック(返金)の発生
    • サービスの信頼失墜
    • 3Dセキュアの導入に約1000万円のコスト

教訓:

  • 3Dセキュアは、オンライン決済のセキュリティを向上させる
  • チャージバックのリスクを軽減できる
  • ✅ ユーザーと事業者の両方を保護する

基本的な認証フロー:

1. ユーザーが決済を実行
2. 決済代行業者(PSP)が3Dセキュア認証を開始
3. カード発行銀行が認証画面を表示
4. ユーザーが認証情報を入力(パスワード、SMS認証など)
5. カード発行銀行が認証結果を返す
6. 認証成功の場合、決済を実行

実装例:

// Stripeでの3Dセキュア認証の実装
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
class ThreeDSecurePayment {
async createPaymentIntent(amount, currency, paymentMethodId) {
// PaymentIntentを作成(3Dセキュア認証を有効化)
const paymentIntent = await stripe.paymentIntents.create({
amount: amount * 100, // 金額をセント単位に変換
currency: currency.toLowerCase(),
payment_method: paymentMethodId,
confirmation_method: 'manual',
confirm: true,
return_url: 'https://example.com/payment/return',
// 3Dセキュア認証を必須にする
payment_method_options: {
card: {
request_three_d_secure: 'automatic', // 自動的に3Dセキュア認証を要求
},
},
});
// 3Dセキュア認証が必要な場合
if (paymentIntent.status === 'requires_action' &&
paymentIntent.next_action.type === 'use_stripe_sdk') {
// クライアント側で3Dセキュア認証を実行
return {
requiresAction: true,
clientSecret: paymentIntent.client_secret,
nextAction: paymentIntent.next_action,
};
}
// 認証が不要な場合、または認証済みの場合
if (paymentIntent.status === 'succeeded') {
return {
success: true,
paymentIntentId: paymentIntent.id,
};
}
return {
success: false,
status: paymentIntent.status,
};
}
async confirmPayment(clientSecret) {
// 3Dセキュア認証後の確認
const paymentIntent = await stripe.paymentIntents.retrieve(
clientSecret.split('_secret_')[0]
);
if (paymentIntent.status === 'succeeded') {
return {
success: true,
paymentIntentId: paymentIntent.id,
};
}
return {
success: false,
status: paymentIntent.status,
};
}
}

Reactでの3Dセキュア認証:

// Reactでの3Dセキュア認証の実装
import { loadStripe } from '@stripe/stripe-js';
import {
Elements,
CardElement,
useStripe,
useElements,
} from '@stripe/react-stripe-js';
const stripePromise = loadStripe(process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY);
function PaymentForm() {
const stripe = useStripe();
const elements = useElements();
const handleSubmit = async (event: React.FormEvent) => {
event.preventDefault();
if (!stripe || !elements) {
return;
}
// カード情報を取得
const cardElement = elements.getElement(CardElement);
// PaymentMethodを作成
const { paymentMethod, error: pmError } = await stripe.createPaymentMethod({
type: 'card',
card: cardElement!,
});
if (pmError) {
console.error(pmError);
return;
}
// PaymentIntentを作成(3Dセキュア認証を含む)
const response = await fetch('/api/create-payment-intent', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
amount: 10000, // 100.00円
currency: 'jpy',
paymentMethodId: paymentMethod.id,
}),
});
const { requiresAction, clientSecret, nextAction } = await response.json();
if (requiresAction) {
// 3Dセキュア認証を実行
const { error: confirmError } = await stripe.confirmCardPayment(
clientSecret,
{
payment_method: {
card: cardElement!,
},
}
);
if (confirmError) {
console.error(confirmError);
return;
}
// 認証成功
alert('決済が完了しました');
} else {
// 認証不要
alert('決済が完了しました');
}
};
return (
<form onSubmit={handleSubmit}>
<CardElement
options={{
style: {
base: {
fontSize: '16px',
color: '#424770',
'::placeholder': {
color: '#aab7c4',
},
},
invalid: {
color: '#9e2146',
},
},
}}
/>
<button type="submit" disabled={!stripe}>
決済する
</button>
</form>
);
}
// Elementsプロバイダーでラップ
function PaymentPage() {
return (
<Elements stripe={stripePromise}>
<PaymentForm />
</Elements>
);
}

📋 特徴:

  • カード発行銀行の独自認証画面
  • パスワード認証が主流
  • ユーザー体験が悪い(別ウィンドウ、リダイレクト)

❌ 問題点:

  • ❌ ユーザー体験が悪い
  • 認証画面のデザインが統一されていない
  • ❌ モバイルでの対応が不十分

📋 特徴:

  • ✅ シームレスな認証体験
  • リスクベース認証(低リスクの場合は認証をスキップ)
  • ✅ モバイルファーストの設計
  • ✅ より多くの認証方法(SMS、生体認証など)

✅ メリット:

  • ✅ ユーザー体験の向上
  • 認証率の向上
  • チャージバックの減少

実装例:

// 3D Secure 2.0の実装
class ThreeDSecure2 {
async authenticate(paymentIntent, cardElement) {
// 3D Secure 2.0の認証を実行
const { error, paymentIntent: updatedPaymentIntent } =
await stripe.confirmCardPayment(paymentIntent.client_secret, {
payment_method: {
card: cardElement,
billing_details: {
name: 'Taro Yamada',
email: 'taro@example.com',
phone: '+81901234567',
address: {
line1: '1-1-1 Shibuya',
city: 'Tokyo',
country: 'JP',
postal_code: '150-0001',
},
},
},
// 3D Secure 2.0の追加情報
return_url: 'https://example.com/payment/return',
});
if (error) {
return {
success: false,
error: error.message,
};
}
return {
success: true,
paymentIntent: updatedPaymentIntent,
};
}
}

✅ 3Dセキュアのベストプラクティス

Section titled “✅ 3Dセキュアのベストプラクティス”

リスクベース認証の実装:

// リスクベース認証の実装
class RiskBasedAuthentication {
async assessRisk(transaction) {
// リスクスコアを計算
let riskScore = 0;
// 取引金額によるリスク
if (transaction.amount > 100000) {
riskScore += 30; // 高額取引はリスクが高い
}
// ユーザーの過去の取引履歴
const userHistory = await this.getUserHistory(transaction.userId);
if (userHistory.transactionCount < 5) {
riskScore += 20; // 新規ユーザーはリスクが高い
}
// デバイス情報
if (!userHistory.knownDevices.includes(transaction.deviceId)) {
riskScore += 25; // 未知のデバイスはリスクが高い
}
// IPアドレスの位置情報
const ipLocation = await this.getIPLocation(transaction.ipAddress);
if (ipLocation.country !== userHistory.commonCountry) {
riskScore += 15; // 異なる国からのアクセスはリスクが高い
}
// リスクスコアに基づいて認証方法を決定
if (riskScore < 30) {
return { require3DS: false, reason: 'low_risk' };
} else if (riskScore < 60) {
return { require3DS: true, method: 'password' };
} else {
return { require3DS: true, method: 'sms' };
}
}
}

ユーザー体験の最適化:

// ユーザー体験の最適化
class UXOptimization {
async optimize3DSFlow(paymentIntent) {
// 1. 認証が必要な場合、事前にユーザーに通知
if (paymentIntent.status === 'requires_action') {
await this.showNotification(
'セキュリティのため、追加認証が必要です。'
);
}
// 2. 認証プロセスの進捗を表示
await this.showProgress('認証中...');
// 3. 認証が完了したら、すぐに結果を表示
if (paymentIntent.status === 'succeeded') {
await this.showSuccess('決済が完了しました');
}
// 4. エラーの場合は、わかりやすいメッセージを表示
if (paymentIntent.status === 'requires_payment_method') {
await this.showError(
'認証に失敗しました。別のカードをお試しください。'
);
}
}
}

3Dセキュアのポイント:

  • 🔒 セキュリティ: オンライン決済のセキュリティを向上
  • チャージバック: チャージバックのリスクを軽減
  • 👤 ユーザー体験: 3D Secure 2.0でユーザー体験を向上
  • ⚖️ リスクベース認証: リスクスコアに基づいて認証方法を決定
  • 最適化: ユーザー体験を最適化し、認証率を向上

適切な3Dセキュアの実装により、セキュリティを確保しながら、優れたユーザー体験を提供できます。