メインコンテンツへスキップ

3D Secure

銀行発行の二要素認証を追加して不正を70%以上削減し、チャージバックの責任をカード発行者に移転します。

概要

3D Secure(3DS)は、オンラインクレジットカードおよびデビットカード取引の追加セキュリティレイヤーで、カード所有者がカード発行銀行で追加の確認ステップを完了する必要があります。この認証により不正が大幅に削減され、チャージバックの責任が加盟店から銀行に移転されます。

主なメリット:

  • 70%以上の不正削減 - 追加の認証により不正使用を防止
  • 責任移転 - 銀行が認証済み取引のチャージバック責任を負担
  • チャージバック率の低下 - 異議申し立てと関連手数料を削減
  • フリクションレスオプション - 3DS2により低リスク取引の即座承認が可能
  • コンプライアンス要件 - 特定の事業タイプと地域で必須

3D Secure 1 vs 3D Secure 2

機能3DS1(非推奨)3DS2(現在の標準)
ステータス2022年10月に非推奨アクティブで必須
認証方法OTP/SMSのみOTP、SMS、生体認証、顔認識
フリクションレスフロー利用不可低リスク取引で利用可能
モバイルサポート制限ありアプリ内フルサポート
データ共有制限ありリッチな取引コンテキスト(デバイス、場所、履歴)
ユーザーエクスペリエンス常にインタラクションが必要スマートなリスクベース判断
承認率低い高い(フリクションレスがカート放棄を削減)
3DS1の終了

3D Secure 1は2022年10月に非推奨となりました。すべての実装では3D Secure 2(3DS2)を使用する必要があります。

3DS2の仕組み

フリクションレスフロー

  • 銀行がリッチデータ(デバイスID、ジオロケーション、購入履歴)を使用して取引リスクを分析
  • リスクが十分低い場合、顧客のインタラクションなしで即座に取引承認
  • チャレンジフローと同じ責任保護
  • 大幅に優れたUX - リダイレクトなし、より速いチェックアウト

チャレンジフロー

  • 追加の確認が必要な高リスク取引に使用
  • 顧客は銀行の認証ページにリダイレクト
  • 複数の認証オプション:
    • OTP(SMSによるワンタイムパスワード)
    • 生体認証(指紋、Face ID)
    • 銀行アプリのプッシュ通知
  • 通常1〜3分かかります
  • 初回登録の場合は最大10分かかる場合があります

3D Secureを有効にするタイミング

必須の場合

  • 旅行 & 宿泊 - ホテル、航空会社、予約プラットフォーム
  • デジタル商品 - 音楽、映画、ソフトウェア、ゲーム
  • バーチャルアイテム - ゲーム通貨、アプリ内購入
  • プリペイドカード - ギフトカード、チャージサービス
  • 高リスク加盟店 - 不正アナリストによって決定

推奨される場合

  • 高額取引(10,000 THB以上または同等額)
  • チャージバック率が0.3%を超える企業
  • 国際カード取引
  • 初回顧客
  • 疑わしい取引パターン

推奨されない場合

  • 継続課金 - 自動課金を妨げます
  • ワンクリックリピート購入 - 毎回インタラクションが必要
  • 少額取引 - 小額購入でのコンバージョンを低下させる可能性
サブスクリプションの回避策

サブスクリプションの場合: 初回カード設定時に3DSを使用し、その後の支払いには3DSなしで保存済み顧客IDを課金(銀行ルールに従う)。

実装ガイド

ステップ1: アカウントで3DSを有効化

Omiseサポートに連絡して3D Secureを有効にします:

Email: support@omise.co
件名: [アカウント名]のための3D Secureを有効化

ステップ2: トークンを作成(標準プロセス)

// クライアントサイド: 通常通りトークンを作成
Omise.setPublicKey("pkey_test_YOUR_KEY");

Omise.createToken("card", {
name: "John Doe",
number: "4242424242424242",
expiration_month: 12,
expiration_year: 2027,
security_code: "123"
}, function(statusCode, response) {
if (statusCode === 200) {
// サーバーにトークンを送信
submitToServer(response.id);
}
});

ステップ3: return_uriを含むチャージを作成

return_uriパラメータは3DSに必須です:

curl https://api.omise.co/charges \
-u skey_test_YOUR_SECRET_KEY: \
-d "amount=100000" \
-d "currency=THB" \
-d "card=tokn_test_..." \
-d "return_uri=https://yourdomain.com/payment/callback"

ステップ4: 顧客のリダイレクトを処理

レスポンスにauthorize_uriが存在する場合、顧客をリダイレクト:

// サーバーサイド
app.post('/create-charge', async (req, res) => {
const charge = await omise.charges.create({
amount: req.body.amount,
currency: 'THB',
card: req.body.token,
return_uri: 'https://yourdomain.com/payment/callback',
metadata: {
order_id: req.body.order_id
}
});

if (charge.authorize_uri) {
// 3DS認証が必要
res.json({
requires_3ds: true,
authorize_uri: charge.authorize_uri,
charge_id: charge.id
});
} else {
// フリクションレス - チャージ完了
res.json({
requires_3ds: false,
status: charge.status,
charge_id: charge.id
});
}
});
// クライアントサイド
fetch('/create-charge', {
method: 'POST',
body: JSON.stringify({ token, amount, order_id })
})
.then(res => res.json())
.then(data => {
if (data.requires_3ds) {
// 3DS認証にリダイレクト
window.location.href = data.authorize_uri;
} else {
// 支払い完了
window.location.href = '/payment-success';
}
});

ステップ5: コールバックを処理

認証後、顧客はreturn_uriにリダイレクトされます:

app.get('/payment/callback', async (req, res) => {
// チャージステータスを取得
const chargeId = req.query.charge_id || req.session.charge_id;

const charge = await omise.charges.retrieve(chargeId);

if (charge.status === 'successful') {
// 3DS認証成功
await processOrder(charge.metadata.order_id);
res.redirect('/payment-success?order=' + charge.metadata.order_id);
} else if (charge.status === 'failed') {
// 3DS認証失敗
res.redirect('/payment-failed?reason=' + encodeURIComponent(charge.failure_message));
} else {
// まだ保留中 - 再度チェックまたはwebhookを使用
res.redirect('/payment-pending');
}
});

ステップ6: Webhookハンドラーを実装

信頼性のあるステータス更新のためにwebhookを使用:

app.post('/webhooks/omise', (req, res) => {
const event = req.body;

if (event.key === 'charge.complete') {
const charge = event.data;

if (charge.status === 'successful') {
// 支払い成功を処理
processOrder(charge.metadata.order_id);
} else if (charge.status === 'failed') {
// 支払い失敗を処理
handleFailedPayment(charge.metadata.order_id, charge.failure_message);
}
}

res.sendStatus(200);
});

完全な実装例

<!DOCTYPE html>
<html>
<head>
<title>3DS Checkout</title>
<script src="https://cdn.omise.co/omise.js"></script>
</head>
<body>
<form id="payment-form">
<input type="text" id="card-name" placeholder="Card Holder" required />
<input type="text" id="card-number" placeholder="Card Number" required />
<input type="text" id="expiry-month" placeholder="MM" required />
<input type="text" id="expiry-year" placeholder="YYYY" required />
<input type="text" id="cvv" placeholder="CVV" required />
<button type="submit">Pay THB 1,000</button>
</form>

<script>
Omise.setPublicKey("pkey_test_YOUR_KEY");

document.getElementById('payment-form').addEventListener('submit', async (e) => {
e.preventDefault();

// ステップ1: トークンを作成
Omise.createToken("card", {
name: document.getElementById('card-name').value,
number: document.getElementById('card-number').value,
expiration_month: parseInt(document.getElementById('expiry-month').value),
expiration_year: parseInt(document.getElementById('expiry-year').value),
security_code: document.getElementById('cvv').value
}, async (statusCode, response) => {
if (statusCode !== 200) {
alert('Error: ' + response.message);
return;
}

// ステップ2: サーバーでチャージを作成
const result = await fetch('/create-charge', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
token: response.id,
amount: 100000,
order_id: 'ORD-12345'
})
}).then(r => r.json());

// ステップ3: レスポンスを処理
if (result.requires_3ds) {
// 3DS認証にリダイレクト
window.location.href = result.authorize_uri;
} else {
// フリクションレス - 支払い完了
window.location.href = '/payment-success';
}
});
});
</script>
</body>
</html>

トレードオフと考慮事項

利点

  • 不正削減: 不正取引が70%以上減少
  • 責任移転: 銀行がチャージバック責任を負担
  • 手数料削減: 異議申し立てが少ない = 異議申し立て手数料が低い
  • コンプライアンス: 特定の事業タイプで必須
  • 顧客信頼: プロフェッショナルなセキュリティ = 信頼の向上

欠点

  • コンバージョンへの影響: 一部の顧客がリダイレクトで離脱(フリクションレスが役立つ)
  • 継続課金不可: 保存済みカードを自動課金できない
  • ユーザーフリクション: チャレンジフローがチェックアウトに1〜3分追加
  • 技術的複雑さ: 追加のリダイレクト処理が必要
  • 国際的なバリエーション: 銀行の実装品質が異なる

緩和戦略

カート放棄の削減:

// リダイレクト前に明確なメッセージを表示
function initiate3DS(authorizeUri) {
const modal = showModal({
title: "安全な支払い確認",
message: "確認のため銀行にリダイレクトされます。これにより支払いが安全に保たれます。",
button: "確認に進む"
});

modal.onConfirm = () => {
window.location.href = authorizeUri;
};
}

継続課金の処理:

// 初回チャージ: 3DSを使用
const firstCharge = await omise.charges.create({
amount: 29900,
currency: 'THB',
card: tokenId,
return_uri: 'https://example.com/callback',
metadata: { type: 'subscription_signup' }
});

// 今後のチャージのために顧客を保存
const customer = await omise.customers.create({
email: 'customer@example.com',
card: tokenId
});

// 後続のチャージ: 3DSなし(顧客IDを使用)
const recurringCharge = await omise.charges.create({
amount: 29900,
currency: 'THB',
customer: customer.id,
// return_uriなし = 3DS不要
});

3D Secureのテスト

テストモードで3DSを有効化

サポートに連絡してテストモードで3DSを有効にします:

Email: support@omise.co
件名: テストモードで3DSを有効化

テストカード

さまざまな3DSシナリオをテストするためにこれらのカードを使用:

注記

3DSテストには3DS対応のテストアカウントが必要です。support@omise.coに連絡して有効化してください。

標準成功カード(3DS問題なし):

カード番号ブランド予想される結果
4242 4242 4242 4242Visaフリクションレス承認
5555 5555 5555 4444Mastercardフリクションレス承認

3DS登録失敗カード:

カード番号ブランド予想される結果
4111 1111 1115 0002Visa3DS登録失敗
5555 5511 1112 0002Mastercard3DS登録失敗
3530 1111 1110 0002JCB3DS登録失敗

3DS認証失敗カード:

カード番号ブランド予想される結果
4111 1111 1114 0003Visa3DS認証失敗
5555 5511 1111 0003Mastercard3DS認証失敗
3771 3816 1111 003Amex3DS認証失敗

テスト認証フロー

  1. テストカードとreturn_uriでチャージを作成
  2. authorize_uriが存在する場合、URLにアクセス
  3. テストページでモック認証を完了
  4. return_uriへのリダイレクトを確認
  5. 最終的なチャージステータスをチェック
# 3DSでテストチャージ
curl https://api.omise.co/charges \
-u skey_test_YOUR_KEY: \
-d "amount=100000" \
-d "currency=THB" \
-d "card=tokn_test_..." \
-d "return_uri=https://example.com/callback"

よくある問題とトラブルシューティング

問題: "3d secure is requested, but return URI is not set"

原因: アカウントで3DSが有効だがreturn_uriが提供されていない

解決策:

// 3DSが有効な場合は常にreturn_uriを含める
const charge = await omise.charges.create({
amount: 100000,
currency: 'THB',
card: tokenId,
return_uri: 'https://yourdomain.com/callback' // 必須!
});

問題: 顧客が3DSページで離脱

原因:

  • 混乱する銀行認証ページ
  • 長い認証時間
  • 顧客が銀行パスワードを知らない

解決策:

  • リダイレクト前に明確なメッセージを表示
  • 顧客の期待を設定(「銀行で確認します」)
  • サポート連絡先情報を提供
  • タイムアウト処理を実装

問題: return_uriが呼び出されない

原因:

  • 顧客がブラウザを閉じた
  • 銀行のリダイレクトが失敗
  • 間違ったreturn_uri URL

解決策:

  • バックアップとしてwebhookを使用(charge.completeイベント)
  • 顧客が注文ステータスを確認できるようにする
  • チャージID検索で注文ステータスページを実装

問題: フリクションレスが機能しない

原因:

  • 銀行に送信される取引データが不十分
  • 加盟店にとって新しい顧客
  • 高リスク取引の特性

解決策:

  • 完全な請求先住所を提供
  • 顧客のメールと電話を含める
  • 時間をかけて取引履歴を構築

ベストプラクティス

  1. 明確なコミュニケーションを提供

    <div class="3ds-notice">
    <p>セキュリティのため、この支払いを銀行で確認するよう求められます。</p>
    <p>通常1分未満で完了します。</p>
    </div>
  2. 適切なエラー処理を実装

    if (charge.failure_code === '3d_secure_authentication_failed') {
    showMessage('銀行認証に失敗しました。再試行するか、別のカードを使用してください。');
    }
  3. 信頼性のためにWebhookを使用

    • リダイレクトコールバックのみに依存しない
    • charge.complete webhookハンドラーを実装
    • webhookイベントから注文ステータスを更新
  4. フリクションレスの最適化

    • 完全な顧客データを収集
    • 請求先住所を提供
    • 電話とメールを含める
    • ポジティブな支払い履歴を構築
  5. タイムアウトを適切に処理

    // 合理的なタイムアウトを設定
    setTimeout(() => {
    if (!paymentConfirmed) {
    showMessage('支払い確認が予想より時間がかかっています。注文ステータスを確認してください。');
    }
    }, 5 * 60 * 1000); // 5分
  6. 徹底的にテスト

    • フリクションレスとチャレンジフローの両方をテスト
    • 失敗シナリオをテスト
    • モバイルデバイスでテスト
    • 実際のテスト銀行アプリでテスト

FAQ

3D Secureは必須ですか?

3D Secureは、Omiseの不正アナリストによって決定された特定の事業タイプ(旅行、デジタル商品、ゲーム)で必須です。他の加盟店にとっては任意ですが、高額または高リスク取引には推奨されます。

3D Secureはチャージバックを保証しますか?

いいえ、しかし大幅に削減します。3DS認証が成功すると、責任が発行銀行に移転するため、チャージバックが承認される可能性が低くなります。ただし、まれに銀行が3DS取引に対して異議を申し立てる場合があります。

サブスクリプションに3D Secureを使用できますか?

自動継続課金には直接使用できません。ただし、以下のことができます:

  1. 初回カード設定に3DSを使用
  2. カードを顧客として保存
  3. 継続課金には3DSなしで顧客IDを課金(銀行ルールに従う)
フリクションレスとチャレンジフローの違いは何ですか?

フリクションレス: 銀行がリスク分析に基づいて即座に承認 - 顧客のインタラクション不要。優れたUX。

チャレンジ: 銀行が追加の確認を要求(OTP、生体認証) - 顧客がインタラクションする必要があります。より安全ですが遅い。

銀行が取引リスクに基づいて使用するフローを決定します。

3DS認証にはどのくらい時間がかかりますか?
  • フリクションレス: 即座(< 1秒)
  • チャレンジ: 通常1〜3分
  • 初回登録: 最大10分

最新の実装のほとんどは、低リスク取引にフリクションレスフローを使用します。

3D Secureはモバイルで動作しますか?

はい!3DS2はモバイル向けに完全に最適化されています:

  • アプリ内認証(ブラウザリダイレクトなし)
  • 生体認証オプション(指紋、Face ID)
  • 銀行アプリのディープリンク
  • 3DS1よりも優れたモバイルUX

関連リソース

次のステップ

  1. サポートに連絡して3DSを有効化
  2. return_uri処理を実装
  3. webhook通知を設定
  4. テストカードでテスト
  5. 不正削減を監視
  6. 本番稼働