--- title: Electron SDK --- # Electron SDK SDK Electron chạy hoàn toàn trong **tiến trình chính (main process)**, mở cửa sổ CAPTCHA gốc do hệ điều hành quản lý. Tiến trình renderer không tham gia quy trình xác thực — hãy giữ sự cô lập này để bảo mật. ## Demo trên GitHub ::: tip 📦 [Captcha-La/electron-demo](https://github.com/Captcha-La/electron-demo) — ví dụ đầy đủ, có thể chạy được, kèm mọi bước tích hợp. ::: ## Cài đặt ```bash npm install @captchala/electron ``` The package targets **Electron 28+** (the demo pins `^33.0.0`) and **Node 18+**. Run the demo end-to-end with: ```bash npm install npm start ``` ## Bắt đầu nhanh ```js // main.js (Electron main process — never the renderer) const { app, BrowserWindow, ipcMain } = require('electron'); const path = require('path'); const { CaptchalaClient } = require('@captchala/electron'); let currentClient = null; ipcMain.handle('verify', async (event, opts) => { // 1. Fetch a one-shot server_token from YOUR backend. const serverToken = await fetchServerTokenFromYourBackend(opts.action); // 2. Tear down any prior client, then build a fresh one. if (currentClient) { currentClient.destroy(); currentClient = null; } currentClient = new CaptchalaClient({ appKey: 'YOUR_APP_KEY', serverToken, action: opts.action, // 'login' | 'register' | 'pay' | … lang: opts.lang, // 'en' | 'zh-CN' | 'ja' | … theme: opts.theme, // 'light' | 'dark' timeoutMs: 15000, retryCount: 3, onReady: () => event.sender.send('captcha-status', 'ready'), onFail: (e) => event.sender.send('captcha-status', `recoverable: ${e.code}`), }); try { const result = await currentClient.verify(); // Send result.passToken to YOUR backend for validation. return { success: true, passToken: result.passToken }; } catch (err) { return { success: false, error: err.message }; } finally { if (currentClient) { currentClient.destroy(); currentClient = null; } } }); function createWindow() { const win = new BrowserWindow({ width: 520, height: 640, resizable: false, webPreferences: { preload: path.join(__dirname, 'preload.js'), contextIsolation: true, nodeIntegration: false, }, }); win.loadFile('index.html'); } app.whenReady().then(createWindow); app.on('window-all-closed', () => app.quit()); ``` ```js // preload.js — bridge the renderer to the main-process verify(). const { contextBridge, ipcRenderer } = require('electron'); contextBridge.exposeInMainWorld('captchala', { verify: (opts) => ipcRenderer.invoke('verify', opts), onStatus: (callback) => ipcRenderer.on('captcha-status', (_, msg) => callback(msg)), }); ``` ## API chính | Ký hiệu | Mục đích | | --- | --- | | `new CaptchalaClient({...})` | Tạo client dùng một lần. Truyền `appKey`, `serverToken`, `action`, `lang`, `theme`, `timeoutMs`, `retryCount` cùng các handler sự kiện. | | `await client.verify()` | Mở cửa sổ CAPTCHA native. Trả về resolve khi thành công, reject khi lỗi nghiêm trọng. | | `onReady` / `onFail` | Handler tuỳ chọn truyền vào constructor. `onFail` dành cho lỗi *có thể phục hồi* (SDK sẽ tự thử lại). | | `result.passToken` | Token để xác thực ở backend. Luôn ở dạng opaque đối với client. | | `client.destroy()` | Đóng cửa sổ và giải phóng tài nguyên. Luôn gọi sau khi dùng xong một client instance. | | `CaptchalaClient.version()` | Helper tĩnh trả về chuỗi phiên bản SDK. Hữu ích cho khung hỗ trợ / debug. | ## Xác thực phía máy chủ Chuyển `result.passToken` (hoặc `result.token`) tới backend của bạn rồi xác thực qua API CaptchaLa. **Tuyệt đối không để lộ `X-App-Secret` trong mã client**. ```bash POST https://apiv1.captcha.la/v1/validate X-App-Key: YOUR_APP_KEY X-App-Secret: YOUR_APP_SECRET Content-Type: application/json { "pass_token": "" } ``` Xem [Tài liệu API](../api-reference) để biết chi tiết endpoint xác thực và quy trình `X-App-Key` / `X-App-Secret`. ## Khắc phục sự cố - **Đừng import SDK trong renderer** `@captchala/electron` **chỉ dùng ở main process**. Hãy phơi kết quả qua `contextBridge` + `ipcRenderer.invoke()` như `preload.js` của demo. Giữ `nodeIntegration: false` và `contextIsolation: true`. - **Không tìm thấy module lúc chạy** `@captchala/electron` thuộc `dependencies`, không phải `devDependencies` — phải được đóng gói vào ứng dụng cuối. electron-builder tự động bao gồm nó. - **Cửa sổ CAPTCHA mở phía sau cửa sổ chính** Đây là đặc điểm Linux/X11. Nếu bạn tự bọc `BrowserWindow`, hãy truyền `parent`, hoặc gọi `mainWindow.focus()` sau khi `verify()` trả về. - **Yêu cầu Electron 28+** Demo khai báo `electron: ^33.0.0`. Electron cũ có thể thiếu API mà SDK cần; hãy ghim `28+` và Node 18+. ## Yêu cầu - Electron 28+ (the demo uses 33.x) - Node 18+ - Cross-platform: macOS, Windows 10 1809+, Linux (X11 / Wayland)