Electron SDK
Electron SDK 는 전적으로 메인 프로세스 에서 실행되며, OS 가 관리하는 네이티브 창으로 CAPTCHA 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() | 네이티브 CAPTCHA 창을 엽니다. 성공 시 결과로 resolve, 치명적 오류 시 reject 합니다. |
onReady / onFail | 생성자에 전달하는 선택적 핸들러. onFail 은 복구 가능한 실패용입니다(SDK 가 재시도). |
result.passToken | 백엔드에서 검증할 토큰. 클라이언트에서는 항상 불투명한 값입니다. |
client.destroy() | 창을 닫고 자원을 해제합니다. 클라이언트 인스턴스 사용 후 반드시 호출하세요. |
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 레퍼런스를 참고하세요.
문제 해결
렌더러에서 SDK 를 import 하지 마세요
@captchala/electron은 메인 프로세스 전용 입니다. 데모의preload.js처럼contextBridge+ipcRenderer.invoke()로 결과를 노출하세요.nodeIntegration: false,contextIsolation: true를 유지하세요.런타임에 모듈을 찾을 수 없음
@captchala/electron은dependencies에 두세요(devDependencies아님). 최종 앱에 번들되어야 하며, electron-builder 같은 도구는 자동으로 포함합니다.CAPTCHA 창이 메인 창 뒤에 뜸
Linux/X11 의 특성입니다. 직접BrowserWindow로 감싼다면parent를 전달하거나,verify()반환 후mainWindow.focus()를 호출하세요.Electron 28+ 필요
데모는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)