Skip to content

Electron SDK

Electron SDK 는 전적으로 메인 프로세스 에서 실행되며, OS 가 관리하는 네이티브 창으로 CAPTCHA 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({...})일회용 클라이언트를 생성합니다. 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을 클라이언트 코드에 노출하지 마세요.

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 레퍼런스를 참고하세요.

문제 해결

  • 렌더러에서 SDK 를 import 하지 마세요
    @captchala/electron메인 프로세스 전용 입니다. 데모의 preload.js 처럼 contextBridge + ipcRenderer.invoke() 로 결과를 노출하세요. nodeIntegration: false, contextIsolation: true 를 유지하세요.

  • 런타임에 모듈을 찾을 수 없음
    @captchala/electrondependencies 에 두세요(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)

MIT-licensed examples · CaptchaLa is operated independently