Caputchin
연동 가이드

모바일 앱 연동

Caputchin은 호스팅된 임베드 페이지를 통해 네이티브 앱 안에서 돌아갑니다. WebView를 그 페이지로 향하게 하면, 방문자가 그 안에서 챌린지를 풀고, 페이지는 그 결과 토큰(그리고 모든 오류)을 당신의 네이티브 코드로 연결합니다. 검증 자체는 웹과 동일하며, 호스트 셸만 다릅니다.

1. 임베드 페이지 열기

WebView를 최소한 사이트 키를 담아 https://caputchin.com/embed로 향하게 하세요:

https://caputchin.com/embed?sitekey=cpt_pub_...&game=caputchin/games/leaf-memory

순수 체크박스를 원하면 게임 파라미터를 생략하세요. games=a,b 목록은 세션마다 하나를 무작위로 고릅니다.

쿼리 파라미터

파라미터필수효과
sitekey당신의 공개 키(cpt_pub_...). 없으면 위젯 없는 오류 셸을 렌더링합니다.
game아니요단일 마켓플레이스 게임 id(owner/repo, 또는 owner/repo/leaf).
games아니요쉼표로 구분된 목록; 세션마다 하나를 무작위로 고릅니다.
game-src아니요자체 호스팅 게임을 위한, 당신이 직접 호스팅한 게임 번들의 URL.
layout아니요inline, modal, fullscreen, 또는 auto. 임베드에서는 기본값이 inline.
locale / skin / config아니요언어, 스킨, 또는 구성을 고르도록 위젯에 전달됩니다.
no-verify아니요검증 게이트 없이 게임을 실행합니다(게임만, 토큰 없음).
postMessageTarget아니요브라우저 iframe 임베더 전용(아래 참고). 네이티브 WebView에서는 무시됩니다.

순수 체크박스를 원하면 game / games / game-src 셋을 모두 생략하세요. mode 파라미터는 없습니다; 위젯이 트리거를 스스로 몰아갑니다.

2. 토큰을 당신의 코드로 연결하기

방문자가 통과하면, 임베드 페이지는 당신의 호스트에 맞는 채널을 통해 토큰을 밀어 보냅니다. 맞는 핸들러를 등록하세요.

iOS (WKWebView, Swift)

토큰은 caputchin이라는 메시지 핸들러에 날 문자열로 도착합니다:

class TokenHandler: NSObject, WKScriptMessageHandler {
  func userContentController(_ controller: WKUserContentController,
                             didReceive message: WKScriptMessage) {
    guard let token = message.body as? String else { return }
    // send `token` to your backend
  }
}

let config = WKWebViewConfiguration()
config.userContentController.add(TokenHandler(), name: "caputchin")
let webView = WKWebView(frame: .zero, configuration: config)
webView.load(URLRequest(url: URL(string: "https://caputchin.com/embed?sitekey=cpt_pub_...&game=caputchin/games/leaf-memory")!))

Android (WebView, Kotlin)

토큰은 caputchin이라는 @JavascriptInterface에 날 문자열로 도착합니다:

class TokenBridge {
  @JavascriptInterface
  fun onToken(token: String) {
    // send `token` to your backend
  }
}

webView.settings.javaScriptEnabled = true
webView.addJavascriptInterface(TokenBridge(), "caputchin")
webView.loadUrl("https://caputchin.com/embed?sitekey=cpt_pub_...&game=caputchin/games/leaf-memory")

React Native (react-native-webview)

임베드는 단일 React Native 채널에 JSON 문자열을 post합니다. 그것을 파싱해 type으로 분기하세요:

<WebView
  source={{ uri: "https://caputchin.com/embed?sitekey=cpt_pub_...&game=caputchin/games/leaf-memory" }}
  onMessage={(e) => {
    const msg = JSON.parse(e.nativeEvent.data);
    if (msg.type === "caputchin-token") {
      // send msg.token to your backend
    } else if (msg.type === "caputchin-error") {
      // msg.code, msg.message, msg.originalCode (optional)
    }
  }}
/>

브라우저 iframe (postMessage)

페이지를 네이티브 WebView가 아니라 브라우저 <iframe>에 임베드한다면, 부모 릴레이는 기본적으로 꺼져 있으며 ?postMessageTarget=<origin>을 통해 정확한 대상 오리진으로 옵트인할 때만 발동합니다(예: postMessageTarget=https://app.example.com). 와일드카드(*), 경로, 또는 맨 스킴·호스트·포트로 파싱되지 않는 무엇이든 거부되니, 일회용이며 사이트에 묶인 토큰이 검증되지 않은 부모로 브로드캐스트되는 일은 결코 없습니다. 부모에서 수신 대기하고, 메시지를 신뢰하기 전에 event.origin을 확인하세요:

window.addEventListener("message", (event) => {
  if (event.origin !== "https://embed-host.example.com") return;
  const msg = event.data;
  if (msg.type === "caputchin-token") {
    // msg.token
  } else if (msg.type === "caputchin-error") {
    // msg.code, msg.message
  }
});

3. 백엔드에서 검증하기

이것은 웹과 같습니다: 토큰을 당신의 시크릿과 함께 /siteverify로 POST하세요. 서버 측 연동을 보세요.

오류 받기 (선택)

위젯이 오류에 부딪힐 때마다, 임베드 페이지는 그것을 병렬 채널 묶음을 통해 그대로 비춥니다: iOS caputchinError 메시지 핸들러, Android caputchinError 인터페이스(onError(json)), { type: "caputchin-error", ... }로서의 React Native 채널, 그리고 같은 게이트된 iframe 릴레이. 페이로드는 { code, message, originalCode? }를 담습니다. iOS와 Android는 그것을 JSON 문자열로 받고; React Native와 iframe 릴레이는 타입 지정된 봉투를 받습니다.

이것은 전적으로 선택입니다. 오류 핸들러를 등록하지 않는 앱은 그저 오류를 받지 않으며, 임베드 페이지는 어쨌든 이미 WebView 안에서 재시도 UI를 보여 줍니다.

함께 보기

이 페이지에서