CYBERSOFT
Đăng nhập

Thực chiến fintech: thanh toán QR VietQR/napas 247, retry & chống trùng bằng Idempotency-Key

Thực chiến doanh nghiệpFintechAPIPlaywrightMockingThực tế
🗓 1 tháng trước22 phút đọc·👁 679 lượt xem👤 247 người đọc

Bài toán thực chiến thanh toán QR: quét mã VietQR qua napas 247, cổng thanh toán, retry & timeout, chống trùng giao dịch bằng Idempotency-Key, hoàn tiền — kiểm thử theo bất biến không ghi nợ 2 lần, tổng tiền khớp, trạng thái cuối duy nhất, hoàn tiền cân bằng sổ.

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ữ.
Bài này thuộc LOẠI 'Thực chiến doanh nghiệp' (thucchien) — giải một bài toán THẬT end-to-end trên domain fintech thanh toán QR, đối chiếu độ sâu với bài mẫu flagship trong hệ thống.

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.

Kiến trúc thanh toán QR VietQR/napas 247 & chống trùng giao dịch · VietQR/napas 247 payment architecture App khách hàngquét mã QR Merchant APItạo lệnh · idempotency-key Payment Gateway Napas 247 Switch Ngân hàng phát hànhtrừ tiền · webhook Ledger nội bộghi sổ · hoàn tiền Đồng bộ: quét QR → Merchant API tạo lệnh gắn Idempotency-Key → gọi Payment Gateway. Bất đồng bộ: Napas 247 xử lý qua ngân hàng phát hành, kết quả về qua webhook có thể trễ, trùng, hoặc không đến (timeout). Sync: scan QR → Merchant API creates order with Idempotency-Key → calls Payment Gateway. Async: Napas 247 processes via issuing bank, result returns via webhook that can be late, duplicated, or never arrive (timeout). Điểm khó kiểm thử · Hard-to-test • Gateway/Napas là bên thứ ba — cần mock kèm độ trễ thật• Retry do timeout dễ tạo giao dịch trùng• Webhook có thể đến trễ, đến 2 lần, hoặc không đến• Hoàn tiền phải cân bằng đúng sổ ledger Chiến lược · Strategy • Mọi lệnh thanh toán bắt buộc Idempotency-Key• Test retry mạng + webhook trùng bằng mock có kiểm soát• Assert tổng tiền + trạng thái cuối duy nhất• Đối soát cuối ngày với sao kê cổng thanh toán
Kiến trúc luồng thanh toán QR VietQR/napas 247, phân tách phần đồng bộ gọi gateway và phần bất đồng bộ nhận webhook.

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.

💡 Vẽ máy trạng thái (state machine) của giao dịch TRƯỚC khi viết test: CREATED → PENDING → SUCCESS/FAILED/EXPIRED → REFUNDED. Mỗi cạnh chuyển tiếp là một ca cần phủ, và mọi trạng thái phải có đường thoát — không được có trạng thái 'kẹt' vô thời hạn.

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.
🔒

Nội dung bị khoá

Bạn đang xem bản xem trước. Đăng nhập để mở khoá toàn bộ bài viết và tất cả tài liệu Tester/QA.

Đã xem 24% nội dung
  • Đọc trọn vẹn mọi bài viết
  • Lưu bài & ghi chú cá nhân
  • Theo dõi tiến độ đã đọc
  • Luyện phỏng vấn, ISTQB, Mock
Đăng nhập để đọc tiếp

Chưa có mã? Lấy mã qua Fanpage / Zalo CyberSoft.

0

💬 Bình luận (0)

Bạn có thể đọc mọi bình luận. Đăng nhập để bình luận

Chưa có bình luận nào. Hãy là người đầu tiên!