Nhúng trình soạn thảo
API phiên nhúng
Các endpoint REST mà api.js dùng: tạo phiên, xem trạng thái, đổi chế độ, đóng phiên, tải phiên bản có chữ ký, CORS và trang thử.
Trong trang này
api.js gọi các endpoint dưới đây thay bạn. Bạn gọi trực tiếp khi cần chẩn đoán, khi muốn tạo phiên từ máy chủ, hoặc khi tự viết lớp nhúng cho một khung giao diện khác. Mọi đường dẫn nằm dưới /o3o/; mọi phản hồi có header X-O3O-Request-Id; lỗi có dạng {error: {code, message, detail, request_id}}.
/o3o/api.jsThư viện JavaScript của lớp nhúng.
/o3o/embed/sessionTạo một phiên nhúng.
Thân là config ở tham chiếu cấu hình đã bỏ events, Content-Type: application/json. Gate kiểm origin, token và config; tải tệp nếu key chưa mở; xét trần khi mode = "edit"; lấy đường dẫn trình soạn thảo từ discovery; rồi trả 201.
Thân yêu cầu
documentobjectbắt buộcXem tham chiếu cấu hình. Có thể nằm trongtoken.editorobjectbắt buộcXem tham chiếu cấu hình. Có thể nằm trongtoken.uiobjecttuỳ chọnXem tham chiếu cấu hình.tokenstringtuỳ chọnJWT HS256; khi hợp lệ thì thay cho ba trường trên.
{
"session_id": "ses_5b1d0c2a9f3e4d6a8b7c0d1e",
"key": "hopdong-42-v7",
"doc_id": "doc_9835f61009fc659dfedab8696f2d2665",
"mode": "edit",
"requested_mode": "edit",
"limited": false,
"limit": null,
"message": null,
"editor_url": "/browser/825c9caa93/cool.html?WOPISrc=http%3A%2F%2Fo3o-gate%3A8070%2Fo3o%2Fwopi%2Ffiles%2Fdoc_9835f61009fc659dfedab8696f2d2665&lang=vi&closebutton=1",
"form": {
"access_token": "kq3…",
"access_token_ttl": 1790043200000,
"ui_defaults": "UIMode=notebookbar"
},
"version": 0,
"expires_at": "2026-09-21T22:00:00Z"
}Trả lời 201
session_idstringbắt buộcses_+ 24 hex.mode, requested_modestringbắt buộcChế độ thật và chế độ đã xin.limited, limit, messageboolean, object | null, string | nullbắt buộcThông tin chạm trần;nullkhi không bị hạ.editor_urlstringbắt buộcĐường dẫn tương đối của trang soạn thảo, nối vào gốc máy chủ O3O.formobjectbắt buộcCác trường form POST gửi vào iframe:access_token,access_token_ttl,ui_defaults. KHÔNG đưa lên URL.versionintegerbắt buộcPhiên bản hiện tại của tài liệu.expires_atstringbắt buộcHạn củaaccess_token.
Tự nhúng không qua api.js: tạo <iframe name="…" allow="clipboard-read; clipboard-write; fullscreen">, tạo <form method="post" target="…"> với action = gốc máy chủ + editor_url và một ô ẩn cho mỗi khoá của form, gửi form rồi gỡ nó. Chỉ nhận postMessage có origin đúng gốc máy chủ.
/o3o/embed/session/{session_id}Trạng thái phiên và tài liệu.
{
"session_id": "ses_5b1d0c2a9f3e4d6a8b7c0d1e",
"key": "hopdong-42-v7",
"doc_id": "doc_9835f61009fc659dfedab8696f2d2665",
"mode": "edit",
"state": "active",
"version": 3,
"modified": false,
"saved_at": "2026-09-21T10:05:00Z",
"size": 48890,
"sha256": "b1946ac92492d2347c6235b4d2611184…",
"download_url": "http://localhost:8080/o3o/embed/files/doc_9835f61009fc659dfedab8696f2d2665?v=3&exp=1790086400&sig=5f1c…",
"users": [
{
"id": "u-1001",
"name": "Nguyễn Văn A"
}
]
}/o3o/embed/session/{session_id}/modeĐổi chế độ; thân {"mode": "view"} hoặc {"mode": "edit"}. Trả cùng lược đồ với 201, giữ nguyên session_id và access_token; chuyển sang edit có xét trần.
/o3o/embed/session/{session_id}Đánh dấu phiên closed, trả 204. Không ép đóng trình soạn thảo, không xoá tài liệu.
# Tạo phiên chỉ đọc để chẩn đoán (chế độ view không giữ suất kết nối)
curl -s -X POST http://localhost:8080/o3o/embed/session \
-H "Content-Type: application/json" \
-d '{"document": {"url": "http://localhost:8080/o3o/demo/sample.docx", "title": "sample.docx", "fileType": "docx", "key": "diag-1"},
"editor": {"mode": "view", "lang": "vi", "user": {"id": "ops-1", "name": "Ops"}}}' > session.json
SESSION=$(python -c "import json; print(json.load(open('session.json'))['session_id'])")
TOKEN=$(python -c "import json; print(json.load(open('session.json'))['form']['access_token'])")
# Trạng thái phiên
curl -s http://localhost:8080/o3o/embed/session/$SESSION -H "Authorization: Bearer $TOKEN"
# Đổi chế độ
curl -s -X POST http://localhost:8080/o3o/embed/session/$SESSION/mode \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{"mode": "edit"}'
# Đóng phiên (204)
curl -s -o /dev/null -w "%{http_code}\n" -X DELETE http://localhost:8080/o3o/embed/session/$SESSION -H "Authorization: Bearer $TOKEN"// Gọi từ máy chủ Node.js 18+ (không có header Origin, PostMessageOrigin = O3O_PUBLIC_URL)
const res = await fetch("http://localhost:8080/o3o/embed/session", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ token: signedToken }) // chỉ gửi token: gate dùng document, editor, ui trong token
});
const session = await res.json();
if (!res.ok) throw new Error(session.error.code + ": " + session.error.message);
console.log(session.session_id, session.mode, session.limited);/o3o/embed/files/{doc_id}?v={n}&exp={unix}&sig={hex}Tải phiên bản n của tài liệu (Content-Disposition: attachment).
Tham số truy vấn
vintegerbắt buộcSố phiên bản (0 là bản gốc).expsố, giây Unixbắt buộcHạn của liên kết. Quá hạn:410 link_expired.sighexbắt buộcChữ ký do gate tạo. Sai:403 invalid_signature. Phiên bản đã dọn:410 version_gone.
# download_url trả về từ GET phiên, hoặc url trong callback / onSaved
curl -f -o v3.docx "http://localhost:8080/o3o/embed/files/doc_9835f61009fc659dfedab8696f2d2665?v=3&exp=1790086400&sig=<sig>"CORS#
Gate trả Access-Control-Allow-Origin bằng đúng Origin của yêu cầu khi origin đó nằm trong O3O_EMBED_ALLOWED_ORIGINS (hoặc danh sách là *); OPTIONS trả Access-Control-Allow-Methods: GET, POST, DELETE, OPTIONS, Access-Control-Allow-Headers: Content-Type, Authorization, Access-Control-Max-Age: 600. Yêu cầu không có Origin (từ máy chủ, curl) vẫn được nhận.
Endpoint của trang thử (chỉ máy DEV)#
| Yêu cầu | Tác dụng |
|---|---|
GET /o3o/demo | Trang thử dùng api.js, mở sample.docx, ghi mọi sự kiện, có nút gọi từng phương thức. |
GET /o3o/demo/sample.docx | Tệp mẫu tiếng Việt nằm sẵn trong image. |
POST /o3o/demo/callback | Nhận callback, kiểm chữ ký, giữ 20 bản gần nhất trong bộ nhớ. |
GET /o3o/demo/callbacks | Danh sách callback đã nhận, dạng JSON. |