Skip to content

Electron SDK

Electron SDK 完全运行在 主进程,通过操作系统原生窗口呈现验证码 UI。渲染进程不参与校验流程——为了安全请保持这种隔离。

GitHub 上的示例

📦

Captcha-La/electron-demo — 完整可运行示例,包含所有集成步骤。

安装

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

快速开始

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 一览

符号用途
new CaptchalaClient({...})创建一次性客户端。传入 appKeyserverTokenactionlangthemetimeoutMsretryCount,以及事件处理函数。
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

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": "<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: falsecontextIsolation: 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)

MIT-licensed examples · CaptchaLa is operated independently