Tài liệu / Tích hợp/ Tích hợp Node.js

Tích hợp Node.js

Tích hợp Cập nhật: 23/03/2026

Tích hợp ThueAPI.VN với Node.js

Xây dựng webhook server với Express, lưu vào database, và push thông báo realtime qua Socket.io.

Cài đặt dependencies

npm install express axios crypto mongoose socket.io dotenv

Cấu hình .env

THUEAPI_KEY=your_api_key_here
THUEAPI_WEBHOOK_SECRET=your_webhook_secret_here
MONGODB_URI=mongodb://localhost:27017/thueapi_app
PORT=3000

Model (Mongoose)

// models/Transaction.js
const mongoose = require('mongoose');

const transactionSchema = new mongoose.Schema({
    transactionNumber: { type: String, unique: true, required: true },
    gateway:           { type: String, required: true },
    accountNumber:     { type: String, required: true },
    transferType:      { type: String, enum: ['IN', 'OUT'], required: true },
    transferAmount:    { type: Number, required: true },
    content:           { type: String },
    transactionDate:   { type: Date, required: true },
}, { timestamps: true });

transactionSchema.index({ accountNumber: 1, transferType: 1 });

module.exports = mongoose.model('Transaction', transactionSchema);

Webhook Server với Socket.io

// server.js — Express + Socket.io webhook handler
require('dotenv').config();
const express    = require('express');
const http       = require('http');
const crypto     = require('crypto');
const { Server } = require('socket.io');
const mongoose   = require('mongoose');
const Transaction = require('./models/Transaction');

const app    = express();
const server = http.createServer(app);
const io     = new Server(server);

// Kết nối MongoDB
mongoose.connect(process.env.MONGODB_URI)
    .then(() => console.log('MongoDB connected'))
    .catch(err => console.error('MongoDB error:', err));

// Raw body cho webhook (để tính HMAC chính xác)
app.use('/webhook', express.raw({ type: 'application/json' }));
app.use(express.json());

// Webhook endpoint
app.post('/webhook/thueapi', async (req, res) => {
    const rawBody   = req.body; // Buffer
    const signature = req.headers['x-webhook-signature'];
    const secret    = process.env.THUEAPI_WEBHOOK_SECRET;

    // Xác thực chữ ký HMAC-SHA256
    const expected = crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
    if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature || ''))) {
        return res.status(401).json({ error: 'Invalid signature' });
    }

    const data = JSON.parse(rawBody.toString());

    for (const tx of data.transactions) {
        try {
            // Lưu vào MongoDB (bỏ qua nếu đã tồn tại)
            const saved = await Transaction.findOneAndUpdate(
                { transactionNumber: tx.transactionNumber },
                { $setOnInsert: {
                    gateway:         tx.gateway,
                    accountNumber:   tx.accountNumber,
                    transferType:    tx.transferType,
                    transferAmount:  tx.transferAmount,
                    content:         tx.content,
                    transactionDate: new Date(tx.transactionDate),
                }},
                { upsert: true, new: true, rawResult: true }
            );

            // Chỉ emit nếu là giao dịch mới
            if (saved.lastErrorObject?.updatedExisting === false) {
                // Realtime notification qua Socket.io
                io.emit('new_transaction', {
                    type:   tx.transferType,
                    amount: tx.transferAmount,
                    bank:   tx.gateway,
                    content: tx.content,
                    time:   tx.transactionDate,
                });
                console.log(`Giao dịch mới: ${tx.transferType} ${tx.transferAmount} VND`);
            }
        } catch (err) {
            console.error('Lỗi lưu giao dịch:', err.message);
        }
    }

    res.json({ success: true });
});

// Client kết nối Socket.io để nhận realtime
io.on('connection', (socket) => {
    console.log('Client kết nối:', socket.id);
    socket.on('disconnect', () => console.log('Client ngắt kết nối:', socket.id));
});

const PORT = process.env.PORT || 3000;
server.listen(PORT, () => console.log(`Server chạy trên port ${PORT}`));

Client HTML nhận realtime

<!-- public/index.html -->
<script src="/socket.io/socket.io.js"></script>
<script>
const socket = io();

socket.on('new_transaction', (tx) => {
    const msg = `[${tx.time}] ${tx.type} ${tx.amount.toLocaleString()} VND từ ${tx.bank}`;
    document.getElementById('transactions').insertAdjacentHTML(
        'afterbegin', `<div class="alert">${msg}</div>`
    );
});
</script>

API Client (lấy lịch sử giao dịch)

// thueapi-client.js — Wrapper gọi ThueAPI
const axios = require('axios');

const thueApi = axios.create({
    baseURL: 'https://thueapi.vn/api/v1',
    headers: { 'Authorization': `Bearer ${process.env.THUEAPI_KEY}` },
});

async function getTransactions(params = {}) {
    const { data } = await thueApi.get('/transactions', { params });
    return data;
}

async function getBankAccounts() {
    const { data } = await thueApi.get('/bank-accounts');
    return data;
}

module.exports = { getTransactions, getBankAccounts };
ThueAPI.VN
Đăng nhập với Google
hoặc đăng nhập bằng email
Quên mật khẩu?

Chưa có tài khoản?

Đăng ký với Google
hoặc đăng ký bằng email

Bằng cách đăng ký, bạn đồng ý với Điều khoản dịch vụChính sách bảo mật của chúng tôi.

Đã có tài khoản?