Để tránh cộng tiền hai lần khi đối soát giao dịch MB Bank qua API, hệ thống cần nhận diện mỗi giao dịch ngân hàng bằng một khóa duy nhất, rồi ghi nhận giao dịch và cập nhật số dư trong cùng một transaction cơ sở dữ liệu. Kiểm tra trùng ở mã ứng dụng là chưa đủ vì webhook, tiến trình lấy lịch sử và tác vụ thử lại có thể chạy đồng thời.
Hướng dẫn dưới đây dành cho lập trình viên vận hành website nhận chuyển khoản MB Bank. Cần phân biệt API chính thức của ngân hàng với dịch vụ tích hợp bên thứ ba; cấu trúc mã giao dịch, cơ chế xác thực và quy tắc gửi lại phải đối chiếu tài liệu của đúng bên cung cấp. Bài viết không giả định MB Bank có endpoint công khai hay một kiểu chữ ký cụ thể.
Hai bản tin giống nhau chưa chắc là hai khoản tiền. Ngược lại, hai giao dịch có cùng nội dung và số tiền vẫn có thể là hai lần chuyển khoản hợp lệ.

Không dùng riêng tổ hợp số tiền, nội dung và thời gian làm khóa chống trùng. Hai khách có thể chuyển cùng số tiền trong một khoảng thời gian ngắn. Hãy xác nhận trường nào định danh giao dịch ổn định, phạm vi duy nhất của trường đó và liệu webhook với lịch sử có dùng cùng định danh hay không.
Đơn nạp thể hiện yêu cầu của khách; giao dịch ngân hàng thể hiện tiền thực nhận. Hai đối tượng này cần bản ghi riêng. Đơn nên có mã nội bộ, người dùng, số tiền dự kiến, tài khoản nhận, nội dung tham chiếu và trạng thái. Giao dịch cần lưu mã từ nguồn cung cấp, số tiền, chiều giao dịch, tài khoản nhận, thời điểm và kết quả xử lý.
Khi ghép đơn, phải kiểm tra đồng thời mã tham chiếu, số tiền và tài khoản nhận. Chỉ xử lý khoản ghi có phù hợp với quy tắc đã công bố. Giao dịch thiếu nội dung, sai số tiền hoặc không xác định được đơn nên vào hàng chờ đối soát, không tự cộng theo phỏng đoán.
Khóa chống trùng phải dựa trên phạm vi định danh được tài liệu xác nhận. Chẳng hạn, nếu mã chỉ duy nhất trong từng tài khoản, khóa cần bao gồm tài khoản đó. Không tùy tiện thêm tên kênh webhook hoặc polling vào khóa: làm vậy có thể khiến cùng một giao dịch bị coi là hai bản ghi khác nhau.
Ví dụ giả lập về ràng buộc dữ liệu:
UNIQUE(source_namespace, receiving_account_id, bank_transaction_id)
UNIQUE(ledger_entry_type, payment_transaction_id)Đây là minh họa thiết kế, không phải tên trường của API MB Bank. Ràng buộc thứ nhất chống lưu trùng giao dịch; ràng buộc thứ hai ngăn tạo lại bút toán cộng tiền cho giao dịch đó. Nếu nguồn không cung cấp định danh đủ tin cậy, cần làm rõ với nhà cung cấp trước khi tự động ghi có.
Transaction cơ sở dữ liệu giúp các thay đổi liên quan cùng thành công hoặc cùng bị hủy. Kết hợp ràng buộc duy nhất với khóa bản ghi hoặc cập nhật có điều kiện để tránh hai tiến trình cùng xử lý một đơn.

Không coi việc khách quay về trang thành công hoặc callback từ trình duyệt là bằng chứng đã nhận tiền. Nếu cập nhật ví ở một dịch vụ khác, transaction cục bộ không bao trùm được toàn bộ luồng; cần cơ chế chuyển việc bền vững như outbox và khóa chống trùng tại dịch vụ nhận.
Tình huống giả lập: đơn nạp NAP-DEMO-27 chờ nhận 200.000 đồng vào tài khoản MB Bank đã cấu hình. Webhook thông báo giao dịch GD-DEMO-81; ngay sau đó, tác vụ lấy lịch sử cũng trả về chính giao dịch này.
Tiến trình webhook tạo bản ghi giao dịch, khóa đơn, kiểm tra khớp tiền và tài khoản rồi ghi một bút toán cộng 200.000 đồng. Tiến trình lấy lịch sử gặp khóa duy nhất đã tồn tại nên đọc trạng thái hiện tại thay vì tạo khoản cộng mới. Kết quả cần đạt là một giao dịch, một bút toán và số dư chỉ tăng 200.000 đồng.
Nếu khách thực sự chuyển thêm 200.000 đồng với mã GD-DEMO-82, đây là khoản tiền khác, không phải thông báo trùng. Nếu đơn chỉ được thanh toán một lần, giao dịch thứ hai cần vào quy trình xử lý tiền thừa hoặc đối soát thủ công, thay vì bị xóa vì giống nội dung.
Khi đã cộng nhầm, không xóa lịch sử để che chênh lệch. Hãy xác minh khoản nhận thực tế, lập bút toán điều chỉnh có liên kết đến bút toán sai và lưu người phê duyệt. Nếu tiền đã được sử dụng, cần xử lý theo quy trình vận hành thay vì tự ý trừ thiếu kiểm soát.

Dùng dữ liệu giả lập hoặc môi trường thử nghiệm nếu nhà cung cấp hỗ trợ. Gửi cùng một sự kiện nhiều lần và chạy đồng thời webhook với tác vụ lấy lịch sử. Cố ý gây lỗi trước commit, sau commit và trước phản hồi để kiểm tra khả năng phục hồi.
Log nên có mã đơn, mã giao dịch, trạng thái, số lần thử và lý do từ chối; che thông tin nhạy cảm và không ghi secret. Đối soát thủ công cần phát hiện cả tiền đã nhận nhưng chưa ghi sổ lẫn khoản đã ghi sổ không có giao dịch tương ứng.
Không. Nếu lần đầu chưa ghi sổ thành công, lần sau có thể cần tiếp tục xử lý. Hãy dựa vào trạng thái đã commit, không chỉ số lần nhận.
Không. Mã đơn giới hạn việc hoàn tất đơn, còn mã giao dịch ngăn cùng khoản tiền bị dùng lại ở nơi khác. Cần kiểm soát cả hai.
Nên dùng chung logic ghi sổ sau khi chuẩn hóa dữ liệu. Điều kiện là phải ánh xạ được hai nguồn về cùng định danh giao dịch đáng tin cậy.
Hãy yêu cầu tài liệu xác nhận mã giao dịch, phạm vi duy nhất, xác thực webhook và quy tắc retry của nguồn đang dùng. Sau đó kiểm tra ràng buộc dữ liệu và chạy thử tình huống nhận đồng thời trước khi bật tự động cộng tiền. Nếu đang lựa chọn giải pháp tích hợp, bạn có thể tham khảo danh mục liên quan tại sieuthicode.com và trao đổi nhu cầu đối soát; cần xác nhận khả năng hỗ trợ MB Bank cùng thông số thực tế trước khi mua.