> ## 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.

# Flutter Giving SDK

> Add authenticated general and campaign giving with Stripe, PayPal, and Flutterwave to a Flutter app.

# Add giving to a Flutter app

The `thefaithapp_giving` package renders general and campaign giving inside
your Flutter app. It uses the member session from `thefaithapp_auth`, 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
* an extension point for future payment providers

<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:

* a Flutter app targeting Android or iOS
* `thefaithapp_auth` configured with a client API key
* a signed-in TheFaithApp member
* an active payment provider configured for the church

Follow the [Flutter SDK Quickstart](/api-reference/flutter-sdk) first if member
sign-in is not working yet.

<Steps>
  <Step title="Add the packages">
    Add the auth and giving packages to `pubspec.yaml`:

    ```yaml theme={null}
    dependencies:
      thefaithapp_auth: ^0.1.0
      thefaithapp_giving: ^0.1.0
    ```

    Install them:

    ```bash theme={null}
    flutter pub get
    ```

    The giving package includes `flutter_stripe` and `webview_flutter`. Stop
    and rebuild the app after adding it so Flutter can register their native
    platform code.
  </Step>

  <Step title="Check the native project">
    Keep the platform requirements from the auth SDK:

    * Android `minSdk` 24 or newer
    * iOS 13.0 or newer
    * Keychain Sharing enabled for the iOS Runner target

    Complete any additional native configuration required by
    `flutter_stripe` for the platforms and wallet features your app enables.
    PayPal and Flutterwave use an in-app WebView and do not require provider
    credentials in the application.
  </Step>

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

    ```dart theme={null}
    import 'package:thefaithapp_auth/thefaithapp_auth.dart';
    import 'package:thefaithapp_giving/thefaithapp_giving.dart';

    const clientKey = String.fromEnvironment('TFA_CLIENT_KEY');

    final auth = TheFaithAppAuth(apiKey: clientKey);
    final giving = TheFaithAppGiving(auth: auth);
    ```

    Before showing protected giving:

    ```dart theme={null}
    final session = await auth.currentSession() ?? await auth.signIn();
    print('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 page:

    ```dart theme={null}
    GivingView.general(
      giving: giving,
      onCompleted: (result) {
        switch (result.state) {
          case GivingPaymentState.succeeded:
            // Show a thank-you state.
            break;
          case GivingPaymentState.pending:
            // Tell the member that confirmation is still processing.
            break;
          case GivingPaymentState.failed:
          case GivingPaymentState.cancelled:
            // Keep the member on a safe retry or dismissal path.
            break;
        }
      },
    )
    ```

    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:

    ```dart theme={null}
    GivingView.campaign(
      giving: giving,
      campaignId: 42,
      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.

If you build a headless campaign form, send the same values with
`CampaignGivingRequest.formFields`. Do not collect or send fields that are not
part of the campaign definition.

## Recurring gifts

When recurring giving is enabled for the church and supported by its active
provider, the general and campaign views can create a recurring gift.

You can load and cancel the signed-in member's subscriptions:

```dart theme={null}
final subscriptions = await giving.getSubscriptions();

if (subscriptions.isNotEmpty) {
  await giving.cancelSubscription(subscriptions.first);
}
```

The platform scopes each subscription to its general or campaign target and
rechecks the member and church before cancellation.

## Add another payment provider

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

```dart theme={null}
final giving = TheFaithAppGiving(
  auth: auth,
  paymentHandlers: [MyPaymentHandler()],
);
```

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

Never persist or log `GivingCheckoutSession` provider data. A custom handler
must return 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.

## Dispose the clients

Dispose both package instances when their owning application service is
released:

```dart theme={null}
giving.dispose();
auth.dispose();
```

## 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                 | Perform a full native rebuild and complete the `flutter_stripe` platform setup.                      |
| 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 pub.dev](https://pub.dev/packages/thefaithapp_giving)
* [Source and standalone example](https://github.com/thefaithapp/thefaithapp-giving-flutter)
