Vibe code xong web bán hàng? Bảo AI thêm live chat, gom Zalo, Messenger và để bot trả lời khách thay bạn
Bạn dựng một web bán hàng (hay một app nhỏ) bằng Cursor hoặc Claude Code trong vài buổi tối. Sản phẩm chạy, quảng cáo chạy, rồi khách bắt đầu nhắn: ô chat trên web, Zalo OA, Messenger của fanpage. 11 giờ đêm vẫn có người hỏi "còn size M không shop?". Bạn chỉ có một mình.
Bài này dành cho đúng hoàn cảnh đó: không có team CSKH, nhưng có một AI coding agent. Mỗi bước dưới đây là một câu lệnh bạn đưa cho agent, kèm đoạn code nó nên viết ra và những chỗ bạn cần soát lại (vì AI hay sai đúng mấy chỗ đó). Kết quả cuối:
- Live chat trên web Next.js, nhận ra khách đã đăng nhập.
- Zalo OA, Messenger, Instagram, TikTok Shop, website đổ về một hộp thư.
- Bot AI trả lời khách bằng dữ liệu sản phẩm và chính sách của bạn, không bịa.
- Khi bot không trả lời được, điện thoại bạn nhận tin qua Telegram.
- Chốt đơn và nhận tiền VietQR ngay trong cuộc chat.
Ví dụ dùng Hạ Tầng, nền tảng mình đang làm. Cách làm (định danh bằng HMAC, xác minh webhook, đồng bộ dữ liệu cho bot) dùng được cho các hệ thống live chat khác.
Vì sao không tự code một ô chat?
Một ô chat WebSocket thì agent viết được trong một buổi. Cái tốn thời gian là mọi thứ xung quanh, và đó là phần bài này không bắt bạn tự làm:
- Một hộp thư cho mọi kênh: website, app, Zalo OA, Messenger, Instagram, TikTok Shop, WhatsApp, Telegram, LINE, X và email. Một khách nhắn từ nhiều nơi vẫn là một hồ sơ.
- Bán ngay trong lúc chat: gửi thẻ sản phẩm, lên đơn và gửi mã VietQR trong hội thoại; tiền về là đơn tự chuyển sang đã thanh toán. Bot cũng tự gửi sản phẩm và ghi đơn nháp khi khách chốt.
- Thấy cả trước và sau cuộc chat: trước khi nhắn khách đã xem trang nào, đến từ quảng cáo nào; sau đó họ mua gì, đánh giá thế nào, lần sau quay lại hỏi gì.
- Bot càng dùng càng giỏi: câu nào bot không trả lời được được gom lại để bạn trả lời một lần; câu bạn gõ cho khách có thể "dạy" lại cho bot ngay trong hộp thư.
- Trả lời từ điện thoại: app iPhone, Android và Mac có thông báo đẩy, cho lúc bạn không ngồi trước máy.
- Chat, email giao dịch, thanh toán VietQR và hoá đơn điện tử trên một nền tảng: ít dịch vụ phải ghép, ít key phải giữ.
Bước 0: Cho agent đọc đúng tài liệu
Lý do số một khiến agent viết sai tích hợp: nó đoán API theo trí nhớ. Hãy cho nó tài liệu thật.
Claude Code: cài MCP server, agent sẽ tự tra tài liệu (không cần key để đọc docs):
claude mcp add hatang -- npx -y @hatang/mcp
Cursor: thêm vào .cursor/mcp.json:
{ "mcpServers": { "hatang": { "command": "npx", "args": ["-y", "@hatang/mcp"] } } }
Rồi thêm luật dự án để agent nhớ những quy tắc quan trọng (key để ở server, xác minh chữ ký...):
curl -s https://hatang.dev/docs/agents/AGENTS.md >> AGENTS.md
Dùng Lovable, Bolt, v0 hay công cụ không cài được MCP? Dán link https://hatang.dev/vi/docs/llms.txt vào prompt và bảo nó đọc trước.
Trên dashboard, tạo website ở Hỗ trợ → Kênh → Thêm kênh → Website để lấy site id (site_...).
Bước 1: Gắn live chat vào web
Prompt: "Thêm widget chat Hạ Tầng vào app Next.js này bằng
@hatang/chat-react. Site id để trongNEXT_PUBLIC_HATANG_SITE_ID. Đọc hướng dẫn React trong docs Hạ Tầng trước khi viết."
Agent nên tạo ra gần như thế này:
// app/layout.tsx
import { HatangChat } from "@hatang/chat-react";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="vi">
<body>
{children}
<HatangChat siteId={process.env.NEXT_PUBLIC_HATANG_SITE_ID!} />
</body>
</html>
);
}
Màu, lời chào, giờ làm việc, form xin số điện thoại trước khi chat: chỉnh trên dashboard, không cần bảo agent sửa code.

Bước 2: Nhận ra khách đã đăng nhập (chỗ AI hay làm sai nhất)
Prompt: "Khi user đã đăng nhập, truyền userId, email, name cho widget Hạ Tầng, kèm hash HMAC-SHA256 của userId tính ở server bằng
HATANG_IDENTITY_SECRET. Secret không được lộ ra client."
// app/layout.tsx (Server Component)
import { createHmac } from "node:crypto";
import { HatangChat } from "@hatang/chat-react";
import { getCurrentUser } from "@/lib/auth"; // hàm lấy user của app bạn
export default async function RootLayout({ children }: { children: React.ReactNode }) {
const user = await getCurrentUser();
const identity = user && {
userId: String(user.id),
email: user.email,
name: user.name,
hash: createHmac("sha256", process.env.HATANG_IDENTITY_SECRET!).update(String(user.id)).digest("hex"),
};
return (
<html lang="vi">
<body>
{children}
<HatangChat siteId={process.env.NEXT_PUBLIC_HATANG_SITE_ID!} user={identity ?? undefined} />
</body>
</html>
);
}
Soát lại:
HATANG_IDENTITY_SECRETkhông có tiền tốNEXT_PUBLIC_và không nằm trong file có"use client". Agent rất hay "sửa lỗi undefined" bằng cách đổi thànhNEXT_PUBLIC_, tức là công khai secret.userIdtruyền cho widget và chuỗi đem đi hash phải giống hệt nhau (cùngString(...)).
Vì sao phải ký: nếu chỉ gửi email từ trình duyệt, ai cũng có thể gõ email của người khác để đọc lịch sử chat của họ. Có hash hợp lệ thì hội thoại được đánh dấu Đã xác minh và gộp với lịch sử của đúng khách đó. Lấy secret ở Hỗ trợ → Kênh → website của bạn → Identity secret.
Bước 3: Gom Zalo, Messenger, Instagram về một hộp thư
Bước này không cần agent: kết nối từng kênh bằng tài khoản chính thức trên dashboard.

Sau đó mọi tin nhắn về chung một chỗ. Với solo builder, cái lợi lớn nhất là cột bên phải: khách đang xem trang nào, đến từ quảng cáo nào, đã mua gì. Không phải hỏi lại.

Prompt (tuỳ chọn): "Khi user áp mã giảm giá hoặc thêm vào giỏ, gọi
hatang().pushEvent(...)của@hatang/chat-reactđể sự kiện hiện trong hộp thư."
"use client";
import { hatang } from "@hatang/chat-react";
hatang().pushEvent("added_to_cart", { product: "tra-sen-100g", price: 120000 });
Bước 4: Cho bot trả lời bằng dữ liệu của bạn
Trợ lý AI chỉ trả lời từ kiến thức bạn đưa vào: FAQ, chính sách, trang web (tự crawl), Google Sheet, Notion, PDF. Với người làm một mình, chế độ hợp nhất là "Trả lời đầu tiên": bot tiếp mọi khách mới, không chắc thì chuyển cho bạn. Hoặc "Khi không ai trực tuyến" nếu bạn chỉ muốn bot trực lúc bạn offline.

Dữ liệu sản phẩm của bạn nằm trong database, nên đừng copy tay. Bảo agent đồng bộ:
Prompt: "Viết script
scripts/sync-knowledge.tsđọc toàn bộ sản phẩm và các trang chính sách trong DB, đẩy vào kho kiến thức Hạ Tầng bằnghatang.knowledge.sync(collectionproducts), mỗi sản phẩm một document Markdown có tên, giá, size, tình trạng hàng và link. Chạy sau mỗi lần deploy."
// scripts/sync-knowledge.ts
import { Hatang } from "@hatang/sdk";
import { db } from "@/lib/db"; // DB của app bạn
const hatang = new Hatang(); // HATANG_API_KEY (scope chat:write)
const products = await db.product.findMany();
const { data, error } = await hatang.knowledge.sync(
"products",
products.map((p) => ({
external_id: `product-${p.id}`,
title: p.name,
content: `# ${p.name}\n\nGiá: ${p.price.toLocaleString("vi-VN")}đ\nSize: ${p.sizes.join(", ")}\nCòn hàng: ${p.stock > 0 ? "có" : "hết"}\n\n${p.description}`,
url: `https://shop.example.com/san-pham/${p.slug}`,
locale: "vi",
})),
);
if (error) throw new Error(`${error.name}: ${error.message}`);
console.log(data);
sync làm cho collection chứa đúng các document bạn gửi: sản phẩm đã xoá trong DB cũng biến mất khỏi kiến thức của bot. Thử xem bot sẽ tìm thấy gì bằng hatang.knowledge.search("còn size M không").
Hai thứ giúp bot giỏi lên theo thời gian mà không cần code thêm: danh sách "Câu hỏi chưa có đáp án" (những gì bot phải chuyển cho bạn), và nút "Dạy AI từ câu trả lời này" ngay trong hộp thư: bạn trả lời khách một lần, bot nhớ cho lần sau.

Bước 5: Bot bí thì báo về Telegram của bạn
Prompt: "Tạo route
app/api/hatang/webhooks/route.tsnhận webhook Hạ Tầng, xác minh chữ ký bằngconstructWebhookEventtrên raw body. Khi nhậnchat.conversation.handoff, gửi tin Telegram cho tôi qua bot (token và chat id trong env) kèm tóm tắt."
// app/api/hatang/webhooks/route.ts
import { constructWebhookEvent, HatangSignatureError } from "@hatang/sdk";
export async function POST(req: Request) {
const raw = await req.text(); // xác minh trên body gốc, trước khi parse JSON
let event;
try {
event = await constructWebhookEvent(raw, req.headers, process.env.HATANG_WEBHOOK_SECRET!);
} catch (err) {
if (err instanceof HatangSignatureError) return new Response(null, { status: 400 });
throw err;
}
if (event.type === "chat.conversation.handoff") {
const c = event.data as { channel: string; reason: string; summary: string | null };
await fetch(`https://api.telegram.org/bot${process.env.TELEGRAM_BOT_TOKEN}/sendMessage`, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ chat_id: process.env.TELEGRAM_CHAT_ID, text: `Khách cần bạn (${c.channel}): ${c.summary ?? c.reason}` }),
});
}
return new Response(null, { status: 200 });
}
Tạo endpoint ở Cài đặt → Webhooks, chọn sự kiện chat.conversation.handoff, copy signing secret (whsec_...) vào HATANG_WEBHOOK_SECRET.
Soát lại: agent hay dùng await req.json() rồi mới xác minh. Sai: chữ ký tính trên body gốc, parse rồi stringify lại là lệch. Phải là req.text() như trên. Và trả 200 nhanh: webhook lỗi sẽ được gửi lại, xử lý nặng thì đưa vào hàng đợi.
Bán hàng ngay trong lúc chat
Phần này cũng không cần code, chỉ cần một danh mục sản phẩm (nhập tay trên dashboard, hoặc bảo agent đồng bộ từ DB như bước 4). Trong hộp thư, nút Sản phẩm gửi thẻ có ảnh, giá và nút mua; nút Đơn hàng lên đơn ngay trong hội thoại; sau đó gửi thẻ thanh toán VietQR với số tiền và nội dung chuyển khoản điền sẵn. Khi tiền về tài khoản của bạn, đơn tự chuyển sang đã thanh toán và khách nhận lời cảm ơn trong chat: không phải mở app ngân hàng để soi.

Bot làm được nửa đầu việc này: gửi sản phẩm với giá lấy đúng từ danh mục, và khi nhận ra khách đã chốt thì ghi một đơn nháp kèm ghi chú nội bộ. Bạn chỉ bấm xác nhận rồi gửi link thanh toán. Bot không tự nhận tiền, không sửa đơn, không hoàn tiền.
Nếu web của bạn đã có checkout riêng, đơn hàng và thanh toán cũng tạo được bằng API (hatang.payments.createOrder), xem bài nhận thanh toán VietQR.
Thấy cả trước và sau cuộc chat
Trước: trang Đang truy cập cho biết ai đang ở trên web ngay lúc này, đang đọc trang nào, đến từ Google, Cốc Cốc hay quảng cáo Facebook nào, quay lại lần thứ mấy. Thấy ai đó ngồi mãi ở trang sản phẩm thì chào trước. Muốn tự động hơn, chiến dịch hiện lời mời chat hoặc form xin số điện thoại khi khách ở trang bảng giá đủ lâu, cuộn nửa trang hay sắp rời đi.

Sau: hồ sơ khách gom mọi thứ theo thời gian: các đơn đã mua và trạng thái thanh toán, hội thoại ở mọi kênh, ghi chú của bạn, nhãn, giai đoạn (mới, đã liên hệ, đủ điều kiện, khách hàng). Khi khách quay lại hỏi "đơn hôm trước của chị đâu rồi em?", bạn (và bot) thấy ngay. Xong hội thoại, khách được mời đánh giá mức độ hài lòng.

Dạy bot cách cư xử, không chỉ kiến thức
Kiến thức cho bot biết điều gì đúng; tình huống cho bot biết nên làm gì: khách hỏi giá sỉ thì gọi bạn vào, khách bực bội thì xin lỗi và chuyển người, ngoài giờ thì vẫn trả lời và xin số điện thoại để gọi lại. Trước khi bật cho khách thật, viết vài câu hỏi mẫu kèm câu trả lời mong đợi ở tab Kiểm thử và chạy lại mỗi khi sửa kiến thức, giống viết test cho code.
Checklist trước khi deploy
- [ ] Không có
HATANG_API_KEY,HATANG_IDENTITY_SECRET,HATANG_WEBHOOK_SECRETnào có tiền tốNEXT_PUBLIC_hay bị import vào client component. - [ ] Hash định danh tính ở server, từ đúng chuỗi
userIdtruyền cho widget. - [ ] Webhook xác minh chữ ký trên
req.text(). - [ ] Domain của website trên dashboard đúng với domain thật (widget chỉ chạy trên domain đó và các origin bạn cho phép thêm).
- [ ] Đã chạy thử bot ở tab Kiểm thử với 5–10 câu khách hay hỏi trước khi bật.
Câu hỏi thường gặp
Làm app di động (Flutter, React Native) chứ không phải web thì sao? Cùng hộp thư, cùng bot, có SDK cho Flutter, React Native, iOS, Android. Prompt gần như y hệt, đổi tên gói.
Web làm bằng WordPress, Shopify, Haravan, Sapo, LadiPage? Có plugin WordPress; nơi khác dán hai dòng script:
<script>window.$hatang=window.$hatang||[];window.HATANG_SITE_ID="site_...";</script>
<script src="https://chat.hatang.dev/widget.js" async></script>
Bot có bịa không? Bot chỉ trả lời từ kiến thức đã lập chỉ mục; không tìm thấy thì chuyển cho bạn (và câu đó vào "Câu hỏi chưa có đáp án") thay vì đoán.
Agent dùng MCP server làm được gì ngoài đọc docs?
Có API key (HATANG_API_KEY) thì agent còn đọc được hội thoại, tìm trong kiến thức, gửi email, tạo thanh toán VietQR thử. Thêm --read-only nếu chỉ muốn cho nó tra cứu. Xem MCP server.
Tài liệu
- Dùng Hạ Tầng với AI coding agent
- Thêm chat vào website Next.js hoặc React
- Xác minh danh tính người dùng
- Trợ lý AI và Knowledge API
- Code mẫu: hatang-nextjs-starter
Mình đang làm ở Hạ Tầng. Code lấy từ tài liệu chính thức và SDK hiện tại.
All rights reserved