flutter_stripe_connect

A Flutter plugin for Stripe Connect embedded components. Easily integrate account onboarding, account management, payouts, payments, and more into your Flutter app.

pub package License: MIT

Features

  • Account Onboarding - Collect connected account information with a pre-built UI
  • Account Management - Let connected accounts manage their account settings
  • Payments - Show payment history for connected accounts
  • Payouts - Display payout history and status for connected accounts
  • Balances - Show balance information and payout controls
  • Notification Banner - Display required actions for compliance
  • Documents - Show documents available for download
  • Tax Settings - Allow connected accounts to configure tax settings
  • Tax Registrations - Manage tax registrations
  • Disputes List - View and manage disputes
  • Payment Details - Show detailed payment information
  • Payout Details - Show detailed payout information
  • Payouts List - Filterable list of payouts
  • WebView Mode - Optional self-hosted web rendering for full component access
  • Customizable Appearance - Configure colors, fonts, and corner radius

Platform Support

Platform Supported
Android ✅
iOS ✅
Web ✅

Component Availability by Platform

Component iOS Native Android Native Web Mobile WebView
Account Onboarding ✅ ✅ ✅ Optional
Payments ✅ ✅ ✅ Optional
Payouts ✅ ✅ ✅ Optional
Account Management ✅ ❌ ✅ Required on Android
Notification Banner ❌ ❌ ✅ Required
Balances ❌ ❌ ✅ Required
Documents ❌ ❌ ✅ Required
Tax Settings ❌ ❌ ✅ Required
Tax Registrations ❌ ❌ ✅ Required
Disputes List ❌ ❌ ✅ Required
Payment Details ❌ ❌ ✅ Required
Payout Details ❌ ❌ ✅ Required
Payouts List ❌ ❌ ✅ Required

Legend:

  • ✅ Native SDK supported - uses platform-native component by default
  • ❌ No native SDK - requires WebView mode on mobile
  • Optional: Component supports both native and WebView (use useWebView: true to force WebView)
  • Required: Component requires webViewConfig to work on mobile

See doc/WEBVIEW_INTEGRATION.md for WebView mode setup.

Installation

Add flutter_stripe_connect to your pubspec.yaml:

dependencies:
  flutter_stripe_connect: ^0.5.0

Platform Setup

Android Setup

Important: Your MainActivity must extend FlutterFragmentActivity (not FlutterActivity) for the Stripe Connect components to work properly.

Update your android/app/src/main/kotlin/.../MainActivity.kt:

package com.example.yourapp

import io.flutter.embedding.android.FlutterFragmentActivity

class MainActivity : FlutterFragmentActivity()

iOS Setup

Important: add NSCameraUsageDescription to your ios/Runner/Info.plist. Embedded components capture identity documents with the camera, and the StripeConnect SDK asserts on this key when the component manager is created — without it a debug build stops there.

<key>NSCameraUsageDescription</key>
<string>This app uses your camera to take a photo of your identity documents.</string>

The plugin ships both a podspec and a Package.swift, so it works under CocoaPods and under Swift Package Manager. Either way the app has to target iOS 15.0 or later.

Troubleshooting: If pod install fails on the first try, run:

cd ios/
pod install --repo-update

Web Setup

Add the Connect.js script to your web/index.html inside the <head> tag:

<script src="https://connect-js.stripe.com/v1.0/connect.js" async></script>

CSP Requirements: If you're using Content Security Policy headers, allow these Stripe domains:

  • https://connect-js.stripe.com
  • https://js.stripe.com

Usage

1. Initialize the SDK

import 'package:flutter_stripe_connect/flutter_stripe_connect.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  await StripeConnect.instance.initialize(
    publishableKey: 'pk_test_...',
    clientSecretProvider: () async {
      // Fetch client secret from your server
      final response = await http.post(
        Uri.parse('https://your-server.com/create-account-session'),
      );
      return jsonDecode(response.body)['client_secret'];
    },
  );
  
  runApp(MyApp());
}

1b. Enable WebView Mode (Optional)

For full component access on mobile (including Tax, Capital, Issuing), use WebView mode:

await StripeConnect.instance.initialize(
  publishableKey: 'pk_test_...',
  clientSecretProvider: () async {
    final response = await http.post(
      Uri.parse('https://your-server.com/create-account-session'),
    );
    return jsonDecode(response.body)['client_secret'];
  },
  webViewConfig: WebViewConfig(
    baseUrl: 'https://connect.yourapp.com',  // Your hosted web app
    theme: 'light',
    primaryColor: '#635BFF',
    // Optional: Customize URL parameter names if your web app uses different names
    // publishableKeyParam: 'pk',      // defaults to 'publishableKey'
    // clientSecretParam: 'secret',    // defaults to 'clientSecret'
  ),
);

Note: WebView mode requires hosting your own Next.js app. See doc/WEBVIEW_INTEGRATION.md for setup guide.

2. Use the Embedded Components

Account Onboarding

Option A: Embed as Widget

StripeAccountOnboarding(
  onLoaded: () => print('Onboarding loaded'),
  onLoadError: (error) => print('Error: $error'),
  onExit: () => print('User exited onboarding'),
  // Uses native SDK by default on iOS/Android
  // Set useWebView: true to force WebView rendering
)

Option B: Present Programmatically (New in 0.3.0)

Trigger onboarding from your own UI without embedding the widget:

ElevatedButton(
  onPressed: () async {
    await StripeConnect.presentAccountOnboarding(
      onExit: () {
        print('User exited onboarding');
        // Navigate back or refresh state
      },
      onLoadError: (error) {
        print('Error: $error');
        // Show error dialog
      },
    );
  },
  child: Text('Start Onboarding'),
)

Note: presentAccountOnboarding() is only supported on iOS and Android. On Web, use the StripeAccountOnboarding widget.

Collecting more than what is currently due

Onboarding always collects currently_due requirements. Anything Stripe defers is left out — for a US individual, the date of birth and the last four digits of the social security number are only due as the account approaches its first payouts, so an onboarding run early in your flow never asks for them. Pass collectionOptions to pull them forward:

await StripeConnect.presentAccountOnboarding(
  collectionOptions: const AccountCollectionOptions(
    fields: AccountFieldOption.eventuallyDue,
    futureRequirements: AccountFutureRequirementOption.include,
  ),
);

Collecting more than what is currently due is subject to Stripe's policy instructions.

Your own agreements, and your own title

For connected accounts where your platform is responsible for collecting requirements, you can put your own agreements in place of Stripe's links and take terms acceptance through your own flow:

await StripeConnect.presentAccountOnboarding(
  title: context.l10n.onboardingTitle,
  fullTermsOfServiceUrl: 'https://example.com/terms',
  recipientTermsOfServiceUrl: 'https://example.com/recipient-terms',
  privacyPolicyUrl: 'https://example.com/privacy',
  collectionOptions: const AccountCollectionOptions(
    excludeTermsOfService: true,
  ),
);

Both sets of options are also available on the StripeAccountOnboarding widget. title applies to native platforms only — on web the component has no title bar of its own. Excluding terms acceptance hides it from onboarding; your platform must collect and record acceptance separately. On Android, the native SDK does not expose requirement restrictions to plugin callers, so the plugin uses the equivalent terms collection flag. The older skipTermsOfServiceCollection argument remains available but is deprecated.

Account Management

StripeAccountManagement(
  onLoaded: () => print('Account management loaded'),
  onLoadError: (error) => print('Error: $error'),
)

Payments

StripePayments(
  onLoaded: () => print('Payments loaded'),
  onLoadError: (error) => print('Error: $error'),
)

Payouts

StripePayouts(
  onLoaded: () => print('Payouts loaded'),
  onLoadError: (error) => print('Error: $error'),
)

Balances

StripeBalances(
  onLoaded: () => print('Balances loaded'),
  onLoadError: (error) => print('Error: $error'),
)

Tax Settings (Web Only)

StripeTaxSettings(
  onLoaded: () => print('Tax settings loaded'),
  onLoadError: (error) => print('Error: $error'),
)

Disputes List

StripeDisputesList(
  onLoaded: () => print('Disputes loaded'),
  onLoadError: (error) => print('Error: $error'),
)

3. Customize Appearance (Optional)

Appearance belongs to the Stripe instance rather than to an individual component, so it is set once at initialization and applies everywhere:

await StripeConnect.instance.initialize(
  publishableKey: 'pk_test_...',
  clientSecretProvider: fetchClientSecret,
  appearance: const ConnectAppearance(
    fontFamily: 'Roboto',
    cornerRadius: 12.0,
    colors: ConnectColors(
      primary: '#635BFF',
      background: '#FFFFFF',
      text: '#1A1A1A',
    ),
  ),
);

Restyle later — following the app's theme, for instance — with updateAppearance, which also reaches the components already on screen:

await StripeConnect.instance.updateAppearance(
  const ConnectAppearance(colors: ConnectColors(background: '#111111')),
);

Colors are hex strings. On native platforms #RGB and #RRGGBB are accepted; alpha is not, because CSS reads #RRGGBBAA while Android reads #AARRGGBB. cornerRadius is a base radius in pixels.

Fonts

fontFamily reaches only as far as naming a family. Every embedded component renders in a web context — a WKWebView on iOS, a WebView on Android, an iframe on web — and that context does not inherit the fonts of the app around it. Each SDK therefore takes the font file through a channel of its own: EmbeddedComponentManager(fonts:) on iOS, customFonts on Android, the fonts option of loadConnectAndInitialize on web. The plugin does not expose any of the three, so a font your app bundles will not render. Stay with a system family, and check it on each platform you ship: iOS, Android and a desktop browser do not carry the same ones. The Roboto above is an Android system font.

iOS differs in one respect: the family is resolved through UIFont(name:) before it is handed to the SDK, so the generic CSS families (sans-serif, serif, monospace) that Android and web accept are rejected there and fall back to -apple-system. Name a concrete font rather than a generic family.

Note: the deprecated appearance argument on individual component widgets has no effect. Set it through initialize or updateAppearance instead.

Server-Side Setup

To use Stripe Connect embedded components, create an Account Session on your server. Authenticate the caller, resolve their connected account on the server, and enable only the components and features their role permits. This Node.js example illustrates the component configuration; supply your own authentication and account lookup:

const stripe = require('stripe')('sk_test_...');

app.post('/create-account-session', async (req, res) => {
  const connectedAccountId = await getConnectedAccountIdForAuthenticatedUser(req);
  const accountSession = await stripe.accountSessions.create({
    account: connectedAccountId,
    components: {
      account_onboarding: { enabled: true },
      account_management: { enabled: true },
      payments: { 
        enabled: true,
        features: {
          refund_management: true,
          dispute_management: true,
          capture_payments: true,
        }
      },
      payouts: { 
        enabled: true,
        features: {
          instant_payouts: true,
          standard_payouts: true,
        }
      },
      balances: { enabled: true },
      tax_settings: { enabled: true },
      tax_registrations: { enabled: true },
      documents: { enabled: true },
      notification_banner: { enabled: true },
    },
  });
  
  res.json({ client_secret: accountSession.client_secret });
});

Requirements

  • Flutter SDK >=3.44.0
  • Dart SDK >=3.12.0 <4.0.0
  • Android: minSdk 24, compileSdk 36
  • iOS: iOS 15.0+
  • Web: Modern browsers (Chrome, Firefox, Safari, Edge)

Documentation

License

MIT License - see LICENSE for details.

Libraries

flutter_stripe_connect
Flutter Stripe Connect - A Flutter plugin for Stripe Connect embedded components
flutter_stripe_connect_web
Web plugin registration for Flutter Stripe Connect