Giao dịch theo sự kiện

Webhook biến động số dư ngân hàng

Nhận HTTP POST khi có giao dịch mới, xác thực header signature và xử lý thanh toán ngay trong hệ thống của bạn.

HTTP POST · JSON

Luồng webhook

Khi tài khoản phát sinh giao dịch, Thuê API Bank gửi payload JSON đến URL bạn đã đăng ký. Endpoint kiểm tra chữ ký, lưu giao dịch và trả HTTP 200 để xác nhận đã nhận.

1Giao dịch mớiNgân hàng ghi nhận tiền vào

2POST webhookHệ thống gửi JSON + signature

3HTTP 200Ứng dụng xác nhận đã nhận

Cấu hình endpoint

  1. 1
    Tạo URL HTTPS công khai

    Ví dụ https://example.com/webhooks/bank. URL không nên chuyển hướng.

  2. 2
    Thêm Webhook URL

    Đăng nhập hệ thống, chọn Webhooks và gắn URL với tài khoản cần nhận giao dịch.

  3. 3
    Lưu signature bí mật

    Lưu giá trị được cấp trong biến môi trường phía máy chủ.

  4. 4
    Gửi dữ liệu kiểm thử

    Dùng chức năng kiểm thử để xác minh endpoint trả mã 200.

Payload giao dịch

Phương thứcPOST
Content-Typeapplication/json
Headersignature: YOUR_SECRET
{
  "status": "success",
  "message": "Thành công",
  "transactions": [
    {
      "type": "IN",
      "transactionID": "24213",
      "amount": "100000",
      "description": "DH1024 THANH TOAN"
    }
  ]
}
TrườngKiểuMô tả
typestringLoại giao dịch IN hoặc OUT.
transactionIDstringMã giao dịch dùng để chống xử lý trùng.
amountstring/numberSố tiền giao dịch.
descriptionstringNội dung chuyển khoản.

Xác thực header signature

So sánh signature nhận được với secret đã lưu bằng hàm so sánh constant-time. Không ghi secret vào log hoặc source code.

<?php
header('Content-Type: application/json; charset=utf-8');

$secret = $_ENV['THUE_API_BANK_WEBHOOK_SECRET'];
$signature = $_SERVER['HTTP_SIGNATURE'] ?? '';
$rawBody = file_get_contents('php://input');

if (!hash_equals($secret, $signature)) {
    http_response_code(401);
    echo json_encode(['status' => false]);
    exit;
}

$payload = json_decode($rawBody, true, flags: JSON_THROW_ON_ERROR);
foreach ($payload['transactions'] ?? [] as $transaction) {
    // Lưu transactionID với UNIQUE INDEX trước khi xử lý đơn hàng.
}

http_response_code(200);
echo json_encode(['status' => true, 'msg' => 'OK']);

Phản hồi và cơ chế gửi lại

Endpoint cần trả mã HTTP 200 sau khi đã lưu giao dịch. Nếu timeout hoặc trả mã khác 200, hệ thống sẽ thử gửi lại sau khoảng một phút, tối đa 10 lần.

Phản hồi nhanh

Chỉ xác thực và lưu sự kiện trong request webhook. Tác vụ nặng như gửi email, xuất hóa đơn hoặc gọi dịch vụ khác nên đưa vào hàng đợi.

Chống xử lý giao dịch trùng

Webhook có cơ chế retry nên cùng một transactionID có thể được gửi nhiều lần. Hãy đặt unique index trong cơ sở dữ liệu và chỉ hoàn tất đơn ở lần ghi đầu tiên.

CREATE TABLE bank_transactions (
  transaction_id VARCHAR(100) PRIMARY KEY,
  amount DECIMAL(18, 2) NOT NULL,
  description TEXT,
  received_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);