1. Bối cảnh doanh nghiệp & phạm vi
Bạn là QA Lead tại QuickPay, một cổng thanh toán trung gian phục vụ hơn 12.000 điểm bán (merchant) tại Việt Nam, xử lý trung bình 450.000 giao dịch thanh toán QR mỗi ngày thông qua chuẩn VietQR và mạng chuyển mạch napas 247. Sản phẩm cốt lõi cho phép khách hàng quét mã QR tại quầy thu ngân, ứng dụng ngân hàng của khách trừ tiền, và tiền được chuyển vào tài khoản merchant gần như tức thời. Vì đây là 'chạm tiền thật' ở tần suất cực cao, mục tiêu chính quý này là siết chặt cơ chế chống trùng giao dịch (idempotency) sau khi phát hiện một sự cố production gần đây: một merchant lớn bị ghi nợ khách hàng 2 lần cho cùng một hoá đơn do client thử lại (retry) request khi mạng chập chờn.
Đội ngũ kỹ thuật đã thống nhất một quy tắc bắt buộc: MỌI lệnh thanh toán gửi tới Payment Gateway phải mang một Idempotency-Key duy nhất do merchant sinh ra, và cổng thanh toán chịu trách nhiệm đảm bảo cùng một key dù được gọi bao nhiêu lần cũng chỉ tạo ra đúng một giao dịch trừ tiền thực sự. Bên cạnh đó, hệ thống phải xử lý đúng các tình huống bất định vốn dĩ của thanh toán qua bên thứ ba: gateway timeout không phản hồi, webhook kết quả từ napas 247 đến trễ hoặc đến trùng lặp, và yêu cầu hoàn tiền một phần hoặc toàn phần khi khách khiếu nại. Vì Ngân hàng Nhà nước yêu cầu đối soát (reconciliation) chính xác tuyệt đối giữa sổ nội bộ và sao kê từ napas 247 mỗi cuối ngày, chiến lược kiểm thử của tài liệu này đặt trọng tâm vào tính đúng đắn tài chính và khả năng chống trùng hơn là giao diện quét mã.
Phạm vi tự động hoá của tài liệu này
- Luồng thanh toán QR đầu-cuối: sinh mã VietQR → khách quét → tạo lệnh với Idempotency-Key → gọi Payment Gateway → napas 247 xử lý → webhook kết quả → cập nhật ledger.
- Các ca lỗi bất định: gateway timeout, retry do mạng, webhook trùng lặp, webhook đến trễ sau khi đã hết hạn xử lý.
- Nghiệp vụ hậu kiểm: đối soát cuối ngày giữa ledger nội bộ và sao kê napas 247, xử lý hoàn tiền một phần/toàn phần và cân bằng sổ sách.
- Đưa toàn bộ vào CI/CD chạy trên mỗi pull request, kèm giám sát tỉ lệ giao dịch trùng phát hiện được và độ trễ webhook trung bình.
- Tích hợp AI Agent để soạn ca kiểm thử biên cho các đối tác gateway mới và điều tra log đối soát lệch — có ranh giới rõ giữa việc AI được làm và việc con người phải giữ.
2. Kiến trúc & luồng nghiệp vụ
Trước khi thiết kế ca kiểm thử, QA phải nắm được luồng thanh toán QR đi qua những thành phần nào và đâu là ranh giới đồng bộ/bất đồng bộ, vì chính ranh giới này quyết định cách chờ webhook và cách mock gateway trong test.
Phần đồng bộ diễn ra ngay khi khách quét mã: Merchant API tạo lệnh thanh toán với một Idempotency-Key duy nhất (thường sinh từ mã hoá đơn + timestamp), sau đó gọi Payment Gateway của QuickPay. Gateway kiểm tra key này đã tồn tại chưa trước khi tiếp tục — nếu đã tồn tại và đang xử lý, gateway trả về NGAY kết quả của lần gọi đầu tiên thay vì tạo giao dịch mới. Việc gọi tiếp sang Napas 247 Switch và ngân hàng phát hành có thể mất từ 1 đến 10 giây tuỳ tải hệ thống liên ngân hàng, và đôi khi timeout hoàn toàn, nên đây là điểm đầu tiên cần mock ổn định kèm độ trễ giả lập trong môi trường test.
Phần bất đồng bộ và phức tạp nhất là việc nhận kết quả qua webhook từ Napas 247: sau khi ngân hàng phát hành trừ tiền thành công, kết quả được đẩy về Merchant API dưới dạng webhook HTTP POST, có thể đến sau vài trăm mili-giây hoặc trễ tới vài phút nếu mạng liên ngân hàng nghẽn. napas 247 có cơ chế tự động gửi lại webhook nếu không nhận được HTTP 200 xác nhận trong 5 giây, nghĩa là hệ thống của QuickPay PHẢI tự chống trùng khi nhận webhook cùng transactionId hai lần — đây là nguồn bug phổ biến nếu xử lý webhook không idempotent.
3. Mô hình dữ liệu & bất biến nghiệp vụ
Mô hình dữ liệu cốt lõi gồm 3 thực thể chính: PaymentOrder (lệnh thanh toán, gắn với trạng thái state machine và Idempotency-Key duy nhất), GatewayTransaction (mỗi bản ghi ứng với 1 lần gọi thực sự tới napas 247, có gatewayTxnId, requestPayload, responseStatus), và LedgerEntry (bút toán ghi sổ nội bộ, gồm loại DEBIT/REFUND, số tiền, thời điểm). Hiểu đúng mô hình này là điều kiện tiên quyết để định nghĩa oracle — kết quả kỳ vọng chính xác — thay vì chỉ kiểm tra thông báo hiển thị trên màn hình.
Bốn bất biến phải đúng ở MỌI thời điểm
- Idempotency-Key duy nhất: cùng một Idempotency-Key dù gọi lệnh thanh toán bao nhiêu lần cũng chỉ tạo ĐÚNG MỘT GatewayTransaction ghi nợ thật, không ghi nợ 2 lần.
- Bảo toàn tổng tiền: tổng số tiền đã ghi nợ trong LedgerEntry cho một PaymentOrder LUÔN khớp đúng số tiền hiển thị trên mã QR ban đầu — không thừa, không thiếu.
- Trạng thái cuối duy nhất: mỗi giao dịch tại mọi thời điểm chỉ ở đúng một trạng thái trong tập hợp lệ (CREATED/PENDING/SUCCESS/FAILED/EXPIRED/REFUNDED), không tồn tại trạng thái mâu thuẫn.
- Cân bằng sổ khi hoàn tiền: sau khi hoàn tiền một phần hoặc toàn phần, SUM(DEBIT) - SUM(REFUND) của một giao dịch phải luôn bằng đúng số tiền khách hàng thực sự còn bị giữ, không âm.
💬 Bình luận (0)
Chưa có bình luận nào. Hãy là người đầu tiên!