Bắt đầu
Trao đổi session token
Điều xảy ra ở mỗi lần tải trang: server của bạn lấy mã 60 giây bằng License key, trình duyệt đổi mã đó lấy session token, rồi Viewer tải mô hình đã mã hoá. Các request, phản hồi và mã lỗi.
Bài này nói về cách dùng mã nhúng, trong đó bạn viết một route trên server của mình. Với WordPress và Shopify, plugin và ứng dụng tự thực hiện các lời gọi này (xem Ba cách tích hợp).
License key chỉ nằm trên server của bạn. Mỗi lần tải trang cần hai request đến từ hai nơi khác nhau. Server của bạn xin Comnoira một mã sống 60 giây và chỉ dùng được một lần. Sau đó trình duyệt của khách đổi mã đó lấy session token mà Viewer dùng. Cần cả hai request vì Comnoira kiểm tra trình duyệt đang ở website nào, và chỉ request từ trình duyệt mới chứng minh được điều đó.
Phiên bản văn bản của sơ đồ
- Trình duyệt và SDK → Máy chủ của bạn: Gọi endpoint của bạn (getSessionToken)
- Máy chủ của bạn → API Comnoira: POST /viewer/session X-License-Key
- API Comnoira → Máy chủ của bạn: Trao đổi mã, expiresIn 60
- Máy chủ của bạn → Trình duyệt và SDK: Chỉ gửi mã, không bao giờ gửi License key
- Trình duyệt và SDK → API Comnoira: POST /session/exchange Header Origin
- API Comnoira → Trình duyệt và SDK: Session token
- Trình duyệt và SDK → Trình xem (iframe): Mở iframe cùng session token
- Trình xem (iframe) → API Comnoira: POST /viewer/bootstrap
- Trình xem (iframe) → API Comnoira: GET /viewer/assets/{id}/url
- API Comnoira → Trình xem (iframe): Liên kết có chữ ký và ID session key
- Trình xem (iframe) → API Comnoira: GET /viewer/key/{id}
- API Comnoira → Trình xem (iframe): Session key, nonce, 60 giây
- Trình xem (iframe) → Kho lưu trữ mô hình: Tệp đã mã hóa (liên kết có chữ ký)
- Trình duyệt và SDK → API Comnoira: POST /session/refresh khoảng 60 giây trước khi hết hạn
- API Comnoira → Trình duyệt và SDK: Session token mới
Bước 1: server của bạn xin mã trao đổi
Server của bạn gọi API Comnoira với License key trong header X-License-Key. Body chứa publicKey và Showcase ID của Showcase cần hiển thị.
curl -X POST https://api.comnoira.com/api/v1/viewer/session \
-H "X-License-Key: $COMNOIRA_LICENSE_KEY" \
-H "Content-Type: application/json" \
-d '{"publicKey": "pk_live_xxx", "showcaseId": "SHOWCASE_ID"}'
Body còn nhận thêm viewerUid (tuỳ chọn). Phản hồi không phải session token dùng được ngay. Đó là một mã chỉ dùng một lần:
{
"sessionToken": "6f1c2a9e-0000-0000-0000-000000000000",
"expiresIn": 60,
"viewerUid": null
}
Trường này tên là sessionToken nhưng chứa mã trao đổi, và expiresIn là 60 giây. Hãy xin mã mới ở mỗi lần tải trang. Đừng cache mã và đừng dùng lại.
Backend từ chối request, trước khi cấp mã, trong các trường hợp sau. Mỗi phản hồi có dạng {"success": false, "error": {"code": "...", "message": "..."}}.
LICENSE_KEY_MISSING(HTTP 403): thiếu headerX-License-Key.LICENSE_KEY_INVALID(400): License key không hợp lệ.LICENSE_INACTIVE(400): license không hoạt động hoặc đã quá ngày hết hạn.LICENSE_KEY_SHOP_MISMATCH(403): License key thuộc shop khác với Showcase.SHOWCASE_NOT_FOUND(404): không có Showcase đang hoạt động với Showcase ID này.- HTTP 400 không kèm mã riêng: publicKey không thuộc Showcase ID đó.
SHOWCASE_NOT_ACTIVATED(400): shop của bạn chưa được kích hoạt. Comnoira là bên kích hoạt. Trước đó hãy dùng Preview.SHOWCASE_NOT_IN_PRODUCTION(409): Showcase là demo hoặc Preview. License key chỉ cấp session cho Showcase production.RATE_LIMITED(429): quá nhiều request từ một địa chỉ server. Giới hạn trong Backend là 2000 request trong 15 phút.
Bước 2: trang của bạn khởi động SDK
Route của bạn trả mã về trình duyệt, và SDK lấy mã từ hàm getSessionToken của bạn. Lời gọi là Comnoira.init(publicKey, showcaseId, options). Tên cũ ThreeHub là cùng một đối tượng và vẫn dùng được.
<div id="comnoira-viewer" style="height: 600px"></div>
<script src="https://cdn.comnoira.com/sdk/v1/3dhub.min.js"></script>
<script>
Comnoira.init("pk_live_xxx", "SHOWCASE_ID", {
container: "comnoira-viewer",
getSessionToken: function () {
return fetch("/your-backend-route")
.then(function (res) { return res.json(); })
.then(function (data) { return data.sessionToken; });
},
});
</script>
Dashboard tạo sẵn đoạn mã này cho Showcase của bạn bằng HTML, React, Vue và Angular, kèm route phía server bằng Node.js, Python, PHP và Java. Hãy copy từ đó, vì đoạn mã đã điền sẵn publicKey và Showcase ID của bạn.
options chứa đúng một trong ba thứ, và init báo lỗi khi không có hoặc có nhiều hơn một.
getSessionToken: hàm trả về mã, dạng chuỗi hoặc đối tượng{ sessionToken }. Dùng cho ứng dụng một trang và cho mọi trang lấy mã ngay trong trình duyệt. SDK gọi lại hàm này mỗi khi cần mã mới.sessionToken: mã mà server của bạn đã đặt sẵn vào trang. Dùng cho trang render phía server. Mã sống 60 giây, nên trang phải được render cho đúng khách đó và mở ngay. Bản trang bị cache hoặc tải lại mang mã đã dùng và lỗi vớiEXCHANGE_TOKEN_INVALID. Chỉ cósessionTokenthì SDK không xin được mã mới, và khi phiên kết thúc SDK phátVIEWER_SESSION_EXPIREDđể trang của bạn tự quyết định.demo: true: xem Bắt đầu dùng Liftmira. Chỉ chạy trên các origin Comnoira đã liệt kê.
container là id của một phần tử, viết không có #. SDK không nhận chính phần tử đó. Nếu id không tồn tại, init lỗi với Container #id not found. Nếu bỏ container, SDK thêm một div vào cuối body của trang, mặc định rộng 100% và cao 500px.
init trả về một promise bị reject khi không dựng được phiên. SDK cũng phát VIEWER_ERROR với { code, message, fatal }, trong đó code là một trong các mã nêu trong bài này. Route của bạn lỗi, hoặc mất mạng, hiện ra là SERVICE_UNAVAILABLE.
Bước 3: SDK đổi mã
SDK gửi mã từ trình duyệt của khách:
POST https://api.comnoira.com/api/v1/viewer/session/exchange
{ "exchangeToken": "6f1c2a9e-..." }
Trình duyệt tự đặt header Origin bằng origin của chính trang, và script trên trang không đổi được giá trị đó. Backend kiểm tra theo thứ tự: tốc độ request, mã chưa dùng và chưa hết hạn, Showcase còn hoạt động, origin được phép, và license còn hoạt động. Nếu qua hết, Backend trả session token:
{
"sessionToken": "eyJ...",
"expiresIn": 3600,
"viewerUid": "..."
}
expiresIn là thời lượng phiên của gói license, hoặc thời gian còn lại của license nếu ngắn hơn. Giá trị ở trên chỉ là ví dụ, không phải giá trị cố định. SDK lưu viewerUid trong local storage của trình duyệt với khoá 3dhub_uid, để khách quay lại giữ được thiết lập của họ.
Các lỗi ở bước này:
EXCHANGE_TOKEN_INVALID(HTTP 403): mã không tồn tại, đã dùng hoặc quá 60 giây. Backend không phân biệt ba trường hợp này.ORIGIN_NOT_ALLOWED(403): domain của trang không có trong danh sách domain được phép của Showcase, hoặc request không có headerOrigin.SHOWCASE_NOT_FOUND(404),LICENSE_INACTIVE(400): Showcase hoặc license đã đổi giữa hai bước.RATE_LIMITED(429): một địa chỉ IP được đổi 30 mã trong 15 phút. Khách cùng sau một địa chỉ văn phòng dùng chung giới hạn này.
Bước kiểm tra origin chỉ so tên host. Scheme và cổng không tính. Mục shop.example.com khớp đúng host đó. Mục *.example.com khớp example.com và mọi subdomain. Dashboard còn có chế độ Mở, bỏ qua bước kiểm tra, chỉ nên dùng để thử nghiệm.
SDK không thử lại bước đổi mã khi gặp 429 hoặc 503, vì mã đã dùng. SDK phát VIEWER_SERVER_BUSY với willRetry: false để trang của bạn thông báo.
Bước 4: Viewer tải mô hình
SDK mở viewer.comnoira.com trong một iframe và truyền session token cho nó. Viewer sau đó hỏi Backend về Showcase và nội dung. Với mỗi file mô hình, Viewer làm như sau.
- Hỏi địa chỉ của file. Backend trả một liên kết có chữ ký tới file đã mã hoá và id của một session key.
- Hỏi session key theo id đó. Backend chỉ đưa mỗi session key một lần, và key có hiệu lực 60 giây.
- Tải file đã mã hoá và giải mã ngay trong trình duyệt bằng session key đó.
File được lưu dưới dạng mã hoá, nên chỉ có liên kết thì chưa xem được mô hình.
Giữ phiên không bị ngắt
Khoảng 60 giây trước khi session token hết hạn, SDK gửi nó tới POST /api/v1/viewer/session/refresh. Lời gọi này không cần License key. Nó qua cùng bước kiểm tra origin như bước đổi mã, và token cũ ngừng dùng được khi token mới được cấp. Nếu refresh lỗi và bạn có đưa getSessionToken, SDK gọi hàm đó để lấy mã mới rồi đổi lại. Nếu refresh lỗi mà bạn không đưa hàm đó, SDK thử tổng cộng ba lần, cách nhau 5 giây rồi 10 giây, sau đó phát VIEWER_SESSION_EXPIRED.
Khi Backend trả 429 hoặc 503 kèm header Retry-After ở bước refresh, SDK chờ đúng khoảng đó rồi thử lại, tối đa hai lần, và phát VIEWER_SERVER_BUSY mỗi lần.
Vì sao request thứ hai do trình duyệt gửi
Header Origin trên request từ server của bạn là giá trị người gửi tự viết, nên nó không cho biết gì về trang. Trình duyệt tự điền header này, nên bước đổi mã là request duy nhất mà Comnoira thấy được website nào đang hỏi. Mã trao đổi là một giá trị đục, API không chấp nhận nó làm thông tin đăng nhập, nên mã bị lộ không mở được Viewer sau 60 giây hoặc sau lần dùng thứ hai.
Nếu Viewer trống hoặc hiện lỗi, xem Xử lý sự cố.
