Integração com apps móveis
O Caputchin roda dentro de um app nativo por meio de uma página de embed hospedada. Você aponta um WebView para essa página, o visitante resolve o desafio dentro dela, e a página leva o token resultante (e qualquer erro) de volta ao seu código nativo. A verificação em si é idêntica à da web; só o shell anfitrião difere.
1. Abra a página de embed
Aponte um WebView para https://caputchin.com/embed com ao menos uma chave de site:
https://caputchin.com/embed?sitekey=cpt_pub_...&game=caputchin/games/leaf-memoryOmita os parâmetros de jogo para a checkbox simples. Uma lista games=a,b escolhe um ao acaso por sessão.
Parâmetros de query
| Parâmetro | Obrigatório | Efeito |
|---|---|---|
sitekey | sim | Sua chave pública (cpt_pub_...). Ausente, renderiza um shell de erro sem widget. |
game | não | Um único id de jogo do marketplace (owner/repo, ou owner/repo/leaf). |
games | não | Uma lista separada por vírgulas; um é escolhido ao acaso por sessão. |
game-src | não | URL do seu próprio bundle de jogo hospedado, para um jogo auto-hospedado. |
layout | não | inline, modal, fullscreen ou auto. O padrão é inline no embed. |
locale / skin / config | não | Encaminhados ao widget para escolher um idioma, skin ou configuração. |
no-verify | não | Roda o jogo sem portão de verificação (só o jogo, sem token). |
postMessageTarget | não | Só para quem embuta em iframe de navegador (veja abaixo). Ignorado em um WebView nativo. |
Omita os três game / games / game-src para a checkbox simples. Não há parâmetro mode; o widget conduz o gatilho sozinho.
2. Leve o token até seu código
Quando o visitante passa, a página de embed empurra o token pelo canal que combina com seu anfitrião. Registre o handler correspondente.
iOS (WKWebView, Swift)
O token chega como uma string crua em um message handler chamado 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)
O token chega como uma string crua em um @JavascriptInterface chamado 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)
O embed posta uma string JSON no canal único do React Native. Faça o parse e ramifique por 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 navegador (postMessage)
Se você embuta a página em um <iframe> de navegador em vez de um WebView nativo, o repasse ao pai vem desligado por padrão e dispara só quando você opta por ele com uma origem-alvo exata via ?postMessageTarget=<origin> (por exemplo postMessageTarget=https://app.example.com). Um curinga (*), um caminho, ou qualquer coisa que não se reduza a um simples esquema, host e porta é rejeitado, de modo que o token de uso único, vinculado ao site, nunca é difundido para um pai não verificado. Escute no pai e cheque event.origin antes de confiar na mensagem:
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. Verifique no seu backend
Isto é o mesmo que na web: faça POST do token em /siteverify com seu segredo. Veja Integração no lado do servidor.
Receber erros (opcional)
Sempre que o widget bate em um erro, a página de embed o espelha por um conjunto paralelo de canais: o message handler caputchinError do iOS, a interface caputchinError do Android (onError(json)), o canal do React Native como { type: "caputchin-error", ... } e o mesmo repasse de iframe protegido. O payload carrega { code, message, originalCode? }. iOS e Android o recebem como string JSON; React Native e o repasse de iframe recebem o envelope tipado.
Isto é totalmente opcional. Um app que não registra nenhum handler de erro simplesmente não recebe erros, e a página de embed já mostra uma UI de retry dentro do WebView de qualquer forma.
Veja também
- Integração no lado do servidor para a conferência do token.
- Integração no lado do cliente para o equivalente web.