# Flutter SDK integration

A guide to integrating the Peach Orchestration mobile SDK into a Flutter app using Dart and the `peachpayments_flutter` package. Minimum: Flutter 3.0+, Dart 2.17+ (iOS 15.1, Android minSdk 21).

## What this page covers
- Ten sections: Prerequisites, Installation, Configuration, Basic integration, Payment methods, Saved cards, Error handling, Customisation, Testing, Troubleshooting
- Flutter/Dart prerequisites and getting Dashboard credentials (publishable key `pk_snd_xxx`/`pk_prd_xxx`)
- Adding the `peachpayments_flutter` dependency and per-platform setup (Podfile, `build.gradle`, `apply_plugins`)
- Initialising the SDK and presenting the payment sheet with a `client_secret` from your backend
- Payment methods, direct wallet buttons (`PeachWalletButton`), saved cards, and theming with `PaymentSheetAppearance`
- Handling the `presentPaymentSheet()` result map, testing and troubleshooting

## Key steps / API

All packages are on pub.dev at **1.1.0**:

| Package | Notes |
|---|---|
| `peachpayments_flutter` | the SDK — payment sheet + saved payment methods |
| `peachpayments_flutter_netcetera_3ds` | optional — links Netcetera 3-D Secure |
| `peachpayments_flutter_scancard` | optional — links card scanning |
| `peachpayments_flutter_airborne` | not published yet (blocked) |

```yaml
dependencies:
  peachpayments_flutter: ^1.1.0
  peachpayments_flutter_netcetera_3ds: ^1.1.0   # optional
  peachpayments_flutter_scancard: ^1.1.0        # optional
```

Then `flutter pub get`. The **Android setup step** is `dart run peachpayments_flutter:apply_plugins` — re-run it after every upgrade. On iOS the plugin pulls in `peachpayments-hyperswitch-ios/sentry`, so the Podfile still needs both pod sources (see [iOS SDK](/sdk-mobile-ios.md)).

Migrating from the upstream plugin: package `flutter_hyperswitch` → `peachpayments_flutter`, Dart class `FlutterHyperswitch` → `PeachPayments`, Android namespace `io.hyperswitch.flutter_hyperswitch` → `io.peachpayments.flutter`.

```dart
import 'package:peachpayments_flutter/peachpayments_flutter.dart';

final _peach = PeachPayments();

// 1. Initialise once at app startup
_peach.init(HyperConfig(
  publishableKey: 'pk_test_your_publishable_key',
  customBackendUrl: 'https://app.sandbox-next.peachpayments.com/api',
));

// 2. Initialise the session with a client secret from your server
await _peach.initPaymentSession(PaymentSheetParams(
  clientSecret: checkoutData.clientSecret,
));

// 3. Present the payment sheet (returns Map<String, dynamic>?)
final result = await _peach.presentPaymentSheet();
```

Other real API surface referenced in the source:
- `PeachPayments()` — the SDK instance
- `HyperConfig(publishableKey, customBackendUrl)` — initialisation config
- `PaymentSheetParams(clientSecret: ...)` — session parameters
- `presentPaymentSheet()` returns a `Map<String, dynamic>?` result you inspect for status
- Theming: `PaymentSheetAppearance` with `PaymentSheetColors`, `PaymentSheetShapes`, `PaymentSheetTypography`, `PaymentSheetPrimaryButton`

### Direct wallet buttons

`PeachWalletButton` embeds a branded Apple Pay / Google Pay button in your own checkout, with no payment sheet:

```dart
PeachWalletButton(
  clientSecret: clientSecret,
  type: WalletButtonType.expressCheckout,   // or .googlePay / .applePay
  googlePay: const GooglePayButtonConfig(
    merchantName: 'Your Store', merchantCountryCode: 'ZA',
  ),
  onReady: (isReady) => setState(() => _walletReady = isReady),
  onResult: (result) { /* result.status */ },
)
```

**Breaking host requirement:** on Android your `MainActivity` must extend `FlutterFragmentActivity`, not `FlutterActivity` — the button attaches a fragment and will otherwise fail. Mount the button only after `initPaymentSession` has completed. `controller.confirm()` starts the payment programmatically.

The button may render nothing: availability is decided by the SDK (wallet enabled for the merchant, connector returns a session token, wallet usable on the device), and it collapses to zero height — a normal empty state, not an error. Use `onReady` as the usability signal and keep a card fallback.

Sandbox API base is `https://app.sandbox-next.peachpayments.com/api`; production is `https://app.next.peachpayments.com/api`. Always `await initPaymentSession` before calling `presentPaymentSheet`. If builds break, `flutter clean && flutter pub get`. Mobile SDK V2 wallets require merchant-owned credentials (Apple Pay certificates, Google Pay merchant ID, Samsung Pay service ID/certificates); see the iOS and Android guides.

The plugin wraps the native SDKs, so the Android host also needs the Peach Maven registry and Gradle plugin 0.2.9 — see [Android SDK](/sdk-mobile-android.md).

## Related
- [iOS SDK](/sdk-mobile-ios.md): the native iOS layer Flutter wraps
- [Android SDK](/sdk-mobile-android.md): the native Android layer Flutter wraps
- [Web SDK](/sdk-web.md): browser integration
- [API Playground](/playground.md): create a payment intent and get a `client_secret`
- [Testing](/docs/testing.md): test cards and sandbox guidance

---

Interactive version: https://playground.peachpayments.com/sdk-mobile/flutter
