npm package: @pok-pay/react-native
Description: POK Pay React Native SDK — WebView card payments and deep-link wallet payments for iOS and Android
Latest version: 0.1.0

# @pok-pay/react-native

Official POK Pay React Native SDK — WebView card payments and deep-link wallet payments for iOS and Android. No native modules beyond `react-native-webview`.

## Installation

```bash
npm install @pok-pay/react-native react-native-webview
```

### iOS — react-native-webview native setup

```bash
cd ios && pod install
```

### Android — react-native-webview native setup

No additional steps required for Android; `react-native-webview` auto-links via Gradle.

> **Important:** `react-native-webview` requires native linking. It is a peer dependency of `@pok-pay/react-native` and must be installed and linked in your app. See the [react-native-webview documentation](https://github.com/react-native-webview/react-native-webview/blob/master/docs/Getting-Started.md) for full setup instructions.
>
> `Linking` from React Native core is used for wallet deep links — no extra installation is needed.

## Environment Config

| Env | App URL (WebView / Deep Link) |
|---|---|
| `staging` | `https://app-staging.pokpay.io` |
| `production` | `https://app.pokpay.io` |

Both components accept an `env` prop: `'staging' | 'production'`.

## Card Payment — PokPaymentWebView

Renders a full-screen `WebView` that loads the POK hosted card form. When the payment completes, POK redirects to your `redirectUrl`; the component intercepts that navigation and calls `onSuccess` instead of following the URL.

```tsx
import React from 'react';
import { StyleSheet, View } from 'react-native';
import { PokPaymentWebView } from '@pok-pay/react-native';

export function CardPaymentScreen({ sdkOrderId }: { sdkOrderId: string }) {
  return (
    <View style={StyleSheet.absoluteFill}>
      <PokPaymentWebView
        sdkOrderId={sdkOrderId}
        env="staging"
        redirectUrl="https://myapp.example.com/payment/success"
        onSuccess={() => {
          // Navigate to your success screen
          console.log('Payment complete!');
        }}
        onError={(error) => {
          console.error('Payment WebView error:', error.message);
        }}
        style={StyleSheet.absoluteFill}
      />
    </View>
  );
}
```

**How it works:**
1. WebView loads `{pokWebUrl}/sdk-orders/{sdkOrderId}` — the POK hosted card form.
2. `onShouldStartLoadWithRequest` intercepts all navigations.
3. When the URL starts with `redirectUrl`, `onSuccess()` is called and navigation is blocked.
4. On any WebView error, `onError(error)` is called.

## Wallet Payment — PokWalletButton

Renders a button that opens the POK app via deep link, then polls your backend for payment completion.

```tsx
import React from 'react';
import { StyleSheet } from 'react-native';
import { PokWalletButton } from '@pok-pay/react-native';

export function WalletPaymentSection({ sdkOrderId }: { sdkOrderId: string }) {
  return (
    <PokWalletButton
      sdkOrderId={sdkOrderId}
      env="staging"
      statusEndpoint="https://your-api.example.com/orders"
      label="Pay with POK Wallet"
      pollInterval={3000}
      pollTimeout={300000}
      onSuccess={() => {
        console.log('Wallet payment complete!');
      }}
      onError={(error) => {
        console.error('Wallet payment error:', error.message);
      }}
      onTimeout={() => {
        console.warn('Wallet payment timed out — user may not have completed payment.');
      }}
      style={styles.walletButton}
      textStyle={styles.walletButtonText}
    />
  );
}

const styles = StyleSheet.create({
  walletButton: {
    backgroundColor: '#6C3FC5',
    borderRadius: 8,
    paddingVertical: 14,
    paddingHorizontal: 24,
    alignItems: 'center',
  },
  walletButtonText: {
    color: '#FFFFFF',
    fontSize: 16,
    fontWeight: '600',
  },
});
```

**How it works:**
1. User presses the button.
2. `Linking.openURL(pokUrl)` opens the POK app on the device.
3. Polling starts: `GET {statusEndpoint}/{sdkOrderId}` every `pollInterval` ms.
4. When the response is `{ status: 'COMPLETED' }`, `onSuccess()` is called.
5. If the overall polling window exceeds `pollTimeout`, `onTimeout()` is called.

**Backend polling endpoint contract:**

Your backend must expose `GET {statusEndpoint}/{sdkOrderId}` and return:

```json
{ "status": "PENDING" | "COMPLETED" | "FAILED" }
```

Example with Express:

```typescript
import { PokPayClient } from '@pok-pay/server-sdk';

const client = new PokPayClient({ env: 'staging', keyId, keySecret, merchantId });

app.get('/orders/:sdkOrderId', authMiddleware, async (req, res) => {
  const { sdkOrderId } = req.params;
  const { isCompleted, status } = await client.getOrderStatus(sdkOrderId);
  res.json({ status: isCompleted ? 'COMPLETED' : status === 'FAILED' ? 'FAILED' : 'PENDING' });
});
```

## API Reference

### `PokPaymentWebView`

| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
| `sdkOrderId` | `string` | Yes | — | The POK SDK order ID to load |
| `env` | `'staging' \| 'production'` | Yes | — | POK environment |
| `redirectUrl` | `string` | Yes | — | Your app's success URL — intercepted by the WebView |
| `onSuccess` | `() => void` | Yes | — | Called when redirectUrl navigation is detected |
| `onError` | `(error: Error) => void` | Yes | — | Called on WebView error |
| `style` | `StyleProp<ViewStyle>` | No | — | Style forwarded to the WebView |

### `PokWalletButton`

| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
| `sdkOrderId` | `string` | Yes | — | The POK SDK order ID |
| `env` | `'staging' \| 'production'` | Yes | — | POK environment |
| `statusEndpoint` | `string` | Yes | — | Base URL for status polling. Polls `GET {statusEndpoint}/{sdkOrderId}` |
| `label` | `string` | No | `'Pay with POK Wallet'` | Button label text |
| `pollInterval` | `number` | No | `3000` | Polling interval in milliseconds |
| `pollTimeout` | `number` | No | `300000` | Total polling timeout in milliseconds (5 minutes) |
| `onSuccess` | `() => void` | Yes | — | Called when polling returns `COMPLETED` |
| `onError` | `(error: Error) => void` | Yes | — | Called on `Linking.openURL` failure or `FAILED` poll status |
| `onTimeout` | `() => void` | Yes | — | Called when polling timeout elapses |
| `style` | `StyleProp<ViewStyle>` | No | — | Style for the `TouchableOpacity` container |
| `textStyle` | `StyleProp<TextStyle>` | No | — | Style for the label `Text` |

### `usePokWalletPoll`

```typescript
usePokWalletPoll(
  sdkOrderId: string,
  statusEndpoint: string,
  options?: { interval?: number; timeout?: number }
): {
  status: 'IDLE' | 'POLLING' | 'COMPLETED' | 'FAILED' | 'TIMEOUT';
  startPolling: () => void;
  stopPolling: () => void;
}
```

Use this hook directly if you need to render your own button UI while still getting the polling state machine.

### `getPokUrl`

```typescript
getPokUrl(env: 'staging' | 'production', sdkOrderId: string): string
```

Returns the full POK web URL for a given order: `{pokWebUrl}/sdk-orders/{sdkOrderId}`.