Bỏ qua để đến nội dung
Knowledge Hub

Tình huống: thanh toán timeout làm khách bị trừ tiền hai lần Nâng cao

Thời gian đọc ước tính: 1 phút

Một lệnh gọi payment gateway bị timeout có kết quả chưa rõ: tiền có thể đã bị trừ. Coi nó là thất bại chẳng khác nào mời khách trả tiền lần nữa.

  • Năm bước: ý nghĩa của timeout, cú bấm thứ hai, webhook đến muộn, dọn dẹp, hàng rào.
  • Để ý số lần trừ tiền trùng, đơn đã trả tiền nhưng bị huỷ và dòng settlement không khớp.
  • Điểm chỉ tính lựa chọn đầu tiên ở mỗi bước.
Tình huống

Thanh toán timeout: gateway chậm, khách trả tiền hai lần, tài chính phát hiện giao dịch trùng

Bạn phụ trách payment service của một shop online chung. Service gọi gateway bên ngoài với timeout 10 s. Mọi con số đều là minh hoạ.

Lần trừ tiền trùng trong đợt sale tới1.100
Đơn đã trả tiền nhưng bị huỷ200
Dòng settlement không khớp1.300

Bước 1/5 · Timeout nghĩa là gì?

Hôm qua p99 của gateway vượt 10 s suốt 40 phút. Tài chính báo 1.300 lần capture trong file settlement không khớp payment captured nào; 1.100 khách trong số đó bị trừ tiền hai lần.

Code checkout khi timeout:

timeout trong 40 phút
1.900
gateway vẫn đã capture
1.300
khách trả tiền lần nữa
1.100
try {
  await gateway.charge({ amount, key: randomUUID() });
  await setStatus(pay.id, 'captured');
} catch (e) {
  await setStatus(pay.id, 'failed');   // timeout cũng rơi vào đây
  return res.status(402).json({ retry: true });
}

Bạn làm gì?

State machine, schema ledger và luồng đối soát có trong Thiết kế hệ thống thanh toán.