Chuyển tới nội dung chính

Realtime

Mọi client chat đều nói chuyện với chat gateway tại https://chat.hatang.dev qua cùng một giao thức WebSocket. Trang này giải thích một phiên chạy từ đầu tới cuối ra sao, để bạn gỡ lỗi widget, hiểu SDK làm gì, hoặc tự viết client. Chi tiết từng khung nằm ở tham chiếu giao thức realtime, các endpoint HTTP ở tham chiếu chat gateway.

Chọn đúng giao diện​

Bạn muốnDùng
Đặt chat trên websiteWidget web; widget tự nói giao thức
Đặt chat trong ứng dụng di độngSDK native (Ứng dụng di động)
Tự xây giao diện chat cho kháchGiao thức phía khách mô tả bên dưới
Đọc và trả lời hội thoại từ server, bot hay CRMREST API Hỗ trợ với API key, kèm webhook

Phía nhân viên của gateway phục vụ dashboard và ứng dụng Hạ Tầng trên iPhone, Android và Mac. Nó cần phiên đăng nhập của một nhân viên, không phải API key, nên tích hợp từ server hãy dùng REST API.

Phiên của khách​

Một khách truy cập (visitor) là một trình duyệt hoặc một bản cài ứng dụng trên một site. Phiên chạy qua năm bước.

1. Bootstrap​

Client gọi POST /widget/v1/sites/{siteId}/bootstrap một lần khi khởi động.

  • Trình duyệt được kiểm tra bằng Origin. Trang phải nằm trên tên miền của site, một tên miền con của nó, hoặc một trong các origin được phép thêm của site. Ngoài ra đều nhận 403 origin_not_allowed.
  • Ứng dụng native gửi khoá ứng dụng trong header x-hatang-app-key và app.install_id (id cố định cho mỗi bản cài) trong body. Không cần origin.

Body có thể mang token đã lưu (để tiếp tục đúng khách cũ), page hoặc screen, và locale. Response gồm:

TrườngLà gì
visitor_tokenThông tin xác thực của khách. Lưu lại (cookie hoặc local storage trên web, keychain trong ứng dụng) và gửi lại lần sau
visitorHồ sơ khách truy cập
configCài đặt widget của site, chiến dịch và nút liên hệ
availabilityĐội đang trực tuyến hay đang trong giờ làm việc
conversation, timelineHội thoại đang mở (nếu có) và 100 phần tử gần nhất khách được thấy
ws_urlĐịa chỉ socket cần mở, ví dụ wss://chat.hatang.dev/ws?site=site_...
protocol_versionHiện là 1

Các lời gọi HTTP khác trong phiên gửi token trong header x-visitor-token.

2. Kết nối và xác thực​

Mở đúng ws_url đã nhận và gửi khung auth trong vòng 5 giây. Mỗi khung là JSON gồm loại t, dữ liệu d, phiên bản v và id tuỳ chọn mà server gửi lại trong câu trả lời.

const ws = new WebSocket(boot.ws_url);
ws.onopen = () => ws.send(JSON.stringify({
t: "auth", v: 1,
d: { token: boot.visitor_token, site_id: "site_...", page: { url: location.href, title: document.title } },
}));
ws.onmessage = (e) => {
const frame = JSON.parse(e.data);
if (frame.t === "ready") render(frame.d.conversation, frame.d.timeline);
if (frame.t === "message") append(frame.d);
};

Server trả lời bằng ready, mang thông tin khách, hội thoại đang mở, dòng thời gian và trạng thái trực của đội. Sau đó cả hai bên gửi ping mỗi 25 giây.

3. Gửi tin​

Mỗi tin gửi đi có một client_id do client sinh ra:

{ "t": "message.send", "id": "req_1", "v": 1, "d": { "client_id": "c_9f2", "content": "Shop còn hàng không ạ?" } }
  1. Hiện tin ở trạng thái đang gửi và chờ tối đa 10 giây để nhận message.ack, trong đó có id của tin, seq và conversation_id. Tin đầu tiên của khách sẽ tạo hội thoại.
  2. Hết thời gian chờ hoặc gặp lỗi thì giữ bong bóng ở trạng thái lỗi và gửi lại với cùng client_id. Server nhận ra và xác nhận tin gốc, nên gửi lại không bao giờ tạo hai tin.
  3. Bản thân tin nhắn cũng quay về dưới dạng khung message. Loại trùng theo id.

Khách gửi được 5 tin mỗi 10 giây và 60 tin mỗi phút. Tệp được tải lên trước bằng POST /widget/v1/sites/{siteId}/uploads (tối đa 10 MB), rồi gửi theo id trong attachments.

4. Nhận​

Khi đang kết nối, khách nhận:

KhungKhi nào
messageNhân viên, trợ lý AI hoặc hệ thống nhắn vào một hội thoại của khách
typingNhân viên đang gõ
readPhía nhân viên đã đọc tới một seq
availabilityĐội chuyển sang trực tuyến hoặc vắng mặt
conversation.updateTrạng thái, số tin chưa đọc hoặc người đang xử lý của một hội thoại thay đổi
eventSự kiện khách nên thấy, như đổi trạng thái hay chuyển sang người thật
sessionKhách vừa được gộp vào một khách khác nhờ identify có chữ ký: lưu token mới

Client báo lại những gì khách làm bằng typing, read, page (trình duyệt) hoặc screen (ứng dụng), và identify khi khách đăng nhập (Nhận diện khách). Ứng dụng còn gửi app.state khi chuyển xuống nền, để trả lời tới tay khách bằng thông báo đẩy.

5. Kết nối lại mà không mất gì​

Mọi tin nhắn và sự kiện trong một hội thoại có seq chỉ tăng. Giữ seq lớn nhất bạn đã thấy. Sau khi kết nối lại, gửi resume {conversation_id, after_seq} và server phát lại từ cơ sở dữ liệu mọi thứ bạn bỏ lỡ. Lịch sử cũ hơn tải qua HTTP với before_seq.

Khi socket đóng, xem mã đóng:

MãÝ nghĩaLàm gì
4001Không có auth trong 5 giâyKết nối lại và gửi auth trước
4003Xác thực bị từ chối hoặc bị thu hồiDừng; bỏ token và bootstrap một khách mới
4004Giao thức của client quá cũTrình duyệt tải lại trang; ứng dụng nhắc người dùng cập nhật
4005Khung session vừa mang token mớiKết nối lại ngay với token mới
KhácMạng hoặc gateway khởi động lạiKết nối lại với backoff min(30 s, 500 ms · 2^n) cộng jitter

Phía nhân viên​

Dashboard và các ứng dụng Hạ Tầng dùng cùng gateway này dưới tư cách nhân viên:

  • Socket. Kết nối của nhân viên xác thực bằng một agent token ngắn hạn. Dashboard lấy token từ phiên đăng nhập và token này chỉ được chấp nhận từ origin của dashboard; ứng dụng di động và Mac nhận token khi nhân viên đăng nhập. Sau đó nhân viên theo dõi hội thoại, nhận các khung message, conversation.upsert, typing và trạng thái trực tuyến, và gửi tin, ghi chú, giao việc, đổi trạng thái, gắn tag, đặt nhắc việc.
  • HTTP. Ứng dụng cũng gọi các endpoint /agent/*, ví dụ GET /agent/conversations để lấy danh sách hộp thư, POST /agent/uploads để tải tệp (10 MB, video 25 MB; tệp .mov được lưu thành MP4), POST/PATCH/DELETE /agent/canned cho câu trả lời mẫu riêng của nhân viên, và /agent/conversations/{id}/scheduled cùng /agent/scheduled/{id} cho tin nhắn hẹn giờ (mọi thay đổi tới tất cả nhân viên qua khung scheduled). Mỗi người được 300 lượt đọc và 60 lượt ghi mỗi phút.
  • Quyền. Token mang vai trò của nhân viên. Người chỉ có quyền xem Hỗ trợ vẫn thấy hộp thư cập nhật trực tiếp nhưng không thao tác được (Nhân viên và phân quyền).

Vì các token này thuộc về một người và hết hạn trong vòng một giờ, chúng không dành cho tích hợp. Để tự động hoá hộp thư, gọi REST API Hỗ trợ bằng API key và đăng ký webhook.

Xử lý sự cố​

Hiện tượngNguyên nhân thường gặp
origin_not_allowed khi bootstrapTên miền của trang không phải tên miền của site, tên miền con của nó, hay một origin được phép. Thêm vào ô Origin được phép thêm trên trang của website trong Hỗ trợ → Kênh
invalid_visitor_tokenToken hết hạn, đã reset, hoặc thuộc site khác. Bootstrap lại không kèm token
product_disabledDoanh nghiệp đang tắt module Hỗ trợ
Socket đóng với mã 4001Client gửi khung khác trước auth, hoặc chậm quá 5 giây
Tin hiện hai lầnClient không loại trùng bản message quay về theo id
Mất tin sau khi rớt mạngClient không gửi resume với seq cuối cùng

Bước tiếp theo​

Xem trang này dạng Markdown