---
type: how-to
title: Integrasi aplikasi seluler
summary: Sematkan widget di WebView iOS, Android, React Native, atau iframe-peramban, dan jembatani token terverifikasi kembali ke kodemu.
---

Caputchin berjalan di dalam aplikasi native lewat sebuah halaman sematan terhosting. Kamu mengarahkan sebuah WebView ke halaman itu, pengunjung menuntaskan tantangan di dalamnya, dan halaman menjembatani token hasilnya (dan galat apa pun) kembali ke kode native-mu. Verifikasinya sendiri identik dengan web; hanya shell host-nya yang berbeda.

## 1. Buka halaman sematan

Arahkan sebuah WebView ke `https://caputchin.com/embed` dengan setidaknya sebuah kunci situs:

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

Hilangkan parameter game untuk checkbox biasa. Sebuah daftar `games=a,b` memilih satu secara acak per sesi.

<Callout type="warn">
Jika kunci situs punya gerbang game menyala (pengaturan **Wajibkan game untuk verifikasi**-nya), checkbox biasa tak bisa lolos: sematan harus menjalankan sebuah game pada key bergerbang. Lewatkan parameter `game` (atau `games`); sematan checkbox telanjang, tanpa parameter game, memunculkan galat `gate-unavailable` di sana. Ini disengaja, karena gerbang ditegakkan di sisi Caputchin. Lihat [gerbang game](/docs/site-keys/games).
</Callout>

### Parameter kueri

| Parameter | Wajib | Efek |
|---|---|---|
| `sitekey` | ya | Public key-mu (`cpt_pub_...`). Jika hilang, merender shell galat tanpa widget. |
| `game` | tidak | Sebuah id game marketplace tunggal (`owner/repo`, atau `owner/repo/leaf`). |
| `games` | tidak | Sebuah daftar dipisah koma; satu dipilih acak per sesi. |
| `game-src` | tidak | URL bundel game terhosting milikmu sendiri, untuk game swahosting. |
| `layout` | tidak | `inline`, `modal`, `fullscreen`, atau `auto`. Default ke `inline` pada sematan. |
| `overlay-width` / `overlay-height` | tidak | Di `modal` / `fullscreen`, mengatur ukuran dialog game: `full`, angka piksel, atau `auto` (ukuran pilihan game itu sendiri). Lihat [Ukuran dan tata letak](/docs/references/widget-sizing). |
| `locale` / `skin` / `config` | tidak | Diteruskan ke widget untuk memilih bahasa, skin, atau konfigurasi. |
| `no-verify` | tidak | Menjalankan game tanpa gerbang verifikasi (game saja, tanpa token). |
| `postMessageTarget` | tidak | Hanya penyemat iframe-peramban (lihat di bawah). Diabaikan di WebView native. |

Hilangkan ketiga `game` / `games` / `game-src` untuk checkbox biasa. Tak ada parameter `mode`; widget mengemudikan pemicunya sendiri.

## 2. Jembatani token ke kodemu

Saat pengunjung lolos, halaman sematan mendorong token lewat kanal yang cocok dengan host-mu. Daftarkan handler yang cocok.

### iOS (WKWebView, Swift)

Token tiba sebagai string mentah pada sebuah message handler bernama `caputchin`:

```swift
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)

Token tiba sebagai string mentah pada sebuah `@JavascriptInterface` bernama `caputchin`:

```kotlin
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)

Sematan memposting sebuah string JSON pada kanal React Native tunggal. Urai dan cabangkan berdasarkan `type`:

```jsx
<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 peramban (postMessage)

Jika kamu menyematkan halaman di `<iframe>` peramban alih-alih WebView native, relai induk **mati secara baku** dan hanya menyala saat kamu memilih masuk dengan origin target yang persis lewat `?postMessageTarget=<origin>` (misalnya `postMessageTarget=https://app.example.com`). Sebuah wildcard (`*`), sebuah path, atau apa pun yang tak terurai menjadi skema, host, dan port telanjang ditolak, jadi token sekali-pakai yang terikat-situs tak pernah disiarkan ke induk yang tak terverifikasi. Dengarkan di induk dan periksa `event.origin` sebelum memercayai pesan:

```js
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. Verifikasi di backend-mu

Ini sama seperti web: POST token ke `/siteverify` dengan secret-mu. Lihat [Integrasi sisi server](/docs/integration-guides/verify-on-your-backend).

## Menerima galat (opsional)

Kapan pun widget menemui galat, halaman sematan mencerminkannya lewat satu set kanal paralel: message handler iOS `caputchinError`, interface Android `caputchinError` (`onError(json)`), kanal React Native sebagai `{ type: "caputchin-error", ... }`, dan relai iframe bergerbang yang sama. Muatannya membawa `{ code, message, originalCode? }`. iOS dan Android menerimanya sebagai string JSON; React Native dan relai iframe menerima amplop bertipe.

Ini sepenuhnya opsional. Sebuah aplikasi yang tak mendaftarkan handler galat sekadar tak menerima galat, dan halaman sematan toh sudah menampilkan UI coba-lagi di dalam WebView.

## Lihat juga

- [Integrasi sisi server](/docs/integration-guides/verify-on-your-backend) untuk pemeriksaan token.
- [Integrasi sisi klien](/docs/integration-guides/cdn) untuk padanan web-nya.
