> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pulseshiga.io/llms.txt
> Use this file to discover all available pages before exploring further.

# React Native checklist

> Validate @pulsebyshiga/collect-react-native in your own app — install, mint a sandbox session, render the payment surface, and verify the lifecycle before you ship.

`@pulsebyshiga/collect-react-native` renders the same Pulse-controlled payment
surface as the [embedded iframe](/render/embedded-iframe), inside a WebView.
Validate it on a real device or emulator before you ship.

## 1. Install

```sh theme={null}
npm install @pulsebyshiga/collect-react-native
```

`react-native-webview` is a peer dependency — install it directly in your
app. For Expo apps: `npx expo install react-native-webview`.

## 2. Mint a session token

Use the same `pulse.collectionSessions.create` flow as any other rendering
model (see [Create a session](/backend/create-session)), from your own
backend — never from the app. For testing, point your backend at a sandbox
key (`sk_test_*`); see [Sandbox](/testing/sandbox).

```ts theme={null}
// Your backend
const session = await pulse.collectionSessions.create(payload, { idempotencyKey });
return { session_token: session.session_token };
```

Fetch it from your app like any other backend endpoint, then hand
`session_token` to `PulseCollectPayment`. Never embed your `sk_` key in the
app.

## 3. Render the payment surface

```tsx theme={null}
import { PulseCollectPayment } from '@pulsebyshiga/collect-react-native';
// peer dep: react-native-webview

<PulseCollectPayment
  sessionToken={sessionToken}
  theme={{ primaryColor: '#083a9a' }}
  onStatusChange={(status, orderId) => console.log('status', status, orderId)}
  onSuccess={(orderId) => onFunded(orderId)} // UX only — credit off the webhook
  onError={(code, message) => report(code, message)}
/>;
```

See [Theming](/render/theming) for every theme token, and [Embedded iframe
(Tier A)](/render/embedded-iframe) for the same model on web.

<Note>
  `onSuccess` is a UX signal only — credit the customer from a verified
  `disbursement.completed` webhook (see [Webhooks](/backend/webhooks)), never
  from a client callback.
</Note>

## 4. Drive the lifecycle in the sandbox

Simulate the deposit → confirmation → disbursement lifecycle against your
sandbox session and watch the WebView react live — see
[Sandbox](/testing/sandbox) for the full event list and the happy path.

## What to verify

<Steps>
  <Step title="The surface mounts and renders">
    The WebView shows the payment surface (deposit address, QR, live quote) with your theme applied, and the panel's height follows its content — no clipped panel, no dead space.
  </Step>

  <Step title="The quote countdown behaves">
    The locked-quote countdown renders and updates; letting it expire and re-locking exercises the same quote lifecycle as on web.
  </Step>

  <Step title="Callbacks fire correctly">
    `onStatusChange` fires on each lifecycle transition; `onSuccess` fires when the order reaches disbursement; `onError` fires on load/session failures.
  </Step>

  <Step title="Copying the deposit address works">
    Copy-to-clipboard works from inside the WebView.
  </Step>

  <Step title="Edge states render on device">
    Underpay, wrong-chain, and expiry banners render correctly inside the WebView.
  </Step>

  <Step title="Unmounting is clean">
    Removing the component tears down the WebView with no dangling listeners or state updates.
  </Step>
</Steps>
