Electron SDK
Electron SDK 完全运行在 主进程,通过操作系统原生窗口呈现验证码 UI。渲染进程不参与校验流程——为了安全请保持这种隔离。
GitHub 上的示例
📦
Captcha-La/electron-demo — 完整可运行示例,包含所有集成步骤。
安装
npm install @captchala/electronThe package targets Electron 28+ (the demo pins ^33.0.0) and Node 18+. Run the demo end-to-end with:
npm install
npm start快速开始
// 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());// 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 一览
| 符号 | 用途 |
|---|---|
new CaptchalaClient({...}) | 创建一次性客户端。传入 appKey、serverToken、action、lang、theme、timeoutMs、retryCount,以及事件处理函数。 |
await client.verify() | 打开原生验证码窗口。成功 resolve 返回结果,硬错误 reject。 |
onReady / onFail | 可选的构造函数回调。onFail 表示 可恢复 的失败(SDK 会自动重试)。 |
result.passToken | 用于服务端校验的 token,对客户端始终是不透明的。 |
client.destroy() | 关闭窗口并释放资源。每个 client 实例使用完毕后都应调用。 |
CaptchalaClient.version() | 静态方法,返回 SDK 版本字符串。适合放在支持 / 调试浮层中。 |
服务端校验
把 result.passToken(或 result.token)发到你的后端,再调用 CaptchaLa API 校验。绝不要在客户端代码中暴露 X-App-Secret。
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": "<result.passToken>", "client_ip": "<end-user IP>" }完整校验接口及 X-App-Key / X-App-Secret 流程见 API 参考。
常见问题
不要在 renderer 中 import SDK
@captchala/electron只能在主进程使用。像 demo 的preload.js那样,通过contextBridge+ipcRenderer.invoke()暴露结果。保持nodeIntegration: false、contextIsolation: true。运行时找不到模块
@captchala/electron应放在dependencies(不是devDependencies),它必须打包进最终应用。electron-builder 等工具会自动包含。验证码窗口出现在主窗口后面
这是 Linux/X11 的常见问题。如果你包了一层BrowserWindow,传入parent;或在verify()返回后调用mainWindow.focus()。需要 Electron 28+
demo 中声明electron: ^33.0.0。更老的 Electron 缺少 SDK 依赖的 API;请固定到28+与 Node 18+。
环境要求
- Electron 28+ (the demo uses 33.x)
- Node 18+
- Cross-platform: macOS, Windows 10 1809+, Linux (X11 / Wayland)