Phần mềm bán hàng

Tích Hợp Thanh Toán SEPAY: Tự Động Xác Nhận Chuyển Khoản QR Tại Điểm Bán

10 phút đọc4 lượt xem
Tích Hợp Thanh Toán SEPAY: Tự Động Xác Nhận Chuyển Khoản QR Tại Điểm Bán

SEPAY cho phép tự động xác nhận thanh toán chuyển khoản ngân hàng tức thì thông qua webhook, loại bỏ hoàn toàn việc nhân viên phải kiểm tra thủ công. WinSell đã tích hợp SEPAY vào module POS của nền tảng bán hàng — đây là hướng dẫn kỹ thuật từ kinh nghiệm thực tế.

SEPAY Là Gì Và Tại Sao Cần Tích Hợp?

SEPAY là dịch vụ tự động đọc và xử lý biến động số dư tài khoản ngân hàng theo thời gian thực. Thay vì nhân viên phải mở ứng dụng ngân hàng, kiểm tra từng giao dịch, rồi xác nhận thủ công — SEPAY nhận thông báo từ ngân hàng và gửi webhook đến hệ thống của bạn ngay lập tức khi có tiền về.

Vấn đề với quy trình thủ công:

Khách hàng chuyển tiền → nhân viên kiểm tra app ngân hàng → tìm đúng giao dịch → xác nhận trong hệ thống → mở khóa đơn hàng. Cả quy trình mất 2–5 phút mỗi đơn. Với POS bận rộn trong giờ cao điểm, 30 khách/giờ × 3 phút = 90 phút lãng phí thuần túy. Chưa kể sai sót do nhân viên xác nhận nhầm hoặc bỏ sót.

Với SEPAY:

Khách quét QR → chuyển tiền → trong vòng 3–5 giây, hệ thống tự nhận webhook → tự xác nhận đơn hàng → in hóa đơn. Nhân viên không cần làm gì.

Kiến Trúc Tích Hợp SEPAY

Bước 1 — Xác Thực OAuth

Trước khi nhận webhook, cần kết nối tài khoản SEPAY với hệ thống qua OAuth 2.0:

  • Merchant đăng nhập SEPAY Dashboard, tạo ứng dụng và lấy client_id + client_secret
  • Hệ thống của bạn redirect merchant đến URL OAuth của SEPAY
  • Sau khi merchant đồng ý, SEPAY redirect về callback URL với authorization_code
  • Đổi code lấy access_token và lưu vào database (mã hóa AES-256)
  • Token có thể dùng để gọi SEPAY API thay mặt cho merchant

Lưu ý quan trọng: access_token hết hạn định kỳ — hệ thống cần implement refresh token flow để tự gia hạn mà không cần merchant đăng nhập lại.

Bước 2 — Đăng Ký Webhook URL

Sau khi có access_token, gọi SEPAY API để đăng ký webhook endpoint:

Endpoint của bạn sẽ nhận POST request mỗi khi có giao dịch. SEPAY hỗ trợ hai cơ chế xác thực webhook:

Cơ chế 1 — API Key trong header:

SEPAY gửi header Authorization: Apikey YOUR_WEBHOOK_SECRET. Backend kiểm tra header này để xác nhận request đến từ SEPAY, không phải từ bên ngoài giả mạo.

Cơ chế 2 — HMAC-SHA256 signature:

SEPAY ký request body bằng HMAC-SHA256 với shared secret. Backend tính lại chữ ký và so sánh. Đây là cơ chế an toàn hơn vì ngay cả khi secret bị lộ trong log, attacker không giả mạo được request nếu không có khả năng tính HMAC đúng.

WinSell triển khai cả hai cơ chế — API Key cho simplicity, HMAC-SHA256 cho merchant có yêu cầu bảo mật cao hơn.

Bước 3 — Xử Lý Webhook Payload

Khi có tiền vào tài khoản, SEPAY gửi payload dạng JSON:

Các field quan trọng:

  • transferAmount: số tiền chuyển khoản (đơn vị VND)
  • transferType: "in" = tiền vào, "out" = tiền ra
  • transferContent: nội dung chuyển khoản (đây là field quan trọng nhất)
  • accountNumber: số tài khoản nhận tiền
  • transaction_date: thời điểm giao dịch

Quy trình xử lý trong backend:

Nhận webhook → verify chữ ký HMAC-SHA256 (hoặc API Key) → extract transferContent → tìm đơn hàng theo mã trong nội dung → kiểm tra số tiền khớp → cập nhật trạng thái đơn hàng → emit Socket.IO event → POS frontend tự động hiển thị "Đã thanh toán".

Bước 4 — Tài Khoản Ảo (Virtual Account) Tự Học

SEPAY có tính năng tài khoản ảo (VA): mỗi đơn hàng được gán một số tài khoản ảo khác nhau (dù thực ra đều chuyển vào cùng một tài khoản thật). Điều này cho phép đối soát chính xác 100% mà không cần khách hàng nhớ gõ mã đơn hàng vào nội dung chuyển khoản.

Khi không dùng VA: khách phải gõ đúng mã đơn hàng vào ô "nội dung chuyển khoản". Nếu gõ sai hoặc để trống → hệ thống không match được → nhân viên phải xác nhận thủ công.

Khi dùng VA: khách quét QR với số tài khoản ảo riêng → SEPAY tự map về đúng đơn hàng → không cần gõ gì.

WinSell implement VA flow cho merchant có nhu cầu loại bỏ hoàn toàn xác nhận thủ công.

Đối Soát Theo Mã Nội Dung Chuyển Khoản

Với merchant không dùng VA (phổ biến hơn), đối soát dựa trên nội dung chuyển khoản:

Quy tắc sinh mã: Mỗi đơn hàng được gán mã ngắn, dễ đọc, ít ký tự đặc biệt. Ví dụ: WS-20250601-0042. Mã này in lên QR code và nhắc khách gõ vào nội dung.

Quy tắc match: Backend dùng regex tìm mã trong transferContent. Không cần match 100% chính xác — "WS 20250601 0042" hay "ws-20250601-0042" đều được nhận dạng đúng nhờ normalize trước khi so sánh.

Xử lý edge case:

  • Số tiền không khớp: đánh dấu "cần xác nhận thủ công", không tự confirm
  • Không tìm thấy mã đơn: ghi log, alert admin, không tự confirm
  • Chuyển khoản trùng (duplicate webhook): idempotency check bằng transaction ID của SEPAY
  • Chuyển khoản nhiều lần cho cùng một đơn: detect và xử lý hoàn tiền thừa nếu tổng vượt giá trị đơn

WinSell Tích Hợp SEPAY Như Thế Nào Trong Module POS?

WinSell Platform (sản phẩm SaaS quản lý bán hàng) tích hợp SEPAY trực tiếp vào module POS:

Luồng tại quầy:

  • Nhân viên tạo đơn hàng trên màn hình POS
  • Chọn phương thức thanh toán "Chuyển khoản QR"
  • Hệ thống hiển thị QR code với số tài khoản + mã đơn hàng + số tiền
  • Màn hình POS chuyển sang chế độ "Chờ thanh toán" với countdown timer
  • Khi SEPAY webhook đến: màn hình tự động chuyển sang "Đã thanh toán" và in hóa đơn
  • Nếu quá 5 phút không nhận webhook: chuyển về màn hình ban đầu, đơn hàng giữ nguyên trạng thái "chờ"

Hệ thống đối soát cuối ngày:

Dashboard báo cáo tổng hợp: tổng giao dịch SEPAY trong ngày, giao dịch tự xác nhận, giao dịch cần xác nhận thủ công, và giao dịch không match được đơn hàng nào (chuyển nhầm hoặc nhầm mã).

So Sánh: Thủ Công Vs. Tích Hợp SEPAY

Xác nhận thủ công:

  • Thời gian mỗi giao dịch: 2–5 phút
  • Tỷ lệ sai sót: 1–3% (nhân viên mệt, quên, nhầm)
  • Yêu cầu nhân lực: 1 người chuyên kiểm tra giao dịch trong giờ bận
  • Báo cáo đối soát: tổng hợp thủ công cuối ngày

Tích hợp SEPAY tự động:

  • Thời gian mỗi giao dịch: 3–5 giây
  • Tỷ lệ sai sót: 0% (với VA) hoặc <0.5% (với mã nội dung)
  • Yêu cầu nhân lực: 0
  • Báo cáo đối soát: real-time, tự động

Câu Hỏi Thường Gặp

SEPAY hỗ trợ những ngân hàng nào?

SEPAY hiện hỗ trợ hầu hết ngân hàng thương mại lớn tại Việt Nam: Vietcombank, VietinBank, BIDV, Techcombank, MB, ACB, Sacombank, TPBank, VPBank và nhiều ngân hàng khác. Danh sách đầy đủ và cập nhật nhất trên website sepay.vn.

Chi phí tích hợp SEPAY là bao nhiêu?

Phí của SEPAY tính theo số giao dịch (xem trên sepay.vn để biết gói hiện tại). Chi phí lập trình tích hợp vào hệ thống có sẵn: 3–5 ngày công = 3–5 triệu đồng tại WinSell, tùy độ phức tạp của hệ thống cần tích hợp.

Có thể dùng SEPAY cho thanh toán đặt cọc không?

Có. Quy trình tương tự — tạo đơn với số tiền bằng giá trị đặt cọc, gán mã, khách chuyển khoản, hệ thống tự xác nhận và đánh dấu trạng thái "đã cọc".

Hệ thống có hoạt động được khi SEPAY bảo trì không?

Nên có fallback: khi không nhận được webhook trong X phút, hệ thống chuyển sang chế độ "xác nhận thủ công tạm thời." WinSell implement fallback này trong module POS để đảm bảo quầy không bị tắc.

Liên Hệ Tích Hợp SEPAY Vào Hệ Thống Của Bạn

Xem thêm về toàn bộ giải pháp tại trang dịch vụ phát triển phần mềm theo yêu cầu. Nếu bạn đang cần tư vấn chọn đối tác công nghệ, xem bài outsource hay tự xây đội ngũ phát triển.

Công ty TNHH WinSell (MST 1801831784). Địa chỉ: Số 79 Đường A4, KDC 91B, Phường An Khánh, Quận Ninh Kiều, TP Cần Thơ.

Liên hệ: Zalo / Điện thoại 0817771184 — Email [email protected] — Website winsell.vn — Facebook facebook.com/phanmembanhangwinsell.

Bảo Mật Webhook: Tại Sao Không Dùng IP Whitelist Đơn Thuần?

Một câu hỏi kỹ thuật hay gặp: "Tại sao không chỉ whitelist IP của SEPAY là đủ?"

IP whitelist là lớp bảo vệ đầu tiên nhưng không đủ vì:

  • IP của SEPAY có thể thay đổi khi họ scale infrastructure hoặc đổi provider
  • IP có thể bị spoofed trong một số tình huống networking phức tạp
  • Nếu attacker nằm trong cùng IP range (cloud provider cùng khu vực), whitelist không bảo vệ được

HMAC-SHA256 signature bảo vệ mạnh hơn vì chỉ SEPAY (biết shared secret) mới tạo được chữ ký đúng. Ngay cả khi attacker biết payload format và IP, họ không thể giả mạo được signature mà không có secret key.

Cách verify HMAC-SHA256 trong NestJS:

Nhận request body dạng raw buffer (không parse JSON trước), tính HMAC-SHA256 với shared secret, so sánh với signature trong header. Nếu không match, trả về 401 và không xử lý thêm. Đây là pattern chuẩn — cũng dùng tương tự với Stripe webhooks, GitHub webhooks, và nhiều provider khác.

Xử Lý Các Tình Huống Đặc Biệt Trong Thực Tế

Tình huống 1: Khách chuyển thiếu tiền

Webhook đến với transferAmount thấp hơn orderAmount. Hệ thống không tự confirm, đánh dấu "thiếu X đồng," notify nhân viên xử lý. Không nên tự động reject — khách có thể chuyển bổ sung.

Tình huống 2: Khách chuyển hai lần

Webhook đến lần 2 cho cùng đơn hàng (khách ấn chuyển khoản hai lần do hiểu lầm). Hệ thống detect đơn đã ở trạng thái "đã thanh toán," không double-confirm. Ghi nhận giao dịch thừa để admin hoàn tiền.

Tình huống 3: Webhook đến sau khi đơn đã hủy

Khách chờ lâu không thấy xác nhận, nghĩ lỗi nên hủy đơn và đặt lại. Webhook của đơn cũ đến muộn (do SEPAY retry). Hệ thống phải check trạng thái đơn trước khi confirm, không confirm đơn đã hủy.

Tình huống 4: Duplicate webhook (SEPAY gửi 2 lần)

SEPAY có cơ chế retry khi không nhận được 200 response trong timeout. Backend phải implement idempotency: lưu transaction ID của SEPAY, nếu đã xử lý rồi thì return 200 luôn mà không xử lý lại.

Bốn tình huống trên đều đã được WinSell test và implement handler đầy đủ trong module POS của WinSell Platform. Đây là loại chi tiết hay bị bỏ qua khi implement "happy path" chỉ và gây ra bug production sau khi launch.

Chia sẻ:

Bài viết liên quan