Một đội hỗ trợ ở Việt Nam đã gom Zalo, WhatsApp và LINE vào một hàng đợi inbound như thế nào
8:12 sáng thứ Hai tại TP. Hồ Chí Minh, trưởng nhóm hỗ trợ còn chưa mở laptop thì tin nhắn Zalo đầu tiên đã đến. Một khách hàng muốn đổi địa chỉ giao hàng trước khi bên vận chuyển đến lấy hàng. Bốn phút sau, một nhà cung cấp ở Bangkok nhắn LINE báo một thùng hàng bị trễ. Đến 8:27, một khách quen ở Singapore hỏi về điều kiện bảo hành qua WhatsApp.
Không tin nhắn nào bất thường. Vấn đề là chúng nằm ở ba nơi khác nhau, trên ba chiếc điện thoại khác nhau, thuộc ba người khác nhau. Đến 9 giờ, đội đã copy hai ảnh chụp màn hình vào Slack, chuyển tiếp một tin cho sales, rồi quên mất khách nào đã hỏi về bảo hành.
Đây là đội vận hành và hỗ trợ 5 người của một thương hiệu mỹ phẩm nhỏ, xử lý đơn hàng xuyên biên giới. Khách hàng chủ yếu ở Việt Nam, Thái Lan và Singapore, nên bộ kênh rất dễ hiểu: khách nội địa dùng Zalo, đối tác Thái Lan dùng LINE, nhà cung cấp và khách quốc tế dùng WhatsApp. Họ không cần campaign, không cần broadcast template, cũng không muốn đổi CRM. Họ cần biến mọi tin nhắn inbound thành một việc có thể xử lý.
Ba inbox, một yêu cầu phản hồi
Trước khi thay đổi, quy trình rất thủ công. Zalo nằm trên điện thoại của trưởng nhóm hỗ trợ tại Việt Nam. LINE nằm với điều phối viên phụ trách nhà cung cấp Thái. WhatsApp nằm với founder vì nhiều khách cũ vẫn có số của anh. Mỗi sáng, cả đội mở Slack và dán ảnh chụp những tin có vẻ gấp.
Cách này ổn khi lượng tin thấp. Nhưng khi tăng lên, vấn đề trở nên rất cụ thể. Một yêu cầu đổi địa chỉ bị bỏ lỡ trước giờ lấy hàng dẫn đến hoàn tiền. Tin LINE của nhà cung cấp về việc trễ thùng hàng được thấy sau khi kho đã hứa giao trong ngày. Một câu hỏi bảo hành trên WhatsApp nằm yên vì founder đang đi công tác.
Trong hai tuần, đội ghi nhận 31 phản hồi trễ. Phần lớn không phải lỗi kỹ thuật. Đó là lỗi về khả năng nhìn thấy. Có người đã thấy tin, nhưng cả đội thì không. Hoặc người phù hợp không online, và những người khác không biết tin nhắn đó tồn tại.
Các đường chính thức của từng nền tảng giải quyết những bài toán lớn hơn. Zalo Official Account hữu ích nếu cần vận hành tài khoản chính thức và template thông báo. LINE Official Account hữu ích cho rich menu, broadcast và hiện diện thương hiệu. WhatsApp Cloud API hữu ích cho business messaging theo template ở quy mô lớn. Nhưng đội này không muốn chủ động mở hàng loạt cuộc trò chuyện. Các cuộc trò chuyện quan trọng đều bắt đầu từ khách hàng hoặc nhà cung cấp.
Vì vậy, yêu cầu của dự án thay đổi. Không phải “triển khai ba hệ thống business messaging chính thức”, mà là “biến mỗi tin inbound thành một queue item đáng tin”.
Webhook họ thật sự cần
Đội tạo một endpoint trong backend:
POST /inbound/messages
Sau đó họ kết nối một tài khoản Zalo, một tài khoản WhatsApp và một tài khoản LINE qua UnifyPort. Cả ba tài khoản đều deliver về cùng một webhook endpoint. Mỗi delivery dùng cùng một envelope: id, type, provider, account_id, occurred_at, và data.
Một tin Zalo sau khi normalize trông như sau:
{
"id": "evt_7f4c20a91d",
"type": "message.received",
"provider": "zalo",
"account_id": "acc_vn_support",
"occurred_at": "2026-07-02T01:12:16Z",
"data": {
"conversation": { "id": "zalo_user_1942", "type": "user", "title": "Minh Anh" },
"sender": { "id": "zalo_user_1942", "type": "user", "name": "Minh Anh" },
"message": {
"id": "zalo_msg_8831",
"type": "text",
"text": "Em muốn đổi địa chỉ giao hàng trước 11h được không?",
"direction": "inbound",
"sent_at": "2026-07-02T01:12:15Z"
},
"event": { "kind": "message_received" }
}
}
Cùng một handler xử lý cả WhatsApp và LINE. provider thay đổi, nhưng code routing không cần parser riêng cho từng nền tảng.
Trước khi tin payload, endpoint kiểm tra chữ ký delivery. Endpoint có signing_secret, nên mỗi request có X-Device-Timestamp và X-Device-Signature. Chữ ký là HMAC-SHA256 hex digest của timestamp, dấu chấm, và raw request body.
import crypto from 'crypto';
import express from 'express';
const app = express();
const secret = process.env.WEBHOOK_SIGNING_SECRET;
app.post('/inbound/messages', express.raw({ type: 'application/json' }), async (req, res) => {
const timestamp = req.get('X-Device-Timestamp');
const signature = req.get('X-Device-Signature');
const hmac = crypto.createHmac('sha256', secret);
hmac.update(timestamp + '.');
hmac.update(req.body);
const expected = hmac.digest('hex');
const valid = signature.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
if (!valid) {
res.status(401).end();
return;
}
const event = JSON.parse(req.body.toString('utf8'));
await enqueueInboundMessage(event);
res.status(200).end();
});
Queue item lưu 5 trường mà đội cần: nền tảng, tên khách hàng, nội dung tin, conversation ID và account ID. Phần còn lại được giữ như raw event metadata để audit sau này.
Quy tắc routing ai cũng hiểu được
Phiên bản đầu tiên cố tình đơn giản.
Tin Zalo đi vào lane hỗ trợ Việt Nam. Tin LINE đi vào lane nhà cung cấp. Tin WhatsApp đi vào lane khách quốc tế. Tin nào có mã đơn hàng thì tạo CRM note. Tin nào có từ khóa giao hàng thì post vào Slack channel #fulfillment.
Tuần đầu tiên không có AI classifier. Đội muốn một hệ thống có thể debug khi đơn hàng đang chạy. Họ dùng tên rule như delivery_change, supplier_delay, warranty_question, và mỗi item hiển thị rule đã match.
Sang tuần thứ hai, họ chỉ thêm một lớp hỗ trợ: draft suggestion cho ba câu hỏi lặp lại. Đổi địa chỉ thì tạo câu trả lời xin địa chỉ mới và mã đơn. Hỏi bảo hành thì tạo mẫu trả lời về thời hạn bảo hành và ảnh cần gửi. Nhà cung cấp báo trễ thì tạo câu hỏi về thời gian bàn giao mới. Draft chỉ được post vào Slack, không gửi tự động.
Ranh giới này rất quan trọng. Đội không muốn automation nói chuyện thay người. Họ muốn automation làm cho hành động tiếp theo của con người rõ ràng hơn.
Sau bốn tuần
Thay đổi dễ thấy nhất rất đơn giản: không ai phải nhìn ba điện thoại nữa. Trưởng nhóm hỗ trợ mở một queue mỗi sáng và thấy Zalo, WhatsApp, LINE trong cùng một danh sách. Đội vẫn lọc theo provider được, nhưng default view là inbound work theo thời gian.
Median first response time giảm từ 2 giờ 18 phút xuống 26 phút. Tin nhắn quá 4 giờ chưa xử lý giảm từ 31 tin trong hai tuần xuống còn 3 tin trong hai tuần tiếp theo. Quan trọng hơn, screenshot không còn là record vận hành. Mỗi inbound event có event ID ổn định, provider, account ID và timestamp.
CRM cũng hữu ích hơn. Trước đây lịch sử Zalo của khách nằm trên một điện thoại, còn ngữ cảnh LINE của nhà cung cấp nằm với một điều phối viên. Sau thay đổi, CRM hiển thị tin cuối cùng bất kể kênh. Khi founder chuẩn bị gọi gia hạn, anh không còn phải nhờ cả đội lục lại chat. Anh mở contact record.
Khách hàng không bị chuyển sang kênh mới. Họ vẫn nhắn vào cùng các tài khoản Zalo, WhatsApp hoặc LINE. Chỉ backend path sau khi tin nhắn đến là thay đổi.
Mẫu hình đáng chú ý
Với đội nhỏ, điều quan trọng là tách inbound support khỏi outbound campaign infrastructure. Sản phẩm business chính thức rất có giá trị khi cần verified presence, broadcast, template, rich menu hoặc campaign operations. Nhưng nếu nỗi đau hiện tại là “khách nhắn trước và đội bỏ sót tin”, hệ thống đầu tiên cần xây là inbound routing layer.
Với UnifyPort, đội xử lý mọi nền tảng như một event stream. message.received trở thành contract chung. HMAC-SHA256 verification làm delivery đáng tin. Trường provider cho queue biết tin đến từ đâu, còn support workflow vẫn platform-neutral.
Với một đội 5 người, vậy là đủ. Một webhook, một queue, và những công cụ họ đã dùng sẵn.