Caputchin
Guides d'intégration

Intégration dans les apps mobiles

Caputchin tourne dans une app native via une page d'embed hébergée. Tu pointes une WebView vers cette page, le visiteur réussit l'épreuve à l'intérieur, et la page fait le pont du token résultant (et de toute erreur) vers ton code natif. La vérification elle-même est identique au web ; seul le shell hôte diffère.

1. Ouvre la page d'embed

Pointe une WebView vers https://caputchin.com/embed avec au moins une clé de site :

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

Omets les paramètres de jeu pour la simple case à cocher. Une liste games=a,b en choisit un au hasard par session.

Paramètres de requête

ParamètreRequisEffet
sitekeyouiTa clé publique (cpt_pub_...). Manquante, elle affiche un shell d'erreur sans widget.
gamenonUn id unique de jeu du marketplace (owner/repo, ou owner/repo/leaf).
gamesnonUne liste séparée par des virgules ; un est choisi au hasard par session.
game-srcnonURL de ton propre bundle de jeu hébergé, pour un jeu auto-hébergé.
layoutnoninline, modal, fullscreen ou auto. Par défaut inline sur l'embed.
locale / skin / confignonTransmis au widget pour choisir une langue, un skin ou une configuration.
no-verifynonExécute le jeu sans gate de vérification (jeu seul, pas de token).
postMessageTargetnonIntégrateurs en iframe de navigateur uniquement (voir ci-dessous). Ignoré dans une WebView native.

Omets les trois game / games / game-src pour la simple case à cocher. Il n'y a pas de paramètre mode ; le widget pilote le déclencheur lui-même.

2. Fais le pont du token vers ton code

Quand le visiteur passe, la page d'embed pousse le token par le canal qui correspond à ton hôte. Enregistre le handler correspondant.

iOS (WKWebView, Swift)

Le token arrive comme une chaîne brute sur un message handler nommé 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)

Le token arrive comme une chaîne brute sur un @JavascriptInterface nommé caputchin :

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)

L'embed poste une chaîne JSON sur l'unique canal React Native. Parse-la et branche sur 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 de navigateur (postMessage)

Si tu intègres la page dans un <iframe> de navigateur plutôt que dans une WebView native, le relais vers le parent est désactivé par défaut et ne se déclenche que si tu actives explicitement une origine cible exacte via ?postMessageTarget=<origin> (par exemple postMessageTarget=https://app.example.com). Un joker (*), un chemin, ou tout ce qui ne se parse pas en un simple schéma, hôte et port nu est rejeté, donc le token à usage unique et lié au site n'est jamais diffusé à un parent non vérifié. Écoute sur le parent et vérifie event.origin avant de faire confiance au message :

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. Vérifie sur ton backend

C'est la même chose que le web : POSTe le token vers /siteverify avec ton secret. Vois Intégration côté serveur.

Recevoir les erreurs (optionnel)

Chaque fois que le widget rencontre une erreur, la page d'embed la reflète à travers un jeu de canaux parallèles : le message handler iOS caputchinError, l'interface Android caputchinError (onError(json)), le canal React Native comme { type: "caputchin-error", ... }, et le même relais iframe gaté. La charge porte { code, message, originalCode? }. iOS et Android la reçoivent comme une chaîne JSON ; React Native et le relais iframe reçoivent l'enveloppe typée.

C'est entièrement optionnel. Une app qui n'enregistre aucun handler d'erreur ne reçoit simplement pas les erreurs, et la page d'embed montre de toute façon une UI de réessai dans la WebView.

Voir aussi

Sur cette page