Financial Connections
Connect to your users' bank accounts (US bank accounts only)
Financial Connections allows you to connect to your users' bank accounts to access financial data for various use cases like account verification, balance checks, and transaction history.
To learn more about how it works read: Official Stripe Financial Connections docs.
1. Create
First, you need a Stripe account. Register now.
Server-side
This integration requires endpoints on your server that talk to the Stripe API. Use one official libraries for access to the Stripe API from your server. Follow the steps to create an Financial account session here.
Client-side
The Flutter SDK is open source, fully documented.
To install the SDK, follow these steps:
- Run the command
flutter pub add flutter_stripe - This will add a line like this to your project's pubspec.yaml with the latest package version
For details on the latest SDK release and past versions, see the Releases page on GitHub. To receive notifications when a new release is published, watch releases for the repository.
When your app starts, configure the SDK with your Stripe publishable key so that it can make requests to the Stripe API.
void main() async {
Stripe.publishableKey = stripePublishableKey;
runApp(const App());
}
Use your test mode keys while you test and develop, and your live mode keys when you publish your app.
2. Create an account holder. [Server Side]
To attach data to an account holder you must first create one.
For detailed api instructions checkout the official docs.
3. Create a Financial connections session [Server Side]
Before you can retrieve data from a user's bank account through Stripe financial connections, your user must authenticate their account with the authentication flow.
4. Collect Financial Accounts [Client Side]
On the client side you need to receive the session client secret in order to start the authorization flow on mobile.
Option A: Collect Financial Connections Accounts
Use collectFinancialConnectionsAccounts to connect to a user's bank account and retrieve account information:
Future<void> _collectAccount(BuildContext context) async {
// 1. Retrieve the session client secret from your backend
final data = await _fetchFinancialConnectionsSession();
final clientSecret = data['clientSecret'];
// 2. Use the client secret to start the financial connections flow
try {
final result = await Stripe.instance.collectFinancialConnectionsAccounts(
clientSecret: clientSecret,
);
// Handle successful result
setState(() {
response = result.toString();
});
} on Exception catch (e) {
if (e is StripeException) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Error from Stripe: ${e.error.localizedMessage}'),
),
);
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Unforeseen error: $e'),
),
);
}
}
}
The collectFinancialConnectionsAccounts method returns a FinancialConnectionSessionResult when the user completes the modal authentication flow, or throws a StripeException on failure or cancellation.
Option B: Collect Bank Account Token
Use collectBankAccountToken to collect a bank account token that can be used for payments:
Future<void> _collectBankToken(BuildContext context) async {
// 1. Retrieve the session client secret from your backend
final data = await _fetchFinancialConnectionsSession();
final clientSecret = data['clientSecret'];
// 2. Use the client secret to collect a bank token
try {
final result = await Stripe.instance.collectBankAccountToken(
clientSecret: clientSecret,
);
// Handle successful result
setState(() {
response = result.toString();
});
} on Exception catch (e) {
if (e is StripeException) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Error from Stripe: ${e.error.localizedMessage}'),
),
);
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Unforeseen error: $e'),
),
);
}
}
}
The collectBankAccountToken method returns a FinancialConnectionTokenResult containing a bank account token.
5. Complete Example [Client Side]
Here's a complete example showing both methods:
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_stripe/flutter_stripe.dart';
import 'package:http/http.dart' as http;
class FinancialConnectionsScreen extends StatefulWidget {
const FinancialConnectionsScreen({super.key});
@override
State<FinancialConnectionsScreen> createState() =>
_FinancialConnectionsScreenState();
}
class _FinancialConnectionsScreenState
extends State<FinancialConnectionsScreen> {
String response = '';
Future<Map<String, dynamic>> _fetchFinancialConnectionsSession() async {
final url = Uri.parse('$kApiUrl/financial-connections-sheet');
final response = await http.post(
url,
headers: {'Content-Type': 'application/json'},
);
return json.decode(response.body);
}
Future<void> _collectAccount(BuildContext context) async {
final data = await _fetchFinancialConnectionsSession();
final clientSecret = data['clientSecret'];
try {
final result = await Stripe.instance.collectFinancialConnectionsAccounts(
clientSecret: clientSecret,
);
if (!mounted) return;
setState(() {
response = result.toString();
});
} on StripeException catch (e) {
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Error: ${e.error.localizedMessage}')),
);
}
}
Future<void> _collectBankToken(BuildContext context) async {
final data = await _fetchFinancialConnectionsSession();
final clientSecret = data['clientSecret'];
try {
final result = await Stripe.instance.collectBankAccountToken(
clientSecret: clientSecret,
);
if (!mounted) return;
setState(() {
response = result.toString();
});
} on StripeException catch (e) {
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Error: ${e.error.localizedMessage}')),
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Financial Connections')),
body: Padding(
padding: EdgeInsets.all(16),
child: Column(
children: [
ElevatedButton(
onPressed: () => _collectAccount(context),
child: Text('Collect Financial Account'),
),
SizedBox(height: 16),
ElevatedButton(
onPressed: () => _collectBankToken(context),
child: Text('Collect Bank Token'),
),
SizedBox(height: 20),
Text(response),
],
),
),
);
}
}
