Trong trang này
Webhooks · Payload & Xác thực
Khi có giao dịch khớp điều kiện, QHTech gửi một request POST tới URL webhook của bạn với body là JSON.
#HTTP headers
QHTech đính kèm token của webhook vào hai header (cả hai đều mang cùng một giá trị token bạn đã cấu hình):
POST /your-webhook-endpoint HTTP/1.1
Content-Type: application/json
QHTECH-TOKEN: {token}
Authorization: Apikey {token}
| Header | Giá trị | Dùng để |
|---|---|---|
Content-Type |
application/json |
Định dạng body |
QHTECH-TOKEN |
{token} |
Token bí mật của webhook — dùng để xác thực |
Authorization |
Apikey {token} |
Cùng token, ở dạng header Authorization |
Bạn có thể kiểm tra một trong hai header trên là đủ.
#Cấu trúc payload
{
"transaction_id": "20250812083338000006",
"gateway": "BIDV",
"transactionDate": "2026-06-10 08:33:38",
"accountNumber": "96247100868",
"code": "DH12345",
"content": "DH12345 chuyen tien mua hang",
"transferType": "in",
"transferAmount": 150000,
"referenceCode": "0551dTCO-82LiomOss"
}
#Mô tả field
| Field | Kiểu | Mô tả |
|---|---|---|
transaction_id |
string | null | Mã giao dịch tại QHTech |
gateway |
string | Mã ngân hàng nguồn (ví dụ BIDV) |
transactionDate |
string (Y-m-d H:i:s) |
Thời điểm giao dịch |
accountNumber |
string | Số tài khoản ngân hàng nhận/phát sinh giao dịch |
code |
string | null | Mã thanh toán trích được từ nội dung chuyển khoản (theo cấu trúc mã của bạn). null nếu không trích được |
content |
string | Nội dung / diễn giải giao dịch (nguyên văn từ ngân hàng) |
transferType |
string | in = tiền vào · out = tiền ra |
transferAmount |
int | Số tiền (VND) |
referenceCode |
string | null | Mã tham chiếu của ngân hàng (core reference) |
codedùng để làm gì? Nếu bạn đặt nội dung chuyển khoản là mã đơn hàng (ví dụ khi sinh QR vớimemo=DH12345), QHTech sẽ tự trích mã đó vào fieldcode— giúp bạn khớp giao dịch với đúng đơn hàng. Cấu trúc mã được cấu hình ở Cài đặt → Cấu trúc mã thanh toán.
#Xác thực request đến từ QHTech
Webhook công khai trên Internet, nên bạn phải kiểm tra mỗi request có đúng là do QHTech gửi không, bằng cách so sánh token trong header với token bạn đã cấu hình cho webhook.
QHTech dùng cơ chế shared token (không ký HMAC). Vì token được gửi trong header dạng plaintext, hãy luôn dùng HTTPS cho URL webhook để tránh lộ token trên đường truyền.
PHP (Laravel controller)
public function handle(Request $request)
{
$expected = config('services.qhtech.webhook_token'); // token bạn đã cấu hình
// Chấp nhận 1 trong 2 header
$token = $request->header('QHTECH-TOKEN')
?? str_replace('Apikey ', '', (string) $request->header('Authorization'));
if (! hash_equals($expected, (string) $token)) {
return response()->json(['success' => false], 401);
}
$data = $request->all();
// Chỉ xử lý tiền vào, ví dụ:
if ($data['transferType'] === 'in') {
// TODO: khớp đơn hàng theo $data['code'] và cộng tiền
}
return response()->json(['success' => true]); // HTTP 200
}
Node.js (Express)
app.post("/qhtech/webhook", express.json(), (req, res) => {
const expected = process.env.QHTECH_WEBHOOK_TOKEN;
const auth = req.get("authorization") || "";
const token = req.get("qhtech-token") || auth.replace("Apikey ", "");
if (token !== expected) {
return res.status(401).json({ success: false });
}
const data = req.body;
if (data.transferType === "in") {
// TODO: khớp đơn hàng theo data.code và cộng tiền
}
return res.json({ success: true }); // HTTP 200
});
Tiếp theo: quy tắc phản hồi, cơ chế retry và xem log.