Mục lục thư viện
Thư viện tài liệuBắt đầu theo ngôn ngữ
Bắt đầu với Node.js và Electron
Bài này đưa một chương trình Node.js từ con số không tới lần kích hoạt license đầu tiên, rồi tới lúc đóng gói cho khách: cài SDK, vài dòng mã, chạy thử, xem kết quả trên dashboard, xử lý lỗi và phát hành. Phần cuối dành riêng cho Electron.
6 phút đọc
Cần có
- Node.js 20 trở lên. SDK là ES module thuần JavaScript, không có mô-đun native, không kéo theo gói nào khác.
- Một ứng dụng trên dashboard. Trang Tích hợp › Kết nối phần mềm của nó có địa chỉ API, App ID, khoá công khai và nút Tạo key thử nghiệm. Địa chỉ API kết thúc bằng
/api, không có/v1:https://<trang ClavisAUH của bạn>/api.
1. Cài SDK
Tải clavisauh-sdk-js-0.1.0.tgz ở trang Tải về, kiểm SHA-256 như trang đó hướng dẫn, đặt file vào thư mục dự án rồi cài:
npm install ./clavisauh-sdk-js-0.1.0.tgz
Gói mang tên @clavisauh/sdk và có sẵn khai báo kiểu TypeScript. Nếu file bạn tải có số phiên bản mới hơn, đổi tên file trong lệnh cho khớp. SDK chưa có trên npm; khi có, bài này sẽ ghi thêm cách cài từ đó.
Muốn chạy thử trước khi đụng vào dự án của mình? Nút Tải dự án mẫu (.zip) ở trang Kết nối phần mềm cho một thư mục có sẵn SDK, năm kịch bản K1 tới K5 và script chạy đã điền cài đặt của ứng dụng.
2. Mã tối thiểu
Các khối dưới đây là từng phần của một file; file đầy đủ, kèm import và hàm phụ, ở bước 3.
Tạo client một lần khi phần mềm khởi động. baseUrl, appId và appPublicKey là ba giá trị ở trang Kết nối phần mềm: mẫu đọc chúng từ biến môi trường, phần mềm của bạn thì ghi thẳng vào mã. Khoá thiết bị nằm trong một file; phiên và token offline gắn với khoá này, còn suất trên license đi theo các định danh đã băm của máy:
const client = new ClavisClient({
baseUrl: env.CLAVIS_BASE_URL,
appId: env.CLAVIS_APP_ID,
appPublicKey: env.CLAVIS_APP_KEY,
device: defaultDevice(),
// The same key every run: sessions and offline tokens stay with this machine.
deviceKey: loadOrCreateDeviceKey(join(STATE, "device.key")),
appVersion: "1.0.0",
});
Kích hoạt key của khách. Khi không có mạng, token offline lưu lần trước giữ phần mềm chạy tiếp:
let grant = null;
try {
await client.init();
grant = await client.activate(env.CLAVIS_LICENSE);
} catch (err) {
if (!(err instanceof ClavisError)) throw err;
// No answer (network_error, timeout...): a token saved last time keeps the software working.
const offline = err.retryable && existsSync(SAVED) ? client.verifyOffline(readFileSync(SAVED, "utf8")) : null;
if (!offline) {
console.log(err.userMessage(LANG));
console.log("FAIL", err.code);
process.exit(1);
}
console.log("Offline: using the license saved on this machine");
}
Khoá công khai chỉ dùng để kiểm chữ ký, nhúng vào phần mềm là an toàn. Đừng bao giờ nhúng một khoá bí mật nào.
3. Chạy thử
- Ở trang Kết nối phần mềm, bấm Tạo key thử nghiệm. Key TEST hết hạn sau 24 giờ và không tính hạn mức.
- Lưu file đầy đủ dưới đây thành
k1_key.mjs(dự án mẫu có sẵn file này), đặt bốn cài đặt rồi chạy:
// K1 · License key only: activate on this machine, keep the session alive, work offline for a while.
// Run: CLAVIS_BASE_URL=... CLAVIS_APP_ID=... CLAVIS_APP_KEY=... CLAVIS_LICENSE=... node k1_key.mjs
import { existsSync, readFileSync, writeFileSync } from "node:fs";
import { join } from "node:path";
import { ClavisClient, ClavisError } from "@clavisauh/sdk";
import { defaultDevice, loadOrCreateDeviceKey } from "@clavisauh/sdk/node";
const env = process.env;
const LANG = env.CLAVIS_LANG ?? "en";
const STATE = env.CLAVIS_STATE_DIR ?? ".clavis";
const SAVED = join(STATE, "offline.token");
const client = new ClavisClient({
baseUrl: env.CLAVIS_BASE_URL,
appId: env.CLAVIS_APP_ID,
appPublicKey: env.CLAVIS_APP_KEY,
device: defaultDevice(),
// The same key every run: sessions and offline tokens stay with this machine.
deviceKey: loadOrCreateDeviceKey(join(STATE, "device.key")),
appVersion: "1.0.0",
});
let grant = null;
try {
await client.init();
grant = await client.activate(env.CLAVIS_LICENSE);
} catch (err) {
if (!(err instanceof ClavisError)) throw err;
// No answer (network_error, timeout...): a token saved last time keeps the software working.
const offline = err.retryable && existsSync(SAVED) ? client.verifyOffline(readFileSync(SAVED, "utf8")) : null;
if (!offline) {
console.log(err.userMessage(LANG));
console.log("FAIL", err.code);
process.exit(1);
}
console.log("Offline: using the license saved on this machine");
}
if (grant) {
console.log("License", grant.license.status, "until", grant.license.expiresAt ?? "forever");
// Every few minutes while the software runs; sessions end after an hour without one.
const beat = await client.heartbeat();
if (beat.offlineToken ?? grant.offlineToken) writeFileSync(SAVED, beat.offlineToken ?? grant.offlineToken);
await client.logout();
}
console.log("OK k1", grant ? grant.license.status : "offline");
export CLAVIS_BASE_URL="<địa chỉ API>"
export CLAVIS_APP_ID="<App ID>"
export CLAVIS_APP_KEY="<khoá công khai>"
export CLAVIS_LICENSE="<key thử nghiệm>"
node k1_key.mjs
Trên Windows, trong PowerShell:
$env:CLAVIS_BASE_URL = "<địa chỉ API>"
$env:CLAVIS_APP_ID = "<App ID>"
$env:CLAVIS_APP_KEY = "<khoá công khai>"
$env:CLAVIS_LICENSE = "<key thử nghiệm>"
node k1_key.mjs
Mẫu in License active until <ngày>, rồi OK k1 active ở dòng cuối. Chạy lại trên cùng máy vẫn thành công và không tốn thêm suất: server nhận ra máy qua các định danh đã băm (Thiết bị, HWID và chuyển máy). Khoá thiết bị, dùng để ký yêu cầu, nằm trong thư mục .clavis dưới thư mục bạn chạy lệnh (hoặc trong CLAVIS_STATE_DIR). Container tạo mới cho mỗi lần chạy thì lần nào cũng giống một máy mới, xem Câu hỏi thường gặp.
4. Thấy trên dashboard
- Tích hợp › Kết nối phần mềm: bước 4 chuyển sang Đã kết nối, kèm
js/0.1.0và hệ điều hành của máy. - Phát hành & bản quyền › License: key chuyển từ Chưa dùng sang Đang dùng.
- Người dùng cuối › Thiết bị & phiên: máy vừa chạy, cùng phiên nó vừa mở.
5. Xử lý lỗi
Mọi lần bị từ chối là một ClavisError có ba thứ bạn cần:
code: mã trong bảng Mã lỗi, ví dụinvalid_credentialshaydevice_limit.userMessage("vi"): câu cho người dùng phần mềm của bạn, tiếng Việt hoặc"en", hiện thẳng được.retryable:truekhi không nhận được câu trả lời (mất mạng, quá chậm, máy chủ bận); để một lúc rồi thử lại có thể thành công.
Câu trả lời không mang đúng chữ ký của ứng dụng bị từ chối bằng ClavisVerificationError (cũng là một ClavisError), với mã unsigned_response, invalid_response_signature, unknown_key hoặc stale_response. Hãy coi đó như không có câu trả lời; thường là địa chỉ API hoặc khoá công khai trong phần mềm bị sai.
Khi phần mềm đang chạy, gửi heartbeat đều đặn để giữ phiên, khoảng mỗi 5 tới 30 phút: phiên hết sau 60 phút không có heartbeat.
// Every few minutes while the software runs; sessions end after an hour without one.
const beat = await client.heartbeat();
Lưu token offline mới nhất, để lần sau không có mạng vẫn mở được:
if (beat.offlineToken ?? grant.offlineToken) writeFileSync(SAVED, beat.offlineToken ?? grant.offlineToken);
Mọi gói đều có token offline, mặc định dùng được 7 ngày; Premium tự chọn thời hạn, còn Chế độ chỉ online thì tắt hẳn. Xem License offline.
6. Đóng gói và phát hành
- Ghi địa chỉ API, App ID và khoá công khai vào mã hoặc vào file cấu hình đi cùng bản build. Máy khách không cần biến môi trường nào.
- Đặt thư mục trạng thái (khoá thiết bị, token offline) ở nơi người dùng ghi được, riêng cho từng người dùng:
%APPDATA%\TênPhầnMềmtrên Windows,~/Library/Application Support/TênPhầnMềmtrên macOS,~/.config/ten-phan-memtrên Linux. Đừng đặt trong thư mục cài đặt. - Truyền
appVersionđúng phiên bản bạn phát hành: server dùng nó để chặn bản quá cũ và báo có bản mới, xem Bản phát hành có ký và cập nhật. - Bundler (esbuild, webpack, Vite) và công cụ đóng gói Node nhận SDK như mọi mã JavaScript khác: không có gì phải build lại cho từng hệ điều hành.
- Trước khi bán, bật Đã phát hành công khai ở Tích hợp › Cài đặt ứng dụng. Mọi key TEST ngừng hoạt động, nên key thử nào lỡ lọt ra ngoài cũng không dùng được nữa.
Với Electron
- Gọi SDK ở main process.
@clavisauh/sdk/nodeđọc thông tin máy và ghi file, việc của main process; renderer chỉ nhận kết quả (trạng thái license, câu báo lỗi) qua IPC, với preload vàcontextBridge. - Thư mục trạng thái:
path.join(app.getPath("userData"), "clavis"). - SDK là ES module. Main process dạng ES module (Electron 28 trở lên) import thẳng như mẫu; main process CommonJS thì nạp bằng
const { ClavisClient } = await import("@clavisauh/sdk"). - electron-builder và Electron Forge đóng gói SDK cùng
node_modulesnhư mọi gói JavaScript, kể cả khi dùngapp.asar. Thư mục trạng thái nằm ởuserData, ngoài gói ứng dụng, nên vẫn ghi được.
Câu hỏi thường gặp
Phần mềm có cần mạng mỗi lần mở không? Kích hoạt và heartbeat cần mạng. Khi mất mạng, token đã lưu giữ phần mềm chạy tiếp, mặc định 7 ngày hoặc theo thời hạn chọn trên Premium, được kiểm ngay trên máy mà không cần server.
Khách cài lại hệ điều hành hay đổi máy thì sao? Cài lại trên cùng máy, server vẫn nhận ra máy nhờ dấu nhận diện phần cứng đã băm. Máy mới chiếm một suất mới; hết suất thì khách nhận device_limit, và bạn Đặt lại thiết bị trong trang License. Xem Thiết bị, HWID và chuyển máy.
Dùng SDK trong trình duyệt được không? Phần chính @clavisauh/sdk chạy được trong trình duyệt (trang Kết nối phần mềm dùng nó cho nút thử), còn @clavisauh/sdk/node chỉ chạy trong Node.js và Electron. ClavisAUH làm cho phần mềm cài trên máy, nơi khoá thiết bị được giữ lại.
Dùng với TypeScript được không? Được. Gói kèm khai báo kiểu; Grant, ClavisOptions và các kiểu khác đều được export.
Muốn xem toàn bộ API? SDK JavaScript liệt kê mọi tuỳ chọn và phương thức; Hệ thống hoạt động thế nào giải thích từng lượt gọi của mỗi kịch bản.