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

# React Native Giving SDK

> Add authenticated general and campaign giving with Stripe, PayPal, and Flutterwave to a React Native or Expo app.

# Add giving to a React Native app

The `@thefaithapp/giving-react-native` package renders general and campaign
giving inside a React Native or Expo app. It uses the member session from
`@thefaithapp/auth-react-native`, presents the church's active payment
provider, and waits for TheFaithApp to confirm the payment.

The package includes:

* general giving with funds, currency, frequency, memo, and fee coverage
* campaign giving with configured donor form fields
* Stripe PaymentSheet
* hosted PayPal and Flutterwave checkout
* checkout cancellation and expiry handling
* headless checkout and custom payment-handler support

<Note>
  TheFaithApp creates and verifies each checkout and processes provider webhooks.
  Do not add payment-provider secret keys or webhook secrets to your mobile app.
</Note>

## Before you begin

You need:

* an Expo SDK 57 or compatible React Native app
* `@thefaithapp/auth-react-native` configured with a client API key
* a signed-in TheFaithApp member
* an active payment provider configured for the church
* a native development or standalone build

Follow the [React Native SDK Quickstart](/api-reference/react-native-sdk) first
if member sign-in is not working yet.

<Steps>
  <Step title="Install the packages">
    Install the auth and giving SDKs:

    ```bash theme={null}
    npm install @thefaithapp/auth-react-native @thefaithapp/giving-react-native
    ```

    Add the native payment dependencies with Expo-compatible versions:

    ```bash theme={null}
    npx expo install @stripe/stripe-react-native react-native-webview
    npx expo install expo-application expo-crypto expo-secure-store expo-web-browser
    ```
  </Step>

  <Step title="Configure the native plugins">
    Add an application scheme, the auth plugin, and the Stripe plugin to
    `app.json`:

    ```json theme={null}
    {
      "expo": {
        "scheme": "your-church",
        "plugins": [
          "@thefaithapp/auth-react-native",
          [
            "@stripe/stripe-react-native",
            {
              "merchantIdentifier": "merchant.com.example.church",
              "enableGooglePay": false
            }
          ],
          "expo-secure-store",
          "expo-web-browser"
        ],
        "ios": {
          "bundleIdentifier": "com.example.church"
        },
        "android": {
          "package": "com.example.church"
        }
      }
    }
    ```

    Rebuild the native application after changing plugins:

    ```bash theme={null}
    npx expo run:ios
    # or
    npx expo run:android
    ```

    Stripe PaymentSheet cannot run in Expo Go.
  </Step>

  <Step title="Create the authenticated giving client">
    Reuse the auth instance that signs the member in:

    ```tsx theme={null}
    import { TheFaithAppAuth } from '@thefaithapp/auth-react-native'
    import {
      TheFaithAppGiving,
      createStripeGivingPaymentHandler,
    } from '@thefaithapp/giving-react-native'

    const auth = new TheFaithAppAuth({
      apiKey: process.env.EXPO_PUBLIC_THEFAITHAPP_API_KEY!,
    })

    const giving = new TheFaithAppGiving({
      auth,
      paymentHandlers: [
        createStripeGivingPaymentHandler({
          urlScheme: 'your-church',
          returnUrl: 'your-church://stripe-redirect',
        }),
      ],
    })
    ```

    The Stripe override adds the return URL used by redirect and 3DS flows. Its
    provider ID replaces the built-in Stripe handler while PayPal and
    Flutterwave continue to use their built-in handlers.

    Before showing protected giving:

    ```tsx theme={null}
    const session = (await auth.currentSession()) ?? (await auth.signIn())
    console.log(`Giving as ${session.member.name}`)
    ```

    The giving client does not accept a member ID or church/client ID. The
    authenticated session supplies that identity on every request.
  </Step>

  <Step title="Render general giving">
    Add the built-in general giving view to a screen:

    ```tsx theme={null}
    import { GeneralGivingView } from '@thefaithapp/giving-react-native'

    export function GivingScreen() {
      return (
        <GeneralGivingView
          giving={giving}
          onCompleted={(result) => {
            // result.state is succeeded, pending, failed, or cancelled.
          }}
          onError={(error) => {
            // Show a safe message without logging checkout data.
          }}
        />
      )
    }
    ```

    The view loads the church's giving settings and funds. It shows only the
    currencies, recurrence options, memo, and fee coverage allowed by that
    configuration.
  </Step>

  <Step title="Render campaign giving">
    Your app chooses the campaign, then passes its numeric ID to the view:

    ```tsx theme={null}
    import { CampaignGivingView } from '@thefaithapp/giving-react-native'

    export function CampaignScreen({
      campaignId,
    }: {
      campaignId: number
    }) {
      return (
        <CampaignGivingView
          campaignId={campaignId}
          giving={giving}
          onCompleted={(result) => {
            // Handle succeeded, pending, failed, or cancelled.
          }}
        />
      )
    }
    ```

    If the campaign has donor fields, the package renders and validates its
    text, multiline text, number, email, telephone, select, radio, checkbox,
    and date fields.

    Campaign discovery and selection belong to your app. The package begins
    with the campaign ID you provide.
  </Step>
</Steps>

## Payment-provider behavior

The package uses the church's active/default provider. An app does not choose
between Stripe, PayPal, and Flutterwave for an individual gift.

| Provider    | Experience                           |
| ----------- | ------------------------------------ |
| Stripe      | Native PaymentSheet                  |
| PayPal      | Hosted approval in an in-app WebView |
| Flutterwave | Hosted checkout in an in-app WebView |

The result from a native sheet or WebView is not treated as proof of payment.
The SDK checks TheFaithApp's webhook-backed status before reporting the final
state. A `pending` result means the provider or webhook is still processing.

## Campaign fields

The built-in campaign view loads the campaign definition and submits its form
responses with the authenticated checkout. Required fields are validated
before the payment experience opens.

Both giving views accept partial `strings` overrides,
`contentContainerStyle`, `allowRecurring`, and `showMemo`.

## Headless checkout

The rendered views are optional. A custom form can create an authenticated
checkout and render the shared payment host:

```tsx theme={null}
const checkout = await giving.createGeneralCheckout({
  allocations: [{ amount: 25, fundId: 4 }],
  currency: 'USD',
  frequency: 'one_time',
})

<GivingPaymentHandlerHost
  giving={giving}
  checkout={checkout}
  onComplete={setResult}
  onError={setError}
/>
```

For a campaign, call `createCampaignCheckout(campaignId, request)` and include
the campaign's configured values in `request.formFields`.

Keep the host mounted until the provider completes. If your custom UI
dismisses an unrendered checkout, report it:

```tsx theme={null}
await giving.abandonCheckout(checkout)
```

## Add another payment provider

Register a handler whose `provider` matches the value configured on
TheFaithApp:

```tsx theme={null}
import type {
  GivingPaymentHandler,
  GivingPaymentHandlerProps,
} from '@thefaithapp/giving-react-native'

function ChurchPay({
  checkout,
  onComplete,
  onError,
}: GivingPaymentHandlerProps) {
  // Present the provider UI and confirm authoritative checkout status.
  return null
}

const churchPayHandler: GivingPaymentHandler = {
  provider: 'church-pay',
  Component: ChurchPay,
}

const giving = new TheFaithAppGiving({
  auth,
  paymentHandlers: [churchPayHandler],
})
```

A handler receives only one checkout's ephemeral session and narrow completion
capabilities. It does not receive the auth client, client API key, bearer
token, member ID, or church ID.

Never persist or log checkout provider data. A custom handler must complete
with the same donation ID and provider it received.

## Cancellation and cleanup

Closing a payment experience triggers a best-effort checkout abandonment
request. If the device is offline or the app terminates before that request
arrives, TheFaithApp expires the checkout on the server. A late valid webhook
still has a short grace period so a completed payment is not incorrectly
cancelled.

## Troubleshooting

| Problem                              | What to check                                                                                          |
| ------------------------------------ | ------------------------------------------------------------------------------------------------------ |
| Giving says it is unavailable        | Confirm the church has an active/default payment provider and supported giving configuration.          |
| The member is not authenticated      | Restore or create the auth session before rendering the giving view.                                   |
| Stripe does not open                 | Use a native development build, rebuild after adding the plugin, and confirm the Stripe return scheme. |
| The app does not return after 3DS    | Confirm `returnUrl` uses the scheme registered in `app.json`.                                          |
| A campaign cannot be loaded          | Confirm the campaign ID belongs to the signed-in member's church and the campaign is available.        |
| A required campaign field is missing | Render the campaign returned by the package instead of maintaining a separate field definition.        |
| A payment remains pending            | Keep the status message visible; TheFaithApp updates the donation when the provider webhook arrives.   |

## Package resources

* [Package on npm](https://www.npmjs.com/package/@thefaithapp/giving-react-native)
* [Source and standalone example](https://github.com/thefaithapp/thefaithapp-giving-react-native)
