MERSO IT

Tự động hóa · Thanh toán

VNPay, MoMo, ZaloPay: tự động hóa thanh toán và đối soát

MERSO IT Insights · Cập nhật tháng 7 2026 · 9 phút đọc

Các luồng thanh toán từ nhiều cổng thanh toán Việt Nam hội tụ về một sổ cái đã xác minh

Điều gì đang bị đặt cược: tầng thanh toán là phần duy nhất trong hệ thống của bạn mà một lỗi phần mềm tốn tiền trực tiếp — một đơn đã giao mà chưa bao giờ được thanh toán, một khoản hoàn ví bị ghi có hai lần, một khoảng trống quyết toán không ai nhận ra suốt cả quý. Shop Việt Nam thường chạy hai hoặc ba cổng cùng lúc (VNPay cho thẻ và QR ngân hàng, MoMo và ZaloPay cho ví điện tử), và mỗi cổng có ngữ nghĩa callback, cơ chế chữ ký và nhịp quyết toán riêng. Bài viết này trình bày những mẫu thiết kế khiến cả tầng thanh toán trở nên nhàm chán — mà trong thanh toán, nhàm chán chính là mục tiêu.

Ba mẫu tích hợp, một mô hình nội bộ

  1. Redirect — khách hàng rời trang thanh toán của bạn sang trang do cổng host và quay lại với một kết quả. Dễ xây nhất, và cũng là nơi trú ngụ của lỗi bảo mật kinh điển (nói thêm bên dưới).
  2. QR — bạn hiển thị một mã QR thanh toán; khách quét bằng app ngân hàng hoặc ví. Rất tốt cho tỷ lệ chuyển đổi tại Việt Nam, nhưng trình duyệt không bao giờ "quay lại" — bạn chỉ biết kết quả qua callback phía server.
  3. App-to-app / deeplink — thanh toán trên mobile chuyển sang app ví rồi quay về. UX tốt nhất trên di động, nhiều bộ phận chuyển động nhất, và chặng quay về có thể bị gián đoạn bởi bất cứ thứ gì, từ một cuộc gọi đến một bản cập nhật hệ điều hành.

Dù chạy tổ hợp nào, hãy chuẩn hóa mọi thứ về một đối tượng thanh toán nội bộ duy nhất với một máy trạng thái duy nhất: created → pending → paid / failed / expired → refunded (một phần hoặc toàn bộ). Các adapter cổng chỉ làm nhiệm vụ phiên dịch; pipeline đơn hàng của bạn chỉ nhìn thấy trạng thái nội bộ. Đây chính là kỷ luật adapter mà chúng tôi áp dụng cho hãng vận chuyển và các nền tảng trong hệ thống trọn gói.

IPN là sự thật. Redirect chỉ là trang trí.

Mọi cổng đều gửi một thông báo server-to-server (IPN hoặc callback) báo kết quả thanh toán, được ký bằng merchant secret của bạn. Ba quy tắc không thể thương lượng:

  1. Xác minh chữ ký trên mọi IPN — từ chối bất cứ thứ gì không qua được kiểm tra, và ghi log lại, vì một chữ ký sai hoặc là cấu hình nhầm hoặc là ai đó đang dò endpoint của bạn.
  2. Xác minh số tiền phía server. So sánh số tiền trong IPN đã xác minh với số tiền đơn hàng mong đợi. Tuyệt đối không đánh dấu đơn đã thanh toán dựa trên việc khách được redirect về trang của bạn — tham số redirect đi qua trình duyệt của khách và có thể bị phát lại hoặc chỉnh sửa. Trang redirect hiển thị trạng thái thân thiện; IPN mới là thứ thay đổi đơn hàng.
  3. Làm cho handler idempotent. Các cổng sẽ gửi lại IPN khi endpoint của bạn chậm hoặc trả lỗi — đôi khi vài giờ sau. Xử lý cùng một thông báo hai lần phải cho ra chính xác cùng một trạng thái, không phải một lần giao hàng thứ hai hay một bút toán trùng. Khóa theo mã giao dịch của cổng kết hợp với mã đơn hàng của bạn.

Pending là một trạng thái thực — hãy xử lý timeout trung thực

Khách quét QR, app ngân hàng của họ treo, trang thanh toán của bạn hết giờ. Timeout không phải là thất bại. Tiền vẫn có thể đến: lệnh chuyển khoản hoàn tất, IPN bắn về hai phút sau. Nếu hệ thống của bạn đã đánh dấu đơn thất bại và nhả hàng tồn kho, giờ bạn có một đơn đã thanh toán mà không còn hàng giữ chỗ — và một khách hàng bực bội. Mẫu xử lý trung thực:

Cửa sổ pendingGiữ các thanh toán bị timeout ở trạng thái pending với hàng vẫn được giữ chỗ trong một khoảng thời gian xác định, và chạy một job chủ động truy vấn API tra cứu trạng thái của cổng trong suốt khoảng đó. Chỉ sau khi cửa sổ đóng lại mà không có xác nhận, bạn mới cho đơn hết hạn và nhả hàng — và kể cả khi đó, một IPN đến muộn phải kích hoạt cảnh báo và luồng hoàn tiền, tuyệt đối không được lặng lẽ vứt bỏ.

Hoàn tiền qua API

Hoàn tiền thủ công qua dashboard của cổng không mở rộng được và không để lại dấu vết trong hệ thống của bạn. Hãy nối luồng hoàn tiền qua API refund của từng cổng, điều khiển từ chính trạng thái đơn hàng của bạn: một yêu cầu trả hàng được duyệt trong trang quản trị kích hoạt lệnh gọi refund, phản hồi của cổng cập nhật đối tượng thanh toán, và sổ cái ghi nhận cả hai chiều. Hoàn tiền một phần (khách giữ lại một trong ba món) cần số tiền ở cấp từng dòng — hãy thiết kế mô hình nội bộ cho việc đó ngay từ ngày đầu, vì việc nhồi hỗ trợ hoàn một phần vào một cờ boolean refunded là cực hình.

Đối soát quyết toán hàng ngày

Mỗi cổng quyết toán về ngân hàng của bạn theo chu kỳ riêng, đã trừ phí, theo từng đợt với định dạng dòng khác nhau. Đối soát là công việc chứng minh sổ sách của bạn khớp với thực tế:

BướcĐiều gì diễn raBắt được gì
1. Nạp dữ liệuKéo file quyết toán hoặc bảng kê trong ngày của từng cổng
2. KhớpKhớp các dòng quyết toán với đối tượng thanh toán theo mã giao dịchKhoản thanh toán cổng bỏ quên, hoặc bạn đếm trùng
3. Sổ phíGhi phí của từng dòng vào tài khoản phí theo từng cổngThay đổi biểu phí và chênh lệch chi phí theo phương thức
4. Ngoại lệDòng không khớp và lệch số tiền đi vào hàng đợi xem xétCon số 0,x% trở thành tiền thật khi quy mô lớn

Thời điểm quyết toán khác nhau giữa các cổng — cổng này quyết toán ngày hôm sau, cổng kia theo chu kỳ khác — nên "doanh thu hôm qua" không bao giờ bằng "tiền về ngân hàng hôm qua". Hãy đối soát từng cổng theo chu kỳ của chính cổng đó, và báo cáo vị thế tiền mặt tách biệt với doanh thu. Nếu bạn còn thu COD, sổ cái này nên nằm cạnh việc khớp tiền COD, được trình bày trong bài viết về đối soát COD — một hàng đợi ngoại lệ duy nhất cho mọi dòng tiền vào.

Sandbox không phải production

Sandbox của mọi cổng đều khác production ở những điểm quan trọng: IPN tức thời trong sandbox so với retry trễ trong production, kiểm tra chữ ký lỏng lẻo, ngân hàng test không bao giờ thất bại. Vượt qua test sandbox chỉ chứng minh đường đi thuận lợi của bạn biên dịch được. Trước khi go-live, hãy chạy các giao dịch thật nhỏ qua từng phương thức — bao gồm một lần timeout có chủ đích và một lần hoàn tiền — và xác nhận các dòng quyết toán xuất hiện và khớp được. Đặc biệt là các dòng phí, chúng chỉ hiện ra với tiền thật.

Vị trí trong bức tranh chung

Một khi tầng thanh toán phát ra các sự kiện sạch, đã xác minh, mọi thứ phía sau đều dễ hơn: hóa đơn điện tử được xuất dựa trên thanh toán đã xác nhận (hướng dẫn Shopify → MISA AMIS), chỉ số hàng ngày của bạn phân biệt doanh thu đã ủy quyền và doanh thu đã quyết toán (pipeline bản tin AI hàng ngày), và các câu hỏi tuân thủ quanh việc lẫn lộn tài khoản cá nhân/doanh nghiệp — một cạm bẫy có thật — được đề cập trong bài tổng hợp tuân thủ của chúng tôi.

Bạn muốn một tầng thanh toán tự đối soát?

MERSO IT xây dựng tích hợp cổng thanh toán với IPN đã xác minh, handler idempotent và khớp quyết toán hàng ngày — và với những dự án phù hợp, chúng tôi demo quy trình lõi trước khi bạn thanh toán bất kỳ khoản nào.

Trao đổi với Mersoid, AI tư vấn của chúng tôi