Payment — Case thường gặp
Cách đọc mỗi case: bắt đầu từ triệu chứng/câu hỏi, sau đó đọc behavior đúng, cách kiểm tra ở UI/API/dữ liệu/code, source anchor và Ví dụ thực tế. Các case ở đây ưu tiên behavior đang chạy; nếu cần contract gốc, mở spec/code được dẫn ở cuối case.
Method không hiện ở checkout
Kiểm tra master toggle, BU/provider setting, category availability, site scope và payment option rule. Nếu method bị ẩn đúng do config, đừng sửa flow checkout.
Ví dụ thực tế: Phụ huynh ở site A không thấy Direct Debit khi checkout. → Xác định ẩn do cấu hình hay do bug. → Provider chưa bật cho BU của site A → đó là ẩn đúng config, không sửa flow checkout.
PayNow thành công nhưng UI không cập nhật
Đọc provider result/webhook, batch/payment status và checkout success method resolution. Webhook có thể đến sau redirect; UI cần chịu được trạng thái pending ngắn hạn.
Ví dụ thực tế: Khách trả thẻ xong, bị quay về trang "đang xử lý" vài giây trước khi báo thành công. → UI không được kết luận thất bại quá sớm. → Webhook về sau redirect → giữ trạng thái pending ngắn rồi cập nhật khi webhook tới.
Direct Debit tạo customer sai BU
AccountPaymentCustomer phải unique/active theo (AccountId, BusinessUnitId, PaymentProvider). Nếu thiếu BU filter, đó là lỗi boundary/security chứ không chỉ là lỗi query.
Ví dụ thực tế: Một account hoạt động ở 2 BU, set Direct Debit ở BU2 lại trỏ về customer của BU1. → Tránh rò rỉ thanh toán giữa hai đơn vị. → Query thiếu BU filter → coi là lỗi boundary, thêm
BusinessUnitIdvào điều kiện unique.
Deposit bị double submit
Kiểm tra order lock, provider callback idempotency và trạng thái batch. Deposit không được tạo nhiều transaction slots cho cùng order nếu lock còn hiệu lực.
Ví dụ thực tế: Khách bấm nút trả deposit hai lần do mạng chậm. → Tránh thu deposit hai lần cho một order. → Order lock + callback idempotency chặn slot thứ hai khi lock còn hiệu lực.
Checkout success message sai method
Đối chiếu payment-success-message-by-method, checkout confirmation type guard và method resolution. Message nên phản ánh method thực tế chứ không đoán từ route.
Ví dụ thực tế: Khách trả Direct Debit nhưng màn hình success lại ghi nội dung của PayNow. → Thông báo phải đúng method để khách không hiểu nhầm. → Resolve message theo method thực tế của giao dịch, không đoán theo route checkout.
Zero-amount checkout không mở provider
Total = 0 → bỏ qua provider dù chọn method nào; Proceed confirm ngay, Submit giữ pending theo eligibility.
Ví dụ thực tế: Booking sau ưu đãi còn total = 0 đồng, khách chọn Pay Now. → Không redirect Windcave cho khoản 0 đồng. → Nút
Proceedhiện ra, bấm xong booking confirm ngay, về confirmed success surface.
Zero-amount Pay Later-only giữ pending
Khi total = 0 và Pay Later là method duy nhất → nút Submit, booking giữ Submitted/pending, hiện pending message; không redirect booking-confirmed.
Ví dụ thực tế: Category chỉ cho Pay Later và booking có total = 0. → Không thể confirm ngay vì chưa có thao tác thu tiền. → Nút
Submitgiữ booking Submitted; admin/staff Confirm sau.
Popup finalization nền sau khi trả tiền
total payable > 0, provider trả về thành công → popup báo hệ thống đang hoàn tất booking nền, không cần bấm OK, tự đóng khi xong.
Ví dụ thực tế: Khách trả deposit xong bị redirect về portal nhưng booking chưa confirm. → Tránh khách đóng tab làm dở finalization. → Popup "đang xử lý, đừng đóng trình duyệt" hiện ra rồi tự biến mất khi finalization xong.
PayLater display name theo BU
Admin đặt PayLaterDisplayName ở tab "Other" → checkout hiện label đó cho mọi category; null/empty → fallback "Pay Later"; category cấm Pay Later thì option không hiện dù label có.
Ví dụ thực tế: BU đặt "Pay by Invoice". → Khách checkout thấy "Pay by Invoice" thay vì "Pay Later". → Hiển thị đúng label; nhưng category để
Nonethì option vẫn không hiện.
Booking FT/PT/Casual hỗn hợp xét Pay Later
Precedence FULL_TIME > PART_TIME > CASUAL: có ≥1 FT session → Full Time; không FT nhưng có PT → Part Time; chỉ Casual → không thỏa FT/PT.
Ví dụ thực tế: Booking gồm 1 session FT + 2 session Casual, category để quy tắc FT. → Xác định booking có thỏa FT không. → Tính Full Time theo precedence → Pay Later khả dụng.
Master toggle bật nhưng category cấm
Provider bật ở BU ≠ booking eligibility ở category. Method chỉ hiện khi cả hai pass; đổi một tầng không ghi đè tầng kia.
Ví dụ thực tế: Pay Now bật Stripe ở BU nhưng category B để
Disabled. → Không lẫn lộn hai cấu hình. → Section Pay Now vẫn enabled trong settings, nhưng khách checkout category B không thấy Pay Now.
Đổi payment method trên billing
Booking Manager đổi PaymentOptionId của billing qua ChangeBillingPaymentMethodModal (Direct Debit = 4 / Other = 1); nút chỉ hiện khi BU có DD provider; lỗi backend → giữ modal + hiện message.
Ví dụ thực tế: Staff muốn chuyển billing từ "Other" sang Direct Debit cho một booking. → Tránh phải tạo billing mới. → Mở modal, chọn Direct Debit, save thành công; nếu BU chưa bật DD thì nút không hiện.
Success message theo method và fallback
Batch type 201 → payNowSuccessMessage; 204 → payNowDepositSuccessMessage, fallback sang payNowSuccessMessage nếu deposit message rỗng; DD/Pay Later confirmed → directDebitSuccessMessage/payLaterMessage; message rỗng → default, không hiện content cũ đã xoá.
Ví dụ thực tế: Khách trả deposit nhưng BU chưa soạn deposit message. → Không để trống trang success. → Hiện
payNowSuccessMessagehiện hành thay vì trống hoặc content cũ đã bị xoá.
Pay Now payment bị treo ở processing
Đối chiếu provider result, payment batch và lock. Lock chỉ là guard trong lúc xử lý; khi payment settle, backend release lock để invoice/Finance tiếp tục. Không tạo payment thứ hai chỉ vì UI chậm cập nhật.
Ví dụ thực tế: Windcave đã trả success nhưng Invoice Manager vẫn thấy Processing vài giây. → Chờ settlement callback cập nhật. → Lock được nhả sau settle, thao tác Add Payment/Apply Credit mở lại.
Xero ghi nhầm tiền dư thành overpayment
Chỉ coi phần tiền là overpayment khi Xero xác nhận invoice không còn room. Overpayment dùng account code của BU, không dùng Pay Now payment code; balance Xero bằng zero một mình không đủ để split.
Ví dụ thực tế: Một batch dư tiền sau khi invoice đầu tiên được apply. → Không bỏ phần dư. → Gửi phần còn lại sang Xero và lưu overpayment đúng account code của BU.
Netcash payment không thấy trong Tux batch
Với site chạy Tux, kiểm tra callback có settle vào DirectPaymentBatch/DirectPayment của Tux hay không, đối chiếu provider reference và status trước khi reconcile Finance.
Ví dụ thực tế: Netcash báo paid nhưng batch hiển thị thiếu payment. → Tránh reconcile nhầm provider ngoài. → Tìm đúng Tux batch theo provider reference rồi mới kiểm tra Finance projection.