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-memoryOmets 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ètre | Requis | Effet |
|---|---|---|
sitekey | oui | Ta clé publique (cpt_pub_...). Manquante, elle affiche un shell d'erreur sans widget. |
game | non | Un id unique de jeu du marketplace (owner/repo, ou owner/repo/leaf). |
games | non | Une liste séparée par des virgules ; un est choisi au hasard par session. |
game-src | non | URL de ton propre bundle de jeu hébergé, pour un jeu auto-hébergé. |
layout | non | inline, modal, fullscreen ou auto. Par défaut inline sur l'embed. |
locale / skin / config | non | Transmis au widget pour choisir une langue, un skin ou une configuration. |
no-verify | non | Exécute le jeu sans gate de vérification (jeu seul, pas de token). |
postMessageTarget | non | Inté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
- Intégration côté serveur pour la vérification du token.
- Intégration côté client pour l'équivalent web.