รหัสคำแนะนำสำหรับร้า นค้า
ทำความเข้าใจว่าทำไมธุรกรรมถูกปฏิเสธ และกำหนดขั้นตอนถัดไปที่เหมาะสมโดยใช้รหัสคำแนะนำสำหรับร้านค้าในการตอบกลับการเรียกเก็บเงิน
ภาพรวม
เมื่อธุรกรรมบัตรถูกปฏิเสธ 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 | ขอบัตรใหม่ | บัตรไม่ถูกต้อง/หมดอายุ | ขอบัตรอื่น |
| 5 | ลองใหม่ด้วย 3DS | ต้องการการยืนยันตัวตน | ลองใหม่โดยเปิดใช้งาน 3D Secure |
| 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 Secure
ผู้ออกบัตรต้องการการยืนยันตัวตนเพิ่มเติม
สาเหตุทั่วไป:
- ต้องการ SCA (บัตรยุโรป)
- นโยบายผู้ออกบัตรต้องการ 3DS
- ธุรกรรมมูลค่าสูง
- ธุรกรรมครั้งแรก
การดำเนินการ: ลองธุรกรรมใหม่โดยเปิดใช้งาน 3D Secure
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.'
};
}
}
// การลองใหม่อัจฉริยะด้วย exponential backoff
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;
}
// Exponential backoff: 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
ตัวเลขสองหลักสุดท้ายของจำนวนเงินที่เรียกเก็บกำหนดรหัสคำแนะนำ:
| จำนวนเงิน (บาท) | รหัสคำแนะนำ | สถานการณ์ |
|---|---|---|
| 10001 | 1 | ไม่ต้องลองใหม่ |
| 10002 | 2 | ลองใหม่ภายหลัง |
| 10003 | 3 | ติดต่อผู้ออกบัตร |
| 10004 | 4 | ขอบัตรใหม่ |
| 10005 | 5 | ลองใหม่ด้วย 3DS |
| 10006 | 6 | ข้อผิดพลาดทางเทคนิค |
ตัวอย่างการทดสอบ
# ทดสอบการตอบกลับ "ไม่ต้องลองใหม่"
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"