Bỏ qua menu, tới nội dung
Thành viên The MONA Group
Thành viên The MONA Group
Sản phẩm và viết theo yêu cầu
1900 636 648Tư vấn miễn phí, 8h–22h
MONA OS 2.0Hệ thống quản trị MONA tự phát triển, nối 7 phần mềm nội bộ về một dữ liệu, có Gấu Quản Trị trả lời câu hỏi điều hành.7 phần mềm1 trục dữ liệu8 AI AgentXem MONA OS hoạt động
Dự án giáo dụcThe IELTS WorkshopPhần mềm quản lý chuỗi 11 cơ sở luyện thi, kèm app cho học viên20238 tháng12 ngườiXem hồ sơ dự án Xem thêm dự án Khoa Y
Dự án bán lẻHình minh hoạ gấu MONA bán trang sức tại quầy kính, cạnh màn hình bán hàng và tồn khoNgọc Thành JewelryPhần mềm quản lý chuỗi cửa hàng trang sức, tích hợp xuất hoá đơn20246 tháng7 ngườiXem hồ sơ dự án
Dự án sản xuấtHình minh hoạ gấu MONA hướng dẫn công nhân học bài trên phần mềm đào tạo trong phòng họp nhà máyPolytex Far Eastern Việt NamPhần mềm đào tạo công nhân viên chạy trong mạng nội bộ nhà máy20234 tháng8 ngườiXem hồ sơ dự án
Dự án nhân sựHình minh hoạ gấu MONA đứng lớp đào tạo cho bác sĩ, điều dưỡng bằng phần mềm học trực tuyếnBệnh viện Hoàn Mỹ Sài GònViệc đào tạo nhân sự chuyển từ Excel sang phần mềm MONA viết riêng20247 tuần13 moduleXem hồ sơ dự án
Sản phẩm có sẵnHình minh hoạ gấu MONA phục vụ bàn, khách quét mã QR trên bàn để gọi mónnhahang.aiGọi món tại bàn bằng mã QR, kết nối bếp, quản lý bàn, định lượng nguyên liệuNhà hàngQuán ănChuỗi ăn uốngXem nhahang.ai
Sản phẩm có sẵnMONA HouseTự lập hoá đơn tiền phòng, gửi mã QR qua Zalo, báo có khi khách chuyển khoảnNhà trọCăn hộ cho thuêXem MONA House
Sản phẩm có sẵnMONA NHTQĐặt hàng Taobao, 1688, Tmall, ví khách hàng và theo dõi vận đơn cho công ty nhập hàngTaobao1688TmallXem MONA NHTQ
Tư vấn miễn phí, 8h–22h mỗi ngày
Bán hàng và thanh toán

Webhook thanh toán: cách tích hợp cho web, phần mềm Việt Nam

Webhook thanh toán giúp web không bỏ sót chuyển khoản: xác thực HMAC, chống trùng, tự động đối soát. Xem thêm code PHP, Node, Python thực tế từ MONA Pay.

MONA Software biên soạnCập nhật · Đăng · 20 phút đọc

Webhook thanh toán: cách tích hợp cho web, phần mềm Việt Nam

Webhook thanh toán là yêu cầu HTTP POST được hệ thống nhận tiền gửi sang web hoặc phần mềm ngay khi ngân hàng ghi nhận giao dịch. Làm sao để tích hợp webhook mà không ghi trùng đơn? Đầu nhận phải kiểm dấu thời gian, xác thực HMAC trên raw body, trả HTTP 200 rồi đưa dữ liệu vào hàng đợi. Làm đúng thứ tự này, đội dev có một luồng tự động xác nhận chuyển khoản theo thời gian thực và còn đường đối soát khi máy chủ gián đoạn. Tụi em từng làm việc này. Từ năm 2022, kiến trúc đó đã nhận biến động ACB cho phần mềm MONA; tụi em sau đó mới đóng gói thành MONA Pay và mở công khai ngày 29/08/2026. Phần dưới đi thẳng vào payload 7 trường, code PHP, Node, Python, 5 lỗi tụi em đã gặp, retry, đối soát 15 phút và cách thử sandbox không tốn tiền.

Webhook thanh toán là gì dưới góc nhìn của đội dev MONA?

Một khách chuyển khoản xong, phần mềm bán hàng cần biết tiền đã tới mà không chờ người mở ứng dụng ngân hàng. Webhook thanh toán làm đúng việc đó: nguồn phát chủ động đẩy một sự kiện tới URL do đội dev khai báo, thay vì đầu nhận liên tục hỏi xem có giao dịch mới chưa. Với webhook thanh toán, sự kiện mang số tiền, nội dung, thời gian, mã giao dịch và tài khoản nhận. Hiểu vậy là đủ.

Video hướng dẫn: Tích hợp webhook thanh toán MONA Pay trong 5 phút. Tài liệu chi tiết và các bước làm theo tại monapay.vn.

MONA Pay là API ngân hàng và dịch vụ xác nhận thanh toán tự động của The MONA Group, giúp doanh nghiệp Việt Nam nhận và xác nhận tiền chuyển khoản theo thời gian thực qua tài khoản ảo (VA), VietQR, webhook và Telegram, thiết kế để cả lập trình viên lẫn AI agent tích hợp trong vài phút. Tiền đi thẳng vào tài khoản ngân hàng đứng tên doanh nghiệp, còn MONA Pay nhận tin báo có rồi chuyển tiếp sự kiện. Hệ thống không cần mật khẩu ngân hàng và không có quyền rút tiền. Ngày 29/08/2026, tụi em mở MONA Pay công khai sau hơn 4 năm dùng luồng nhận báo có ACB trong phần mềm, và hơn 14.000 dự án của cả tập đoàn cho tụi em đủ ca thực tế để chốt các lớp phòng vệ.

Tài liệu webhook thanh toán và API dành cho lập trình viên
Tài liệu MONA Pay tách riêng phần nhận webhook thanh toán, bảo mật, gửi lại và đối soát.

Khác biệt này ảnh hưởng trực tiếp tới kiến trúc web. Khi nhân viên đọc sao kê, trạng thái đơn nằm trong đầu một người; khi webhook thanh toán đi vào phần mềm, trạng thái nằm trong cơ sở dữ liệu và mọi khâu sau đó dùng chung một bản ghi. Đội dev MONA đã áp dụng cách thứ hai cho phần mềm giao khách từ năm 2022, trước lúc MONA Pay có tên và có bảng giá công khai. Anh chị đang xây phần mềm quản lý đơn hàng hoặc đọc bài API ngân hàng cho phần mềm bán hàng sẽ thấy đây là lớp dữ liệu nối tiền với nghiệp vụ, nên kiến trúc cần được chọn đúng từ đầu. Mốc vận hành từ năm 2022 cũng là lý do tụi em ưu tiên log và đối soát thay vì chỉ nhìn một lần callback thành công.

Thành phầnViệc phải làmDữ kiện cần giữĐiều kiện đạt
Ngân hàng và MONA PayGhi nhận tiền vào, tạo sự kiệnMã giao dịch, số tiền, tài khoản nhậnGiao dịch xuất hiện trong dashboard
Sender webhook thanh toánPOST payload tới URL đã khai báoRaw body, timestamp, chữ kýNhận 200, 201 hoặc 202 trong 10 giây
Receiver webhook thanh toánKiểm thời gian và HMACtransaction_code UNIQUEKhông nhận gói sai chữ ký hoặc trùng mã
Hàng đợi nghiệp vụKhớp đơn, gửi email, cập nhật khoTrạng thái xử lý và log lỗiChạy độc lập sau phản hồi HTTP

Kiến trúc webhook thanh toán chuẩn bắt đầu bằng raw body

Tụi em hay vẽ luồng này thành 5 ô: ngân hàng ghi nhận tiền, MONA Pay lưu giao dịch, webhook thanh toán POST tới endpoint, endpoint xác minh, hàng đợi xử lý đơn. Dấu thời gian trong X-Mona-Timestamp phải được kiểm trước để loại gói lệch quá 300 giây. Tiếp theo, máy chủ lấy đúng raw body từng byte và tính HMAC-SHA256 bằng secret riêng của cấu hình. Sau khi chữ ký khớp, endpoint trả 200 trong giới hạn 10 giây.

Thứ tự đó rất đáng giữ, vì tác vụ khớp đơn có thể đụng cơ sở dữ liệu, kho, CRM và dịch vụ gửi mail trong cùng một lượt. Chỉ một API phía sau chậm 12 giây là MONA Pay ghi nhận TIMEOUT, dù tiền đã vào và chữ ký đã đúng. Trả lời trước giúp kênh giao nhận sự kiện kết thúc nhanh; hàng đợi mới chịu trách nhiệm chạy lại tác vụ nghiệp vụ. Đừng đảo chỗ.

Wizard nhập URL HTTPS nhận webhook thanh toán MONA Pay
Bước đầu của wizard yêu cầu URL đích cuối, tránh redirect làm lần gửi bị đánh dấu thất bại.

Payload mặc định có 7 trường và giữ cấu trúc phẳng để hệ thống cũ cũng đọc được. amount là số nguyên VND; description giữ nội dung chuyển khoản; transfer_date dùng giờ Việt Nam; transaction_code là khóa chống trùng; account_number là VA hoặc tài khoản nhận; bank_name cho biết ngân hàng; type hiện mang giá trị income. Code cần bỏ qua trường lạ trong tương lai, nhưng phải từ chối kiểu dữ liệu sai ở 7 trường đang dùng để tạo ra ranh giới dễ kiểm.

TrườngVí dụDùng để làm gìQuy tắc đầu nhận
amount2500000So với số tiền đơnSố nguyên VND, không có phần thập phân
descriptionDH10234Khớp mã khi không dùng VA riêngChuẩn hóa để tìm, vẫn lưu bản gốc
transfer_date10:30:00 28/08/2026Đối chiếu thời điểm ngân hàng báoKhông đưa thẳng vào new Date()
transaction_codeFT26240001234IdempotencyĐặt UNIQUE ở cơ sở dữ liệu
account_numberMONA0000010234Nhận diện VA hoặc đơnLưu dạng chuỗi
bank_nameACBChọn bộ quy tắc theo ngân hàngKhông hard-code một giá trị duy nhất
typeincomePhân loại tiền vàoBỏ qua loại chưa hỗ trợ

Trong dự án theo mô hình MVC, receiver chỉ làm phần xác minh và chuyển payload sang service; controller mỏng giúp kiểm thử lỗi rõ hơn. Phần lưu giao dịch nên có migration tạo chỉ mục UNIQUE, đọc thêm cách tổ chức dữ liệu ở bài SQL là gì. Còn tác vụ đổi trạng thái đơn phải gọi cùng một hàm cho cả webhook thanh toán lẫn đối soát, để hai đường dữ liệu chỉ có một nguồn xử lý.

Tích hợp webhook thanh toán và xác thực HMAC bằng PHP, Node, Python

Ba đoạn dưới giữ cùng một thứ tự: đọc raw body, kiểm cửa sổ 5 phút, xác thực webhook HMAC bằng so sánh thời gian cố định, trả 200 rồi mới chuyển dữ liệu webhook thanh toán sang hàng đợi. Tụi em giữ cửa sổ đó ở 300 giây và đặt trần phản hồi 10 giây cho cả ba SDK. Secret nằm trong biến môi trường MONA_WEBHOOK_SECRET, tách khỏi client_secret dùng để gọi API MONA Pay vì hai khóa có công việc khác nhau. Đừng lưu chúng trong Git.

Wizard chọn xác thực webhook HMAC SHA256 và secret
Secret HMAC thuộc riêng cấu hình webhook thanh toán và phải nằm ngoài mã nguồn của dự án.

Mẫu PHP thuần kiểm HMAC trên raw body

PHP thuần đọc trực tiếp php://input, nên đoạn receiver khá ngắn nhưng raw body phải nguyên vẹn. Sau phản hồi, fastcgi_finish_request() đóng kết nối với sender trước khi ứng dụng đưa giao dịch sang worker. Ở WordPress hoặc Laravel, vẫn lấy body gốc từ request thay vì mã hóa lại mảng đã parse.

<?php
$secret = getenv('MONA_WEBHOOK_SECRET');
$raw = file_get_contents('php://input');
$timestamp = $_SERVER['HTTP_X_MONA_TIMESTAMP'] ?? '';
$signature = $_SERVER['HTTP_X_MONA_SIGNATURE'] ?? '';

if (abs(time() - (int) $timestamp) > 300) {
    http_response_code(400); exit('timestamp qua han');
}

$expected = 'sha256=' . hash_hmac('sha256', $timestamp . '.' . $raw, $secret);
if (!hash_equals($expected, $signature)) {
    http_response_code(401); exit('sai chu ky');
}

http_response_code(200); echo 'OK';
if (function_exists('fastcgi_finish_request')) fastcgi_finish_request();
$payload = json_decode($raw, true);
queue_transaction($payload);

Mẫu Node dùng SDK @monapay/node 0.4.0

SDK Node nhận raw body của webhook thanh toán dưới dạng Buffer và kiểm hai header bằng hàm verifyWebhook. Route này phải đặt express.raw() trước middleware express.json(), nếu không body đã bị biến thành object. Dot notation giữ nguyên để dev copy vào Express rồi đọc tiếp. Ở route production, tụi em còn đặt cảnh báo khi thời gian phản hồi p95 vượt 1 giây.

import express from 'express';
import { verifyWebhook } from '@monapay/node';

const app = express();

app.post('/webhooks/monapay', express.raw({ type: 'application/json' }), async (req, res) => {
  const result = verifyWebhook({
    rawBody: req.body,
    headers: req.headers,
    secret: process.env.MONA_WEBHOOK_SECRET
  });

  if (!result.ok) return res.status(401).send(result.reason);
  res.sendStatus(200);

  await queue.add('monapay', {
    transactionCode: result.payload.transaction_code,
    payload: result.payload
  });
});

Mẫu Python dùng gói monapay trên PyPI

FastAPI đọc bytes của webhook thanh toán bằng await request.body(), sau đó thư viện monapay trả kết quả đã kiểm timestamp và chữ ký. BackgroundTasks đủ cho ví dụ ngắn; hệ thống có tải nên chuyển sang Redis, RabbitMQ hoặc hàng đợi đang có. Phần worker vẫn dựa vào UNIQUE transaction_code.

import os
from fastapi import BackgroundTasks, FastAPI, Request, Response
from monapay import verify_webhook

app = FastAPI()

@app.post('/webhooks/monapay')
async def monapay_webhook(request: Request, tasks: BackgroundTasks):
    raw_body = await request.body()
    result = verify_webhook(
        raw_body,
        request.headers,
        os.environ['MONA_WEBHOOK_SECRET']
    )
    if not result.ok:
        return Response(content=result.reason, status_code=401)
    tasks.add_task(process_transaction, result.payload)
    return Response(status_code=200)

Đội dev đang làm lập trình web app cho khách có thể giữ ba mẫu trên làm contract test webhook thanh toán. Tạo một raw body cố định, ký bằng secret test, rồi chạy ca chữ ký đúng, chữ ký sai, timestamp quá hạn và cùng transaction_code gửi hai lần. Bài kiểm thử phần mềm giải thích sâu hơn cách tách dữ liệu test khỏi môi trường thật. Bốn ca này phải xanh trước khi nối tiền.

Năm lỗi thật khi dev nối webhook thanh toán và cách sửa

Từ năm 2022, tụi em đã gặp lại đúng 5 lỗi ở các đầu nhận tiền vào phần mềm: parse JSON rồi ký lại, thiếu UNIQUE cho mã giao dịch, URL còn redirect 301, xử lý nặng trước phản hồi 200 và giờ máy chủ bị lệch. Mỗi lỗi nhìn riêng đều nhỏ; đặt vào đường tiền, nó biến thành đơn treo, đơn ghi hai lần hoặc log đỏ hàng loạt. Đội nhận bàn giao thường chỉ thấy triệu chứng sau cùng. Sửa từ gốc.

Wizard chọn định dạng JSON cho webhook chuyển khoản
Định dạng JSON tiện cho framework hiện đại, nhưng chữ ký vẫn tính trên chuỗi body nguyên bản.

Lỗi parse trước khi ký xuất hiện nhiều ở Express, Next.js và Laravel vì middleware chạy sẵn. JSON được parse rồi serialize lại có thể đổi thứ tự khóa, khoảng trắng hoặc cách escape Unicode, nên HMAC khác dù dữ liệu nhìn bằng mắt vẫn giống nhau. URL redirect cũng dễ lọt qua lúc test bằng trình duyệt, vì trình duyệt tự đi theo 301; sender webhook thanh toán không đi tiếp và gắn nhãn HTTP_3XX. Browser không phải sender, vì vậy thấy nhãn gì phải sửa đúng lớp đó. Tụi em kiểm từng nhãn ngay trong lịch sử gửi trước khi đụng tới code nghiệp vụ.

Lỗi tụi em đã gặpDấu hiệu trong logNguyên nhânCách sửa dứt điểm
Parse JSON rồi ký lại401, mọi chữ ký đều saiRaw body đã đổi byteLấy body bytes trước middleware JSON
Không UNIQUE transaction_codeMột khoản làm đơn chạy hai lầnGửi lại được xem như giao dịch mớiRàng buộc UNIQUE và insert idempotent
URL redirect 301HTTP_3XXThiếu HTTPS, www hoặc dấu gạch cuốiKhai URL đích cuối trả thẳng 200
Làm việc nặng trước 200TIMEOUT sau 10 giâyKhớp đơn, gửi mail chạy đồng bộTrả 200 rồi đẩy vào hàng đợi
Giờ máy chủ lệch400 timestamp quá hạnNTP tắt hoặc đồng hồ container saiBật NTP, cảnh báo khi lệch trên 60 giây

Ngày 03/09/2026, tụi em đóng vai chủ một tiệm hoa mới đăng ký rồi đi hết wizard webhook thanh toán 5 bước, nối Telegram và bật 2FA để kiểm lại đường người dùng. Một chi tiết đáng nhớ là URL nhìn đúng trong ô nhập vẫn có thể trả 301 nếu máy chủ ép thêm dấu gạch cuối; phải bấm Gửi thử và nhìn chính log mới biết. Secret HMAC được wizard sinh, còn API key nằm ở màn hình khác và chỉ hiện phần bí mật một lần. Ca kiểm đó giúp tài liệu phản ánh đúng thứ dev sẽ bấm.

The MONA Group làm dự án từ năm 2016, đã làm hơn 14.000 dự án, nên tụi em xem bảo trì phần mềm là một phần của thiết kế ban đầu. Webhook thanh toán không kết thúc ở ngày nhận được payload đầu tiên. Endpoint cần log raw body, header, mã phản hồi, thời gian xử lý và trạng thái worker tối thiểu 30 ngày để khi đơn sai còn lần lại được, thay vì debug bằng trí nhớ.

Retry webhook thanh toán và đối soát 15 phút giữ đơn không bị sót

Webhook thanh toán là kênh thời gian thực, còn đối soát là lưới đỡ. MONA Pay ghi mỗi lần gửi với mã HTTP, duration_ms, payload, phần đầu body phản hồi và nhãn như HTTP_4XX, HTTP_5XX, TIMEOUT, SSL, DNS hoặc CONNECTION. Lần lỗi bấm gửi lại được từ dashboard hoặc gọi API gửi lại theo mã giao dịch. Vì vậy, đối soát định kỳ vẫn phải có ngay từ đầu.

Lịch sử giao dịch dùng đối soát webhook chuyển khoản
Mã giao dịch chung giúp webhook thanh toán, lần gửi lại và đối soát gặp nhau ở một bản ghi.

Luồng bán hàng giao ngay, vé hoặc mở khóa học nên chạy đối soát mỗi 15 phút; phần mềm quản lý ít gấp hơn có thể chạy mỗi giờ, kế toán vẫn chốt đủ vào 23:30. Tác vụ gọi GET /api/v1/acb/virtual-account/transactions theo từng VA, lấy tối đa 100 giao dịch mỗi trang và dừng khi cả trang không còn mã mới. Mỗi khoản thiếu được đưa vào đúng hàm worker mà webhook thanh toán đang dùng, không viết hai bộ nghiệp vụ.

Chống trùng nằm ở cơ sở dữ liệu, không nằm trong bộ nhớ tiến trình. Hai worker chạy cùng lúc đều có thể đọc thấy “chưa tồn tại”, nên câu lệnh insert cần UNIQUE transaction_code và xử lý xung đột như một kết quả bình thường. Với MySQL dùng INSERT IGNORE; PostgreSQL dùng ON CONFLICT DO NOTHING. Sau đó cơ sở dữ liệu mới chốt lượt bằng cách khóa hoặc cập nhật đơn theo transaction.

Một quy tắc tụi em giữ khá cứng: webhook thanh toán, retry và đối soát đều gọi một hàm process_transaction(), rồi hàm này tự kiểm idempotency trước khi chạm đơn hàng. Cách làm hợp với luồng công việc có nhiều tác vụ nối nhau và giảm số chỗ cần sửa khi nghiệp vụ đổi. Nếu tiền đã vào dashboard nhưng đơn chưa đổi trạng thái, đội vận hành nhìn được bước nào gãy thay vì chuyển bill qua nhóm chat để đoán. Log phải trả lời được.

Đưa một endpoint thật vào bàn kiểm

Anh chị đã tốn thời gian viết route, dựng bảng giao dịch, cấu hình SSL và nối hàng đợi; đừng đợi tới lúc 800 khoản tiền trong tháng mới phát hiện URL đang redirect hoặc cùng một mã bị ghi hai lần. Gửi MONA endpoint staging, tụi em cùng bắn payload ký HMAC, xem log dưới 10 giây và chạy lại một khoản qua đối soát 15 phút.

Tạo MONA Pay và thử webhook thanh toán Gọi 1900 636 648

Wizard 5 bước rút ngắn cấu hình webhook thanh toán

Dashboard chia cấu hình webhook thanh toán thành 5 bước rõ ràng: đặt tên và URL HTTPS, chọn phạm vi mọi tài khoản hoặc một VA, chọn HMAC-SHA256, chọn JSON hoặc dạng form, rồi kiểm lại trước khi lưu. Tụi em đã bấm Gửi thử, mở Lịch sử gửi và xác nhận mã 200 cùng thời gian phản hồi dưới 1 giây trên chính luồng này. Nhãn HTTP_3XX buộc sửa URL đích; nhãn TIMEOUT buộc tách việc nặng khỏi request, vì wizard không che lỗi và dev nhìn được từng bước.

API key và lệnh MCP cho AI agent tích hợp webhook
Màn hình API Keys đưa sẵn client credentials để agent cấu hình webhook thanh toán đúng luồng.

Luồng AI agent làm webhook thanh toán bắt đầu tại my.monapay.vn → API Keys → Tạo key. Màn hình hiện sẵn client_id, client_secret và lệnh claude mcp add monapay -e MONAPAY_CLIENT_ID=… -e MONAPAY_CLIENT_SECRET=… -- npx -y monapay-mcp. Bản MCP 0.4.0 có 34 tools, gồm cả cấu hình webhook, Telegram, email và giao dịch sandbox; agent tự gọi POST /api/v1/oauth/token với client credentials để lấy token, không cầm username hoặc mật khẩu. Cách này vẫn chạy khi tài khoản bật 2FA.

Sau khi có token, agent nối ngân hàng bằng 2 lượt OTP ngay trong khung chat: bắt đầu đăng ký VA, hỏi mã ngân hàng gửi tới điện thoại, xác minh, đăng ký nhận thông báo rồi hỏi OTP lần hai. Agent không tự đoán mã và không lưu mật khẩu ngân hàng. Khi ngân hàng đã nối, POST /api/v1/sandbox/transactions tạo giao dịch giả để phát qua webhook thanh toán, Telegram và email mà không tính hạn mức gói. Thử sạch trước.

Dashboard MONA Pay theo dõi bước tích hợp webhook
Danh sách kích hoạt cho thấy ngân hàng, webhook thanh toán, Telegram và API key đã hoàn tất hay chưa.

Ba prompt ngắn dưới đây đủ giao việc webhook thanh toán ban đầu cho agent, rồi dev review pull request như mọi thay đổi liên quan tiền. Prompt một: “Đọc monapay.vn/llms-full.txt, tạo endpoint POST /webhooks/monapay, kiểm HMAC trên raw body, từ chối timestamp lệch 300 giây và viết test chữ ký đúng, sai.” Prompt hai: “Đặt transaction_code UNIQUE, trả 200 trước khi chạy nghiệp vụ, bỏ qua DUMMY123 và ghi log amount không khớp đơn.” Prompt ba: “Tạo cron đối soát 15 phút, lấy 100 giao dịch mỗi trang, dùng chung process_transaction với webhook và báo số khoản được bổ sung.” Tài liệu máy đọc nằm ở trang AI agent MONA Pay.

Webhook thanh toán, polling và Telegram hợp với ba việc khác nhau

Webhook thanh toán đẩy sự kiện ngay khi tiền vào, nên nó hợp với đổi trạng thái đơn, giữ chỗ, mở quyền và phát lệnh xuống kho. Polling chủ động hỏi API theo lịch 15 phút hoặc 1 giờ, chậm hơn nhưng kiểm soát được nhịp tải và rất hữu ích cho đối soát. Telegram báo cho con người trong nhóm hoặc topic, không thay cho bản ghi cơ sở dữ liệu vì không kênh nào ôm hết việc. Ba kênh đứng cạnh nhau.

Telegram nhận thông báo tiền vào theo nhóm và topic
Telegram giúp người vận hành nhìn thấy tiền vào, còn webhook thanh toán cập nhật phần mềm theo quy tắc.

Tụi em thường cấu hình cả ba: webhook thanh toán chạy thời gian thực, cron đối soát mỗi 15 phút, Telegram báo cho nhóm vận hành biết. Khi endpoint lỗi 8 phút trong một lần deploy, Telegram vẫn giúp người trực thấy khoản tiền, còn cron bổ sung bản ghi thiếu sau khi máy chủ sống lại. Một kênh hỏng không làm cả hệ thống mù và tạo ra dự phòng có mục đích.

KênhĐộ trễĐiểm mạnhChỗ phải bùDùng cho
Webhook thanh toánGần thời gian thựcĐẩy đúng sự kiện, ít request thừaCần endpoint sống và xử lý idempotentĐổi trạng thái đơn, mở quyền
Polling APITheo lịch 15 phút hoặc 1 giờTự kéo lại dữ liệu khi receiver gián đoạnTốn request, có độ trễĐối soát và tác vụ bù
TelegramGần thời gian thựcNhóm vận hành thấy ngay, có topicCon người vẫn phải đọcCảnh báo, kiểm tra nhanh

Hệ thống chỉ thu vài khoản mỗi tháng và chưa có nghiệp vụ sau báo có thì Telegram là điểm bắt đầu gọn. Web bán hàng có kho, CRM và email xác nhận cần webhook thanh toán làm kênh chính. Dù chọn cách nào, phần mềm production vẫn cần polling đối soát vì mạng, SSL và lúc deploy luôn có xác suất gián đoạn. Tụi em không khuyên kéo thả no-code thành đường tiền chính; một node sai cấu hình đủ làm luồng đứng, trong khi đơn vẫn phát sinh. Giao production cho code có log và người chịu trách nhiệm.

Phí đường tiền và lộ trình nhiều ngân hàng cần nói rõ từ đầu

Webhook thanh toán của MONA Pay được thiết kế cho nhiều ngân hàng, nối nhiều tài khoản ở nhiều ngân hàng về một dashboard; ACB đang chạy trực tiếp vì tụi em đã dùng thật với ACB từ năm 2022, các ngân hàng khác đang nối thêm theo lộ trình. Bảng trạng thái được cập nhật tại monapay.vn/ngan-hang. Tiền vẫn vào thẳng tài khoản của anh chị, còn MONA Pay chỉ nhận tin báo.

Bảng giá MONA Pay theo số khoản tiền vào
Gói miễn phí có 500 khoản mỗi tháng, các gói sau tăng theo số khoản chứ không theo doanh thu.

Chữ “miễn phí” của webhook thanh toán chỉ có nghĩa khi đặt cạnh phí của từng đường tiền. Biểu phí thương mại điện tử VietinBank hiệu lực 22/04/2026 ghi thẻ nội địa NAPAS nối trực tiếp ở mức 0,5% tới 0,7%, nối gián tiếp 1,09% cộng 1.818 đồng mỗi giao dịch; thẻ Visa hoặc Mastercard phát hành trong nước là 1,818% tới 2,182% cộng 4.200 đồng. PayPal công bố ngày 28/05/2026 mức 4,40% cộng 0,30 USD, phí rút 60.000 đồng mỗi lần và đổi tiền thêm 4%. Chuyển khoản tự báo có qua MONA Pay là 0% cộng 0 đồng trên từng khoản, và phép tính phải ghi nguồn.

Đường tiềnPhí công bốKhoản cố địnhNguồn, ngày kiểm
Thẻ nội địa NAPAS qua cổng ngân hàng0,5% đến 0,7% trực tiếp; 1,09% gián tiếpGián tiếp cộng 1.818 đồng mỗi giao dịchVietinBank, hiệu lực 22/04/2026, chưa VAT
Visa, Mastercard phát hành trong nước1,818% đến 2,182%4.200 đồng mỗi giao dịchVietinBank, hiệu lực 22/04/2026, chưa VAT
PayPal4,40% cộng 0,30 USDRút 60.000 đồng mỗi lần, đổi tiền 4%PayPal Việt Nam, 28/05/2026
Chuyển khoản tự báo có qua MONA Pay0% cộng 0 đồng mỗi khoảnGói 0 đồng có 500 khoản mỗi thángBảng giá MONA Pay, 03/09/2026; NAPAS và VietQR
Biểu đồ phí thẻ và chuyển khoản tự báo có
Với 200 triệu đồng và 800 khoản, lựa chọn đường tiền tạo chênh lệch hàng triệu đồng mỗi tháng.

Lấy một phần mềm SaaS thu 200 triệu đồng mỗi tháng qua 800 hóa đơn, trung bình 250.000 đồng một khoản. Nếu toàn bộ đi qua thẻ phát hành trong nước ở mức thấp 1,818%, riêng phần trăm là 3.636.000 đồng, cộng 3.360.000 đồng phí cố định, tổng gần 7 triệu đồng và chưa VAT. Chuyển khoản tự báo có kèm webhook thanh toán dùng gói 99.000 đồng cho 2.000 khoản, chênh khoảng 6,9 triệu đồng mỗi tháng và hơn 82 triệu đồng một năm.

Gói Miễn phí có 500 khoản webhook thanh toán mỗi tháng; các mức tiếp theo là 99.000 đồng cho 2.000 khoản, 299.000 đồng cho 10.000, 799.000 đồng cho 50.000 và 1.990.000 đồng cho 300.000, trả năm bằng tiền 10 tháng. Khách đang làm web, phần mềm hoặc hosting tại MONA được miễn phí hoàn toàn trong thời gian còn là khách hàng. Tụi em vẫn giữ cổng thẻ cho khách cần thẻ hoặc bán ra nước ngoài, còn chuyển khoản nội địa đi đường VietQR để giảm phí. Chọn theo người trả tiền.

Webhook thanh toán đi vào bán lẻ, F&B, giáo dục và SaaS

Cùng một payload webhook thanh toán 7 trường, mỗi ngành lại có quy tắc khớp tiền khác nhau. Một shop chạy 50 đơn mỗi ngày, một trung tâm có 300 học viên và một SaaS gia hạn theo 12 tháng vẫn dùng chung receiver nếu contract không đổi. Bán lẻ dùng VA hoặc mã đơn để đổi trạng thái và phát lệnh đóng gói; F&B gắn khoản cọc với bàn hoặc tiệc; giáo dục gắn VA với học viên và kỳ thu; SaaS gắn mã giao dịch với hóa đơn gia hạn. Receiver chung nhưng worker khác, vì nghiệp vụ quyết định phần sau. Tụi em giữ contract chung để sửa lớp bảo mật một lần mà không đụng quy tắc riêng của từng ngành.

Tạo tài khoản ảo để khớp giao dịch theo khách
VA riêng giúp phần mềm biết tiền thuộc đơn hoặc khách nào mà không phải đoán nội dung.

Với phần mềm quản lý bán hàng, worker webhook thanh toán phải đưa đơn sai số tiền sang danh sách kiểm tra, không tự đánh dấu đã thanh toán. Trong phần mềm quản lý nhà hàng, tiền cọc về có thể giữ bàn, nhưng việc khách đổi lịch vẫn để người quản lý duyệt. Một phần mềm thu học phí cần tách học viên, kỳ thu và khoản thừa; còn mô hình SaaS phải ngăn một giao dịch gia hạn hai lần. Máy chỉ chạy quy tắc đã viết.

NgànhKhóa khớpTác vụ sau báo cóCa cần người duyệt
Bán lẻMã đơn hoặc VA của đơnĐổi trạng thái, gửi khoThiếu hoặc thừa tiền
F&BMã đặt bàn, mã tiệcGiữ chỗ, báo thu ngânĐổi lịch sau khi cọc
Giáo dụcVA học viên và kỳ thuGhi học phí, mở quyền họcChuyển sai kỳ hoặc chuyển gộp
SaaSMã hóa đơnGia hạn tài khoảnMột khoản trả nhiều hóa đơn

Tụi em xem webhook thanh toán là một module trong hệ thống lớn hơn, giống cách CRM giữ hồ sơ khách và ERP giữ luồng vận hành. Giao dịch đã xác minh tạo ra sự kiện sạch, còn phần mềm quyết định đổi đơn, cộng công nợ, mở quyền hay chờ người duyệt. Trường hợp chỉ cần nhóm biết tiền vào, Telegram đủ dùng và anh chị chưa cần thuê dev. Trường hợp đã có nhiều trạng thái đơn, hãy tích hợp vào code gốc.

Gán mỗi đơn một số tài khoản ảo giúp webhook khớp đơn chắc hơn đọc nội dung chuyển khoản; cách làm có trong bài tài khoản ngân hàng ảo là gì.

Câu hỏi thường gặp và bước kiểm cuối trước khi nhận tiền thật

Webhook thanh toán là gì nếu phần mềm đang dùng polling?

Nếu đội kỹ thuật còn hỏi webhook là gì, hãy nhìn theo hướng gửi dữ liệu: polling là đầu nhận hỏi API theo lịch, webhook thanh toán là nguồn phát chủ động gửi sự kiện khi có thay đổi. Anh chị giữ polling làm đối soát 15 phút và thêm webhook làm kênh thời gian thực, không cần bỏ một trong hai. Cùng một hàm xử lý giao dịch sẽ nhận dữ liệu từ cả hai đường.

Xác thực webhook HMAC có thay cho đối soát không?

Không. HMAC chứng minh payload webhook thanh toán tới từ bên biết secret và body không bị sửa trên đường truyền; đối soát xác nhận bản ghi của hệ thống anh chị đủ so với sổ MONA Pay. Với giao dịch giá trị lớn, worker còn phải so amount, account_number và trạng thái đơn trước khi giao hàng, vì hai lớp này giải hai rủi ro riêng.

Webhook thanh toán gửi lại có làm đơn chạy hai lần không?

Không, nếu bảng giao dịch đặt UNIQUE cho transaction_code và worker xử lý idempotent. Lần gửi lại giữ nguyên mã, nên insert xung đột được xem là giao dịch đã nhận.

AI agent có cần mật khẩu ngân hàng để tích hợp webhook thanh toán không?

Không cần. Agent dùng client_id và client_secret để đổi lấy token, còn 2 mã OTP nối ngân hàng do chủ tài khoản đọc từ điện thoại và nhập ngay trong phiên chat. Sandbox tạo giao dịch giả sau khi nối VA, không tốn tiền và không tính vào hạn mức. Mật khẩu ngân hàng không đi qua MONA Pay.

Bật xác thực hai lớp trước khi vận hành webhook
TOTP bảo vệ dashboard, còn HMAC bảo vệ từng sự kiện webhook thanh toán gửi sang phần mềm.

Trước khi nhận tiền thật, đội dev chạy đủ 8 mục cho webhook thanh toán:

  1. HTTPS hợp lệ trên đúng domain production.
  2. URL đích cuối không redirect.
  3. Raw body chưa bị middleware parse.
  4. Timestamp lệch dưới 300 giây.
  5. HMAC được so sánh timing-safe.
  6. Endpoint trả HTTP 200 dưới 1 giây.
  7. transaction_code có ràng buộc UNIQUE.
  8. Cron đối soát chạy mỗi 15 phút.

Sau đó bắn DUMMY123, tạo một giao dịch sandbox 10.000 đồng, kiểm log và gửi lại cùng payload để chắc worker không chạy trùng. Bài framework là gì hay ngôn ngữ lập trình là gì không thay cho bài kiểm này; contract phải chạy trên chính ứng dụng sắp nhận tiền. Test rồi mới mở.

Chốt webhook thanh toán trước khi 800 hóa đơn chạy qua

Một redirect 301, một middleware parse JSON sớm hoặc một bảng thiếu UNIQUE đều đủ làm luồng webhook thanh toán sai trong đêm triển khai; phép tính ở trên cho thấy 800 khoản đã tạo chênh gần 6,9 triệu đồng mỗi tháng, nên phần tiết kiệm chỉ có ý nghĩa khi endpoint chạy chắc. Tụi em có thể ngồi cùng đội dev kiểm HMAC, retry và đối soát trên staging.

Tạo MONA Pay, lấy key và bắn sandbox ngay hôm nay. Khách đang dùng web, phần mềm hoặc hosting của MONA được gán gói miễn phí hoàn toàn; đội kỹ thuật cần người rà cùng thì gọi 1900 636 648.

Tạo tài khoản và bắn sandbox Gọi 1900 636 648

Tụi em đã dùng webhook nhận tiền cho phần mềm MONA từ năm 2022, rồi ngày 03/09/2026 tự đi lại trọn wizard 5 bước như một tài khoản mới để kiểm từng chỗ dev sẽ gặp. Một webhook thanh toán đáng đưa vào production phải xác minh raw body, chặn replay 5 phút, phản hồi trong 10 giây, chống trùng bằng transaction_code và có đối soát 15 phút. Anh chị xem code gốc tại hướng dẫn tích hợp webhook, đọc riêng bảo mật HMAC-SHA256 cùng phần gửi lại và xử lý lỗi; cần rà kiến trúc phần mềm hiện có, gọi 1900 636 648 hoặc viết tới [email protected]. Anh chị đã sẵn sàng bắn giao dịch sandbox đầu tiên chưa?