> ## Documentation Index
> Fetch the complete documentation index at: https://yuno-3979e326-fix-create-subscription-card-usage.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# React Native Headless

> Build a completely custom UI for your payments with the Headless integration.

<Warning>
  **Orientation: Choosing Your Integration Flow**, before you begin, please review the [Official Integration Flow](/docs/sdks/overview/understanding-flows).

  * **Standard Flow ([Full Checkout](/docs/sdks/full-checkout/web-payments))**: Recommended for most merchants. Yuno handles the UI, security, and automatic updates for payment methods.
  * **Custom Flow (This SDK)**: Use this only if you require full control over the UX. **Note**: You will be responsible for manually handling payment statuses, 3DS transitions, and fraud routing data collection.
</Warning>

Build completely custom payment forms with full UI control when you need complete control over every UI element, highly custom checkout experiences, or have development resources for custom UI.

## Integration workflow

```typescript theme={null}
import { YunoSdk } from '@yuno-payments/yuno-sdk-react-native';

const CustomPaymentForm = () => {
  const [cardNumber, setCardNumber] = useState('');
  const [expiry, setExpiry] = useState('');
  const [cvv, setCvv] = useState('');
  
  const processPayment = async () => {
    try {
      // 1. Use headless API to generate a one-time token
      const result = await YunoSdk.generateToken({
        checkoutSession: 'session_id',
        paymentMethod: {
          type: 'CARD',
          card: {
            number: cardNumber,
            expirationMonth: parseInt(expiry.split('/')[0]),
            expirationYear: parseInt(expiry.split('/')[1]),
            securityCode: cvv,
            holderName: 'John Doe',
            type: 'CREDIT',
          },
        },
      }, 'session_id', 'US');
      
      
      // 2. Create payment with token on your backend
      await createPayment(result.token);
      
      // 3. Handle 3DS if needed - use getThreeDSecureChallenge
      const challengeResult = await YunoSdk.getThreeDSecureChallenge('session_id', 'US');
      if (challengeResult.type === 'URL') {
        // Open 3DS URL in WebView, then continue payment
        await YunoSdk.continuePayment('session_id', 'US', true);
      }
      
    } catch (error) {
      console.error('Payment error:', error);
    }
  };
  
  return (
    <View>
      <TextInput
        placeholder="Card Number"
        value={cardNumber}
        onChangeText={setCardNumber}
      />
      <TextInput
        placeholder="MM/YY"
        value={expiry}
        onChangeText={setExpiry}
      />
      <TextInput
        placeholder="CVV"
        value={cvv}
        onChangeText={setCvv}
        secureTextEntry
      />
      <Button title="Pay" onPress={processPayment} />
    </View>
  );
};
```

## Handling 3DS

For headless integrations, you must manually trigger the 3DS challenge if the payment requires authentication.

1. After creating the payment on your backend, if the status is `WAITING_FOR_ACTION`, call `YunoSdk.getThreeDSecureChallenge`.
2. If a URL is returned, display it to the user.
3. Once the user completes the challenge, call `YunoSdk.continuePayment` to finalize the transaction.
