Hướng dẫn nhúng màn hình hỗ trợ chat vào trang quản trị của bạn
Back to ezychatMàn hình hỗ trợ chat có thể được nhúng trực tiếp vào trang quản trị của một hệ thống khác bằng iframe. Khác với embedded script dành cho khách truy cập, iframe này hiển thị toàn bộ không gian làm việc của nhân viên hỗ trợ: danh sách hội thoại, lịch sử tin nhắn, chatbot, thông tin khách hàng và các thao tác quản lý hội thoại.

Phân biệt hai hình thức nhúng
Hệ thống cung cấp hai cơ chế nhúng khác nhau:
| Cơ chế | Đối tượng sử dụng | Nội dung |
|---|---|---|
| Embedded script | Khách truy cập website | Widget chat nổi |
| Support iframe | Nhân viên hỗ trợ | Toàn bộ màn hình xử lý hội thoại |
Bài viết này chỉ hướng dẫn support iframe.
Support iframe không dùng
embed.js. Trang quản trị của bạn tạo trực tiếp một iframe trỏ đến màn hình hỗ trợ của hệ thống chat.Chuẩn bị hồ sơ chat
Trước khi nhúng, cần có một hồ sơ chat đang hoạt động.
Hồ sơ này xác định:
- Các kênh được hiển thị.
- Thành viên được phép trực chat.
- Dịch vụ chatbot.
- Cấu hình hội thoại.
- Nguồn website được phép tải màn hình.
- Khóa nhúng dùng để xác định phạm vi dữ liệu.
Tại trang chi tiết hồ sơ chat, hệ thống cung cấp sẵn:
- URL mở màn hình hỗ trợ.
- Đoạn iframe hoàn chỉnh.
- Nút sao chép.
- Nút mở thử trong tab mới.
Thêm nhân viên hỗ trợ vào hồ sơ
Màn hình hỗ trợ độc lập sử dụng tài khoản người dùng, không sử dụng trực tiếp phiên đăng nhập quản trị của
/chat.Trước khi nhân viên có thể truy cập:
- Tạo tài khoản người dùng cho nhân viên.
- Mở trang chi tiết hồ sơ chat.
- Thêm người dùng đó vào danh sách thành viên.
- Chọn vai trò nhân viên chăm sóc khách hàng.
- Đặt trạng thái thành viên là
ACTIVATED.
Một tài khoản chỉ được vào màn hình chat khi là thành viên đang hoạt động của ít nhất một hồ sơ.
Sau khi đăng nhập, danh sách hội thoại tiếp tục được lọc theo:
- Tư cách thành viên kênh.
- Hồ sơ được truyền vào URL.
- Trạng thái của kênh.
Lấy đoạn iframe
Đoạn mã được tạo từ trang chi tiết hồ sơ có cấu trúc:
<iframe src="https://chat.example.com/ezychat/support?profile=YOUR_EMBED_KEY&lang=vi" title="Support Chat" width="100%" height="700" frameborder="0" allow="clipboard-write"> </iframe>
Thay:
-
https://chat.example.combằng địa chỉ máy chủ chat. -
YOUR_EMBED_KEYbằng khóa nhúng của hồ sơ. -
vibằng ngôn ngữ muốn sử dụng.
Nếu sao chép từ trang quản trị hồ sơ, địa chỉ máy chủ và khóa đã được điền sẵn.
Nhúng vào trang quản trị
Ví dụ một trang quản trị đơn giản:
<!DOCTYPE html> <html lang="vi"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Quản trị hỗ trợ khách hàng</title> <style> html, body { height: 100%; margin: 0; } .admin-layout { display: grid; grid-template-rows: 64px minmax(0, 1fr); height: 100vh; } .admin-header { display: flex; align-items: center; padding: 0 24px; border-bottom: 1px solid #ddd; } .chat-frame { display: block; width: 100%; height: 100%; border: 0; } </style> </head> <body> <div class="admin-layout"> <header class="admin-header"> <strong>Trung tâm hỗ trợ</strong> </header> <iframe class="chat-frame" src="https://chat.example.com/ezychat/support?profile=YOUR_EMBED_KEY&lang=vi" title="Màn hình hỗ trợ chat" allow="clipboard-write"> </iframe> </div> </body> </html>
Cách bố trí này cho phép màn hình chat chiếm toàn bộ vùng còn lại bên dưới thanh điều hướng.
Cấu trúc URL
URL màn hình hỗ trợ có dạng:
https://chat.example.com/ezychat/support
?profile=YOUR_EMBED_KEY
&lang=vi
&style=
Ba tham số được hỗ trợ gồm:
| Tham số | Bắt buộc | Ý nghĩa |
|---|---|---|
profile | Nên có | Khóa của hồ sơ chat |
lang | Không | Ngôn ngữ giao diện |
style | Không | CSS tùy chỉnh bên trong màn hình |
Tham số profile
profile chứa khóa nhúng của hồ sơ:profile=YOUR_EMBED_KEY
Khi nhận khóa, máy chủ:
- Tìm hồ sơ tương ứng.
- Kiểm tra hồ sơ đang hoạt động.
- Kiểm tra nguồn mở iframe.
- Truyền ID hồ sơ xuống ứng dụng.
- Lọc danh sách hội thoại theo hồ sơ đó.
Nếu khóa sai, hồ sơ đã bị xóa hoặc đang ngừng hoạt động, màn hình không được khởi tạo bình thường.
Không nên bỏ tham số
profile khi nhúng vào trang quản trị. Nếu không có hồ sơ, màn hình mất phạm vi phân tuyến mong muốn.Tham số lang
Ngôn ngữ được truyền qua tham số:
lang=vi
Ví dụ:
<iframe src="https://chat.example.com/ezychat/support?profile=YOUR_EMBED_KEY&lang=vi" title="Màn hình hỗ trợ chat"> </iframe>
Nếu không truyền
lang, hệ thống sử dụng cơ chế ngôn ngữ mặc định.Tham số style
Tham số
style chứa CSS được chèn vào bên trong trang hỗ trợ:style=CSS_DA_MA_HOA_URL
Khác với
data-style của embedded script:-
data-stylethay đổi iframe bên ngoài. - Tham số
stylethay đổi giao diện bên trong iframe.
CSS phải được URL-encode trước khi nối vào URL.
Ví dụ CSS:
.ezychat-support-page {
padding: 0;
}
#chatSection {
height: 100vh;
border-radius: 0;
}
Sau khi mã hóa:
const profileKey = 'YOUR_EMBED_KEY'; const customStyle = ` .ezychat-support-page { padding: 0; } #chatSection { height: 100vh; border-radius: 0; } `; const supportUrl = 'https://chat.example.com/ezychat/support' + '?profile=' + encodeURIComponent(profileKey) + '&lang=' + encodeURIComponent('vi') + '&style=' + encodeURIComponent(customStyle); document.getElementById('supportChatFrame').src = supportUrl;
HTML:
<iframe id="supportChatFrame" title="Màn hình hỗ trợ chat" class="chat-frame" allow="clipboard-write"> </iframe>
Chỉ nên truyền CSS do đội phát triển kiểm soát. Không đưa trực tiếp nội dung do người dùng cuối nhập vào tham số này.
Kích thước mặc định
Trang hỗ trợ mặc định:
- Chiếm toàn bộ chiều cao viewport của iframe.
- Có khoảng đệm
24px. - Căn giữa vùng chat.
- Đặt chiều cao vùng chat là
100vh - 48px. - Bo góc vùng làm việc.
- Ẩn phần nội dung tràn ra ngoài.
Nếu iframe có chiều cao
700px, màn hình chat bên trong gần tương ứng với chiều cao đó, trừ khoảng đệm.
Để chat chiếm trọn iframe, có thể truyền CSS:
.ezychat-support-page {
padding: 0;
}
#chatSection {
height: 100vh;
border-radius: 0;
}
Ví dụ nhúng vào bố cục có thanh bên
<div class="admin-shell"> <aside class="admin-sidebar"> <a href="/dashboard">Tổng quan</a> <a href="/support">Hỗ trợ khách hàng</a> </aside> <main class="admin-content"> <iframe src="https://chat.example.com/ezychat/support?profile=YOUR_EMBED_KEY&lang=vi" title="Hỗ trợ khách hàng" class="support-frame" allow="clipboard-write"> </iframe> </main> </div>
html,
body {
height: 100%;
margin: 0;
}
.admin-shell {
display: grid;
grid-template-columns: 240px minmax(0, 1fr);
height: 100vh;
}
.admin-sidebar {
overflow-y: auto;
border-right: 1px solid #ddd;
}
.admin-content {
min-width: 0;
min-height: 0;
}
.support-frame {
display: block;
width: 100%;
height: 100%;
border: 0;
}
min-width: 0 và min-height: 0 giúp iframe co đúng bên trong bố cục Grid hoặc Flexbox.Luồng xác thực
Màn hình hỗ trợ có cơ chế đăng nhập riêng.
sequenceDiagram
participant A as Trang quản trị
participant F as Support iframe
participant Auth as Dịch vụ đăng nhập
participant Chat as Dịch vụ chat
A->>F: Tải màn hình theo khóa hồ sơ
alt Chưa đăng nhập
F-->>A: Hiển thị form đăng nhập trong iframe
F->>Auth: Gửi tên đăng nhập và mật khẩu
Auth-->>F: Thiết lập cookie phiên
F->>F: Tải lại trang
end
F->>Chat: Kiểm tra tư cách thành viên hồ sơ
alt Có quyền
Chat-->>F: Cho phép vào màn hình chat
F->>Chat: Tải danh sách hội thoại
F->>Chat: Kết nối socket
else Không có quyền
Chat-->>F: Từ chối truy cập
F-->>A: Hiển thị màn hình không có quyền
end
Nếu chưa đăng nhập, iframe hiển thị biểu mẫu gồm:
- Tên đăng nhập hoặc email.
- Mật khẩu.
- Nút hiện hoặc ẩn mật khẩu.
- Nút đăng nhập.
- Thông báo khi đăng nhập thất bại.
Sau khi đăng nhập thành công, API đặt cookie xác thực và iframe tự tải lại.
Kiểm tra quyền
Sau khi có phiên đăng nhập, ứng dụng kiểm tra tài khoản có phải thành viên đang hoạt động của một hồ sơ chat hay không.
Có ba trạng thái:
- Chưa đăng nhập: hiển thị biểu mẫu đăng nhập.
- Đã đăng nhập nhưng không có quyền: hiển thị thông báo từ chối.
- Đủ quyền: hiển thị màn hình hỗ trợ.
Màn hình từ chối có nút đăng xuất và đăng nhập bằng tài khoản khác.
Cần lưu ý rằng bước kiểm tra ban đầu xác nhận người dùng thuộc ít nhất một hồ sơ đang hoạt động. Danh sách hội thoại sau đó mới được giới hạn bằng ID hồ sơ trên URL và tư cách thành viên kênh.
Tài khoản sử dụng
Support iframe dùng tài khoản người dùng của hệ thống web:
- Đăng nhập qua API dành cho người dùng.
- Lấy access token socket dành cho người dùng.
- Kiểm tra quan hệ thành viên hồ sơ theo loại người dùng.
- Truy cập các kênh mà người đó là thành viên.
Nó không dùng:
- Phiên quản trị của trang
/chat. - Admin access token.
- Vai trò nhân viên hỗ trợ toàn cục dành cho tài khoản quản trị.
Nếu trang quản trị bên ngoài đang đăng nhập bằng một hệ thống tài khoản khác, phiên đó không tự động được chia sẻ với iframe. Nhân viên vẫn phải đăng nhập vào hệ thống chat, trừ khi hai hệ thống đã triển khai cơ chế đăng nhập liên thông.
Kết nối realtime
Sau khi xác thực thành công, iframe:
- Lấy socket access token.
- Kết nối tới WebSocket của hệ thống chat.
- Đăng nhập socket bằng access token của người dùng.
- Tải các kênh thuộc hồ sơ.
- Nhận tin nhắn và trạng thái nhập realtime.
Màn hình hiển thị trạng thái:
- Đang kết nối.
- Trực tuyến.
- Ngoại tuyến.
Nếu kết nối socket bị gián đoạn, client tự thử kết nối lại. Các API lịch sử vẫn có thể hoạt động độc lập qua HTTP.
Các chức năng trong iframe
Màn hình hỗ trợ được nhúng cung cấp:
- Danh sách hội thoại đang hoạt động.
- Danh sách hội thoại đã lưu trữ.
- Cuộn tải thêm hội thoại.
- Tin nhắn cuối và số chưa đọc.
- Nhận và gửi tin realtime.
- Gửi văn bản, liên kết và media.
- Kéo thả tệp.
- Trả lời tin nhắn.
- Ghim và bỏ ghim.
- Nhảy tới tin đã ghim.
- Tải lịch sử cũ.
- Trạng thái đang nhập.
- Bật hoặc tắt chatbot.
- Quan sát chatbot đang sinh câu trả lời.
- Xem thông tin khách hàng.
- Đánh dấu hoặc bỏ đánh dấu spam.
- Lưu trữ và khôi phục hội thoại.
- Chuyển giao diện sáng hoặc tối.
- Chọn màu chủ đạo.
- Đăng xuất.
Các tùy chọn giao diện được lưu trong
localStorage của origin máy chủ chat, không phải localStorage của trang quản trị chứa iframe.
Khác biệt với màn hình /chat
Support iframe tái sử dụng phần lớn giao diện chat, nhưng có một số khác biệt:
| Chức năng | `/chat` quản trị | Support iframe |
|---|---|---|
| Dùng tài khoản quản trị | Có | Không |
| Dùng tài khoản người dùng | Không | Có |
| Form đăng nhập riêng | Không | Có |
| Lọc theo hồ sơ từ URL | Có thể | Có |
| Chế độ tối và màu giao diện | Không hiển thị riêng | Có |
| Nút đăng xuất | Theo hệ thống quản trị | Có trong iframe |
| Mở hồ sơ người dùng đầy đủ | Có nếu đủ quyền | Không |
| Xóa hội thoại | Có với kênh lưu trữ | Không hiển thị |
| Lưu trữ, khôi phục | Có | Có |
Support iframe phù hợp khi muốn đưa chức năng trực chat vào một cổng vận hành riêng mà không nhúng toàn bộ giao diện quản trị gốc.
Cookie và nhúng khác origin
Nếu trang quản trị và máy chủ chat dùng hai origin khác nhau, iframe hoạt động trong ngữ cảnh bên thứ ba.
Ví dụ:
Trang quản trị: https://admin.example.com Máy chủ chat: https://chat.example.net
Trình duyệt có thể giới hạn cookie của iframe. Khi đó có thể xảy ra:
- Đăng nhập thành công nhưng tải lại vẫn quay về form đăng nhập.
- Cookie không được lưu.
- API kiểm tra quyền trả về chưa xác thực.
- Socket access token không lấy được.
Để hỗ trợ iframe khác origin, cookie xác thực thường cần:
SameSite=None; Secure
Điều này yêu cầu HTTPS.
Một số trình duyệt hoặc chính sách doanh nghiệp vẫn có thể chặn hoàn toàn third-party cookies. Giải pháp ổn định hơn là:
- Đặt trang quản trị và dịch vụ chat dưới cùng một site.
- Dùng reverse proxy để xuất màn hình chat dưới tên miền quản trị.
- Triển khai đăng nhập liên thông.
- Mở màn hình hỗ trợ trong tab riêng nếu cookie iframe bị chặn.
Ví dụ triển khai cùng site:
https://admin.example.com/ https://chat.example.com/
Hai origin vẫn khác nhau, nhưng có thể thuận lợi hơn cho cấu hình cookie cùng site so với hai tên miền hoàn toàn độc lập. Cần kiểm tra thực tế chính sách cookie của trình duyệt đang hỗ trợ.
Cấu hình máy chủ cho phép iframe
Máy chủ chat phải cho phép trang hỗ trợ được hiển thị trong iframe.
Kiểm tra các header:
Content-Security-Policy: frame-ancestors https://admin.example.com
Không nên trả về:
X-Frame-Options: DENY
Nếu dùng
X-Frame-Options: SAMEORIGIN, iframe chỉ hoạt động khi trang quản trị và màn hình chat có cùng origin. Với tích hợp khác origin, nên dùng frame-ancestors để giới hạn rõ những trang được phép nhúng.Content Security Policy của trang quản trị
Trang quản trị cần cho phép iframe từ máy chủ chat:
Content-Security-Policy:
default-src 'self';
frame-src https://chat.example.com;
Trong nhiều cấu hình hiện đại,
frame-src là phần quan trọng nhất đối với trang cha. Các request API và WebSocket được thực hiện bên trong iframe và chịu CSP của chính trang hỗ trợ.Nếu CSP không cho phép, trình duyệt sẽ từ chối tải iframe và ghi lỗi trong Console.
Kiểm tra origin
Khi tải màn hình theo khóa hồ sơ, máy chủ chat kiểm tra origin hoặc referer của request.
Đối với iframe, request điều hướng thường có
Referer là URL trang quản trị. Hệ thống suy ra origin:scheme://host[:port]
Ví dụ:
https://admin.example.com
Origin này phải nằm trong danh sách được phép của hồ sơ nếu hồ sơ đã cấu hình allowlist.
Cần khai báo riêng cho từng môi trường:
https://admin.example.com https://staging-admin.example.com http://localhost:3000
Các URL có đường dẫn khác nhau nhưng cùng origin không cần khai báo riêng.
Sử dụng sandbox
Có thể thêm
sandbox để giới hạn iframe, nhưng phải cấp đủ quyền cho đăng nhập và runtime chat.Ví dụ tham khảo:
<iframe src="https://chat.example.com/ezychat/support?profile=YOUR_EMBED_KEY&lang=vi" title="Màn hình hỗ trợ chat" class="support-frame" allow="clipboard-write" sandbox=" allow-forms allow-scripts allow-same-origin allow-popups"> </iframe>
Các quyền có ý nghĩa:
-
allow-forms: cho phép đăng nhập và gửi form. -
allow-scripts: cho phép ứng dụng chat chạy. -
allow-same-origin: cần cho cookie, localStorage và request cùng origin của iframe. -
allow-popups: cho phép mở liên kết ngoài nếu giao diện có sử dụng.
Nếu bỏ
allow-same-origin, đăng nhập, localStorage hoặc các request xác thực có thể không hoạt động.
Không nên thêm sandbox quá chặt nếu chưa kiểm thử đầy đủ các luồng đăng nhập, upload, clipboard và mở liên kết.
Cho phép clipboard
Đoạn iframe do hệ thống sinh có:
allow="clipboard-write"
Quyền này cho phép các chức năng cần ghi dữ liệu vào clipboard hoạt động trong iframe khi trình duyệt hỗ trợ.
Nếu không cần clipboard, có thể bỏ thuộc tính. Việc gửi và nhận tin nhắn không phụ thuộc vào nó.
Điều chỉnh chiều cao
Chiều cao cố định
<iframe src="..." width="100%" height="700" style="border: 0;"> </iframe>
Phù hợp khi chat là một phần trong trang dài.
Chiếm phần còn lại của màn hình
.admin-page {
display: flex;
flex-direction: column;
height: 100vh;
}
.admin-header {
flex: 0 0 64px;
}
.support-frame {
flex: 1 1 auto;
width: 100%;
min-height: 0;
border: 0;
}
Chiếm toàn màn hình
.support-frame {
position: fixed;
inset: 0;
width: 100vw;
height: 100vh;
border: 0;
}
Cách này sẽ phủ lên giao diện quản trị, nên chỉ phù hợp với một route riêng dành hoàn toàn cho chat.
Tích hợp vào React
function SupportChatPage() {
const chatOrigin = 'https://chat.example.com';
const profileKey = 'YOUR_EMBED_KEY';
const params = new URLSearchParams({
profile: profileKey,
lang: 'vi',
});
return (
<iframe
src={`/ezychat/support?`}
title="Màn hình hỗ trợ chat"
allow="clipboard-write"
style={{
display: 'block',
width: '100%',
height: 'calc(100vh - 64px)',
border: 0,
}}
/>
);
}
Nếu dùng React Router, nên đặt iframe trong một route ổn định. Tránh thay đổi
key của component không cần thiết vì mỗi lần remount sẽ tải lại toàn bộ ứng dụng chat và kết nối socket.Tích hợp vào Vue
<template>
<iframe
:src="supportUrl"
title="Màn hình hỗ trợ chat"
allow="clipboard-write"
class="support-frame"
/>
</template>
<script setup>
const chatOrigin = 'https://chat.example.com';
const profileKey = 'YOUR_EMBED_KEY';
const params = new URLSearchParams({
profile: profileKey,
lang: 'vi',
});
const supportUrl =
`/ezychat/support?`;
</script>
<style scoped>
.support-frame {
display: block;
width: 100%;
height: calc(100vh - 64px);
border: 0;
}
</style>
Tích hợp vào Angular
import { Component } from '@angular/core';
import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
@Component({
selector: 'app-support-chat',
template: `
<iframe
[src]="supportUrl"
title="Màn hình hỗ trợ chat"
allow="clipboard-write"
class="support-frame">
</iframe>
`,
styles: [`
.support-frame {
display: block;
width: 100%;
height: calc(100vh - 64px);
border: 0;
}
`],
})
export class SupportChatComponent {
supportUrl: SafeResourceUrl;
constructor(sanitizer: DomSanitizer) {
const params = new URLSearchParams({
profile: 'YOUR_EMBED_KEY',
lang: 'vi',
});
this.supportUrl = sanitizer.bypassSecurityTrustResourceUrl(
`https://chat.example.com/ezychat/support?`
);
}
}
Chỉ sử dụng cơ chế bỏ qua kiểm tra URL với origin và profile do ứng dụng kiểm soát. Không truyền URL tùy ý từ người dùng vào
bypassSecurityTrustResourceUrl.Đăng xuất
Màn hình độc lập có nút đăng xuất ở cuối thanh bên.
Khi đăng xuất:
- Client yêu cầu xóa access token.
- Cookie phiên bị thu hồi.
- Iframe tải lại.
- Form đăng nhập xuất hiện.
Nếu nhiều ứng dụng cùng chia sẻ phiên người dùng trên origin máy chủ chat, thao tác này có thể đăng xuất người dùng khỏi các ứng dụng đó, không chỉ iframe hiện tại.
Giao diện cá nhân
Nhân viên có thể:
- Bật hoặc tắt chế độ tối.
- Chọn màu chủ đạo.
- Trở về màu mặc định.
Các lựa chọn được lưu trong localStorage dưới origin của máy chủ chat. Vì vậy:
- Tùy chọn được giữ khi tải lại iframe.
- Hai trang quản trị cùng nhúng một máy chủ chat có thể dùng chung lựa chọn.
- Xóa dữ liệu website của máy chủ chat sẽ đặt lại giao diện.
- Trang cha không thể đọc trực tiếp giá trị này khi khác origin.
Kiểm tra sau khi tích hợp
Sau khi nhúng, hãy kiểm tra:
- Iframe tải thành công.
- Không bị CSP hoặc
X-Frame-Optionschặn. - Hồ sơ đúng và đang hoạt động.
- Origin trang quản trị được cho phép.
- Form đăng nhập xuất hiện khi chưa có phiên.
- Cookie được giữ sau khi tải lại.
- Tài khoản không có quyền bị từ chối.
- Tài khoản được phân công xem đúng danh sách kênh.
- Danh sách chỉ chứa kênh của hồ sơ.
- Socket chuyển sang trạng thái trực tuyến.
- Có thể nhận và gửi tin.
- Upload tệp hoạt động.
- Lưu trữ và khôi phục hội thoại hoạt động.
- Chế độ tối và màu chủ đạo được lưu.
- Đăng xuất đưa về form đăng nhập.
- Bố cục hoạt động trên màn hình nhỏ.
Xử lý lỗi thường gặp
Iframe trắng hoặc bị từ chối tải
Kiểm tra Console của trang cha. Nguyên nhân thường là:
-
frame-srckhông cho phép máy chủ chat. - Máy chủ trả
X-Frame-Options: DENY. -
frame-ancestorskhông chứa origin trang quản trị. - URL iframe sai.
- Máy chủ chat không hoạt động.
Báo không tìm thấy hồ sơ
Kiểm tra:
- Khóa nhúng.
- Trạng thái hồ sơ.
- Khoảng trắng thừa trong URL.
- Hồ sơ có bị xóa hay không.
Báo không được phép truy cập
Kiểm tra tài khoản:
- Có tồn tại trong hệ thống người dùng không.
- Đã được thêm vào hồ sơ chưa.
- Loại thành viên có phải người dùng không.
- Trạng thái thành viên có phải
ACTIVATEDkhông. - Đã được thêm vào các kênh cần xử lý chưa.
Đăng nhập xong lại quay về màn hình đăng nhập
Đây thường là vấn đề cookie trong iframe:
- Cookie thiếu
SameSite=None. - Cookie thiếu
Secure. - Website đang dùng HTTP.
- Trình duyệt chặn third-party cookies.
- iframe thiếu
allow-same-originkhi dùng sandbox.
Đăng nhập được nhưng không có hội thoại
Kiểm tra:
- URL có đúng
profilekhông. - Các kênh có được gắn với hồ sơ đó không.
- Người dùng có phải thành viên kênh không.
- Kênh có đang ở trạng thái phù hợp không.
- Thành viên hồ sơ có được thêm trước khi các kênh được tạo không.
Việc được phân công vào hồ sơ không tự động đồng bộ người dùng vào mọi kênh cũ.
Socket luôn ở trạng thái đang kết nối
Kiểm tra:
- URL WebSocket.
- Chứng chỉ TLS.
- Reverse proxy có hỗ trợ WebSocket upgrade không.
- Access token socket có lấy được không.
- Trình duyệt có chặn
ws://trên trang HTTPS không.
CSS tùy chỉnh không có tác dụng
Đảm bảo CSS:
- Được đặt trong tham số
style. - Đã được URL-encode.
- Chọn đúng selector bên trong màn hình.
- Không bị stylesheet mặc định ghi đè bởi selector mạnh hơn.
Giới hạn hiện tại
Màn hình hỗ trợ nhúng hiện có một số giới hạn:
- Chưa hỗ trợ nhận phiên đăng nhập từ trang cha qua
postMessage. - Chưa có API SSO riêng dành cho iframe.
- Không tự động dùng phiên quản trị của hệ thống chứa iframe.
- Không có sự kiện công khai báo cho trang cha khi đăng nhập thành công.
- Không có sự kiện thông báo số hội thoại chưa đọc cho trang cha.
- Không có API công khai để trang cha chọn một kênh.
- Không có API công khai để thay đổi hồ sơ sau khi iframe đã tải.
- Không tự thay đổi chiều cao theo vùng chứa.
- CSS tùy chỉnh được truyền qua query string nên không phù hợp với cấu hình quá dài.
- Quyền ban đầu chỉ kiểm tra tài khoản thuộc ít nhất một hồ sơ hoạt động, chưa xác nhận trực tiếp tài khoản thuộc đúng hồ sơ trong URL.
- Người dùng mới thêm vào hồ sơ không tự động được thêm vào các kênh cũ.
- Đăng xuất có thể ảnh hưởng đến các ứng dụng khác dùng chung phiên trên máy chủ chat.
Khuyến nghị triển khai
Mô hình ổn định nhất là:
- Tạo một hồ sơ riêng cho từng nhóm hỗ trợ.
- Thêm đúng tài khoản người dùng vào hồ sơ.
- Dùng một route riêng trong trang quản trị cho iframe.
- Cấu hình allowlist origin.
- Dùng HTTPS cho cả hai hệ thống.
- Cấu hình cookie phù hợp nếu khác origin.
- Cho phép iframe bằng CSP
frame-ancestors. - Cho phép máy chủ chat trong
frame-srccủa trang quản trị. - Dùng chiều cao theo viewport.
- Kiểm thử trên các trình duyệt có chính sách cookie nghiêm ngặt.
Kết luận
Để nhúng màn hình hỗ trợ chat vào trang quản trị:
- Tạo và kích hoạt hồ sơ chat.
- Thêm nhân viên dưới dạng thành viên người dùng đang hoạt động.
- Sao chép support iframe từ trang chi tiết hồ sơ.
- Đặt iframe vào route quản trị.
- Cấu hình kích thước phù hợp.
- Cho phép origin và iframe ở cả hai phía.
- Kiểm tra cookie đăng nhập và kết nối socket.
- Xác nhận nhân viên chỉ nhìn thấy các kênh thuộc phạm vi được giao.
Support iframe phù hợp khi bạn muốn tích hợp đầy đủ không gian xử lý hội thoại vào một hệ thống quản trị riêng mà không phải tự xây dựng giao diện chat, phân trang, realtime, upload hay quản lý chatbot.