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

マーチャントアドバイスコード

取引が拒否された理由を理解し、課金レスポンスのマーチャントアドバイスコードを使用して適切な対応を判断します。

概要

カード取引が拒否された場合、Omiseは課金レスポンスにmerchant_adviceフィールドを提供します。このフィールドには、取引が失敗した理由と次に取るべきアクションを理解するための標準化されたメッセージが含まれています。

主なメリット:

  • 一貫したメッセージング - カードブランド(Visa、Mastercardなど)に関係なく同じアドバイス
  • 実行可能なガイダンス - 各拒否タイプに対する明確な次のステップ
  • 顧客体験の向上 - カード保有者へのより良いエラーメッセージ
  • 誤った拒否の削減 - リトライすべき場合と新しい支払い方法を要求すべき場合を判断

レスポンスの理解

課金が拒否された場合、レスポンスには以下が含まれます:

{
"object": "charge",
"id": "chrg_test_xxx",
"status": "failed",
"failure_code": "insufficient_fund",
"failure_message": "insufficient fund",
"merchant_advice": "Cardholder should contact their bank or use a different payment method.",
"merchant_advice_code": 3,
"card": {
"brand": "Visa",
"last_digits": "4242"
}
}
フィールド説明
failure_code技術的なエラーコード
failure_message簡潔なエラーの説明
merchant_adviceマーチャント向けの人間が読めるガイダンス
merchant_advice_codeプログラムによる処理用の数値コード

マーチャントアドバイスコード

一般的なコードとアクション

コードアドバイス説明推奨アクション
1リトライ不可取引は成功しない別の支払い方法を要求
2後でリトライ一時的な問題遅延後にリトライ(数時間/翌日)
3発行会社に連絡カード保有者が銀行と解決する必要あり顧客に銀行への連絡を依頼
4新しいカードを要求カードが無効/期限切れ別のカードを依頼
53DSでリトライ認証が必要3Dセキュアを有効にしてリトライ
6技術的エラーシステム/ネットワークの問題即座または短い遅延後にリトライ

詳細なコードリファレンス

コード1: リトライ不可

このカードでは取引が成功しません。リトライしないでください。

一般的な原因:

  • カードが紛失/盗難として報告されている
  • アカウントが閉鎖されている
  • 不正行為が検出された
  • カードが永久にブロックされている

アクション: 顧客に別の支払い方法を要求します。

if (charge.merchant_advice_code === 1) {
// このカードを保存済み支払い方法から削除
await removePaymentMethod(customer.id, card.id);

// 顧客に通知
await sendNotification(customer, {
message: 'Your card could not be charged. Please add a new payment method.'
});
}

コード2: 後でリトライ

拒否は一時的です。後でリトライすると取引が成功する可能性があります。

一般的な原因:

  • 一時的な残高不足
  • 日次/週次の限度額超過
  • 発行会社のシステムメンテナンス
  • 高い取引量

アクション: 待ってからリトライします(通常24時間後)。

if (charge.merchant_advice_code === 2) {
// 翌日のリトライをスケジュール
await schedulePaymentRetry({
charge_id: charge.id,
retry_at: addHours(new Date(), 24),
max_retries: 3
});
}

コード3: 発行会社に連絡

カード保有者が問題を解決するために銀行に連絡する必要があります。

一般的な原因:

  • アカウントのセキュリティ保留
  • 異常な活動がフラグ付けされた
  • 確認が必要
  • 旅行通知が必要

アクション: 顧客にカード発行会社への連絡を案内します。

if (charge.merchant_advice_code === 3) {
await sendNotification(customer, {
message: 'Your payment was declined. Please contact your bank to resolve this issue, then try again.'
});
}

コード4: 新しいカードを要求

カード自体が無効で使用できません。

一般的な原因:

  • 期限切れのカード
  • 無効なカード番号
  • カードが有効化されていない
  • キャンセルされたカード

アクション: 顧客に別のカードの使用を依頼します。

if (charge.merchant_advice_code === 4) {
await sendNotification(customer, {
message: 'This card is no longer valid. Please update your payment method.'
});
}

コード5: 3Dセキュアでリトライ

発行会社が追加の認証を要求しています。

一般的な原因:

  • SCAが必要(ヨーロッパのカード)
  • 発行会社のポリシーで3DSが必要
  • 高額取引
  • 初回取引

アクション: 3Dセキュアを有効にして取引をリトライします。

if (charge.merchant_advice_code === 5) {
// 3DSでリトライ
const charge = await omise.charges.create({
amount: originalAmount,
currency: 'thb',
card: card.id,
return_uri: 'https://yoursite.com/3ds-complete',
// 3DSは自動的にトリガーされます
});

// 3DS認証にリダイレクト
if (charge.authorize_uri) {
redirect(charge.authorize_uri);
}
}

コード6: 技術的エラー

システムまたはネットワークエラーが発生しました。

一般的な原因:

  • ネットワークタイムアウト
  • 発行会社のシステムが利用不可
  • 処理エラー
  • ゲートウェイ接続の問題

アクション: 即座または短い遅延後にリトライします。

if (charge.merchant_advice_code === 6) {
// 即座にリトライ
const retryCharge = await omise.charges.create({
amount: charge.amount,
currency: charge.currency,
card: charge.card.id
});
}

実装例

支払いリトライシステム

const omise = require('omise')({
secretKey: process.env.OMISE_SECRET_KEY
});

async function processPayment(customerId, amount, cardId) {
try {
const charge = await omise.charges.create({
amount: amount,
currency: 'thb',
card: cardId,
metadata: {
customer_id: customerId,
attempt: 1
}
});

if (charge.status === 'successful') {
return { success: true, charge };
}

// 拒否された取引を処理
return handleDecline(charge, customerId);

} catch (error) {
return { success: false, error: error.message };
}
}

async function handleDecline(charge, customerId) {
const code = charge.merchant_advice_code;

switch (code) {
case 1: // リトライ不可
await notifyCustomer(customerId, 'payment_failed_permanent', {
message: charge.merchant_advice
});
await flagCardForRemoval(charge.card.id);
return {
success: false,
action: 'request_new_payment_method',
message: charge.merchant_advice
};

case 2: // 後でリトライ
await scheduleRetry(charge, customerId, { delay: '24h' });
return {
success: false,
action: 'retry_scheduled',
retry_at: getNextRetryTime()
};

case 3: // 発行会社に連絡
await notifyCustomer(customerId, 'contact_bank', {
message: charge.merchant_advice
});
return {
success: false,
action: 'contact_issuer',
message: 'Please contact your bank to resolve this issue.'
};

case 4: // 新しいカードを要求
await notifyCustomer(customerId, 'update_card', {
message: charge.merchant_advice
});
return {
success: false,
action: 'update_payment_method',
message: 'This card is no longer valid. Please add a new card.'
};

case 5: // 3DSでリトライ
const retryCharge = await omise.charges.create({
amount: charge.amount,
currency: charge.currency,
card: charge.card.id,
return_uri: `https://example.com/3ds-callback/${charge.id}`
});

if (retryCharge.authorize_uri) {
return {
success: false,
action: 'redirect_3ds',
authorize_uri: retryCharge.authorize_uri
};
}
break;

case 6: // 技術的エラー
// 即座にリトライ
const immediateRetry = await omise.charges.create({
amount: charge.amount,
currency: charge.currency,
card: charge.card.id
});

if (immediateRetry.status === 'successful') {
return { success: true, charge: immediateRetry };
}

// 遅延リトライをスケジュール
await scheduleRetry(charge, customerId, { delay: '1h' });
return {
success: false,
action: 'retry_scheduled',
message: 'Temporary issue. We will retry shortly.'
};

default:
return {
success: false,
action: 'unknown',
message: charge.merchant_advice || 'Payment failed. Please try again.'
};
}
}

// 指数バックオフを使用したスマートリトライ
async function scheduleRetry(charge, customerId, options) {
const attempt = (charge.metadata?.attempt || 1) + 1;
const maxAttempts = 4;

if (attempt > maxAttempts) {
await notifyCustomer(customerId, 'payment_failed_final', {
message: 'We were unable to process your payment after multiple attempts.'
});
return;
}

// 指数バックオフ: 1時間、4時間、12時間
const delays = ['1h', '4h', '12h'];
const delay = delays[Math.min(attempt - 2, delays.length - 1)];

await retryQueue.add({
charge_id: charge.id,
customer_id: customerId,
amount: charge.amount,
currency: charge.currency,
card_id: charge.card.id,
attempt: attempt
}, {
delay: parseDelay(delay)
});
}

顧客向けエラーメッセージ

const customerMessages = {
1: 'この支払い方法は使用できません。別のカードをお試しください。',
2: '一時的に支払いを処理できません。間もなく再試行します。',
3: 'この支払いを承認するために銀行にご連絡ください。',
4: 'このカードは期限切れまたは無効です。別のカードをご使用ください。',
5: '追加の認証が必要です。銀行のページにリダイレクトされます。',
6: '技術的な問題が発生しました。もう一度お試しください。'
};

function getCustomerMessage(merchantAdviceCode, defaultMessage) {
return customerMessages[merchantAdviceCode] || defaultMessage || '支払いに失敗しました。もう一度お試しください。';
}

テスト

異なるマーチャントアドバイスコードをシミュレートするための専用テストカードを使用します。

テストカード: 4111 1111 1117 0018

課金金額の下2桁がマーチャントアドバイスコードを決定します:

金額(THB)アドバイスコードシナリオ
100011リトライ不可
100022後でリトライ
100033発行会社に連絡
100044新しいカードを要求
1000553DSでリトライ
100066技術的エラー

テスト例

# 「リトライ不可」レスポンスをテスト
curl https://api.omise.co/charges \
-u skey_test_YOUR_KEY: \
-d "amount=10001" \
-d "currency=thb" \
-d "card=tokn_test_xxx"

# 「3DSでリトライ」レスポンスをテスト
curl https://api.omise.co/charges \
-u skey_test_YOUR_KEY: \
-d "amount=10005" \
-d "currency=thb" \
-d "card=tokn_test_xxx"

ベストプラクティス

1. 常にマーチャントアドバイスを確認

if (charge.status === 'failed') {
// 適切なアクションのために常にmerchant_advice_codeを確認
const action = determineAction(charge.merchant_advice_code);
handleDeclinedPayment(charge, action);
}

2. スマートリトライロジックの実装

  • コード1: リトライしない
  • コード2: 24時間後にリトライ、最大3回
  • コード3-4: 顧客のアクションを待つ
  • コード5: 3DSで即座にリトライ
  • コード6: 即座にリトライ、その後バックオフ

3. 分析用のログ記録

await analytics.track('payment_declined', {
charge_id: charge.id,
failure_code: charge.failure_code,
merchant_advice_code: charge.merchant_advice_code,
card_brand: charge.card.brand,
amount: charge.amount
});

4. 明確なコミュニケーション

技術的なコードを、問題解決に導く顧客にわかりやすいメッセージに変換します。

FAQ

merchant_advice_codeが存在しない場合はどうすればよいですか?

古い拒否やカード以外の支払い方法では、マーチャントアドバイスコードが含まれていない場合があります。その場合は、failure_codefailure_messageフィールドをガイダンスとして使用してください。

merchant_adviceを顧客に表示すべきですか?

merchant_adviceフィールドはマーチャント向けであり、顧客向けではありません。生のメッセージを表示するのではなく、アドバイスコードに基づいて顧客にわかりやすいメッセージを作成してください。

拒否された支払いをどのくらいの頻度でリトライすべきですか?

コード2(後でリトライ)の場合、以下を推奨します:

  • 1回目のリトライ: 24時間後
  • 2回目のリトライ: 3日後
  • 3回目のリトライ: 7日後
  • その後、顧客に支払い方法の更新を通知
マーチャントアドバイスコードはすべてのカードブランドで同じですか?

はい、OmiseはVisa、Mastercard、その他のカードスキームでアドバイスを正規化するため、カードブランドに関係なく一貫したコードを取得できます。

完全なコードリストはどこで確認できますか?

完全なマーチャントアドバイスコードリファレンスドキュメントをダウンロードしてください:

マーチャントアドバイスコードをダウンロード(Excel)

追加サポートが必要な場合は、support@omise.coにお問い合わせください。

関連リソース