Introduction to the flutter_stripe Flutter Package
Integrating payments and commerce into mobile applications used to require writing custom native bridges for both Android and iOS. The flutter_stripe Flutter package solves this problem by providing a official-feeling, cross-platform wrapper around the native Stripe SDKs. Whether you are building an e-commerce shop, subscription platform, or digital marketplace, this package enables secure credit card processing, Google Pay, Apple Pay, and payment intent workflows.
Note: Always review the latest documentation and pub.dev metadata before deploying payment features to production, as native SDK dependencies and API contracts evolve.
When to Use flutter_stripe in Your App
The flutter_stripe package is best suited for scenarios where you need direct payment processing and checkout interfaces inside your app without constructing complex custom UI components from scratch.
- In-app Checkout Flows: Display pre-built Stripe Payment Sheets for seamless user checkout.
- Subscription Management: Process initial subscription setups using payment intents generated by your backend.
- Custom Card Inputs: Render secure, PCI-compliant card text fields directly inside your Flutter widget tree.
Installing the Package
To add the flutter_stripe package to your Flutter project, run the following command in your root project directory:
flutter pub add flutter_stripeThis adds the dependency to your pubspec.yaml file and fetches the package from pub.dev.
Setup and Configuration Notes
Before executing payment logic, initialize the Stripe instance with your publishable key. Always place package setup logic inside isolated services rather than coupling UI widgets directly to third-party dependencies.
On native platforms, ensure your Android theme inherits from Theme.AppCompat or a Material Theme derivative, and verify iOS configuration requirements in the official package README.
Step-by-Step Implementation Example
Below is a production-ready, runnable example demonstrating how to initialize Stripe and display a native Payment Sheet.
import 'package:flutter/material.dart';
import 'package:flutter_stripe/flutter_stripe.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Assign your Stripe publishable key before rendering UI
Stripe.publishableKey = 'pk_test_51ExamplePublishableKeyHere';
await Stripe.instance.applySettings();
runApp(const PaymentApp());
}
class PaymentApp extends StatelessWidget {
const PaymentApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Stripe Demo',
theme: ThemeData(primarySwatch: Colors.indigo),
home: const CheckoutScreen(),
);
}
}
class CheckoutScreen extends StatefulWidget {
const CheckoutScreen({super.key});
@override
State<CheckoutScreen> createState() => _CheckoutScreenState();
}
class _CheckoutScreenState extends State<CheckoutScreen> {
bool _isLoading = false;
Future<void> _presentPaymentSheet() async {
setState(() => _isLoading = true);
try {
// 1. Obtain paymentIntentClientSecret from your secure backend server.
// Never hardcode client secrets in production app builds.
const String dummyClientSecret = 'pi_3M..._secret_...';
// 2. Initialize the Payment Sheet configuration
await Stripe.instance.initPaymentSheet(
paymentSheetParameters: const SetupPaymentSheetParameters(
paymentIntentClientSecret: dummyClientSecret,
merchantDisplayName: 'FlutterFever Store',
style: ThemeMode.system,
),
);
// 3. Display the native Payment Sheet UI
await Stripe.instance.presentPaymentSheet();
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Payment completed successfully!')),
);
}
} on StripeException catch (e) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Stripe Error: ${e.error.localizedMessage}')),
);
}
} catch (e) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Unexpected Error: $e')),
);
}
} finally {
if (mounted) {
setState(() => _isLoading = false);
}
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Stripe Checkout'),
),
body: Center(
child: _isLoading
? const CircularProgressIndicator()
: ElevatedButton(
onPressed: _presentPaymentSheet,
child: const Text('Pay with Stripe'),
),
),
);
}
}Mistakes to Avoid
When working with the flutter_stripe Flutter package, watch out for these standard integration pitfalls:
- Exposing Secret Keys: Storing secret keys in Flutter code compromises security. Keep secret keys strictly on your backend infrastructure.
- Direct UI Coupling: Avoid calling
Stripe.instancedirectly inside business logic or state management layers. Wrap payments in a dedicated repository class (e.g.,PaymentRepository). - Ignoring Platform Errors: Always catch
StripeExceptionspecifically to catch user cancellations gracefully without crashing app execution flows.
Conclusion
The flutter_stripe Flutter package gives developers a structured, robust path to implement commerce features across mobile platforms. By keeping package usage behind clear application boundaries and maintaining secure backend endpoints for client secrets, you can quickly deploy compliant payment flows into your Flutter apps. Check flutter_stripe on pub.dev for latest platform notes and API adjustments.
Frequently Asked Questions
How do I initialize the flutter_stripe package in my app?
Set Stripe.publishableKey in your main() function after calling WidgetsFlutterBinding.ensureInitialized(), then call await Stripe.instance.applySettings().
Where should secret keys be stored when using flutter_stripe?
Never store Stripe secret keys in your Flutter client code. Secret keys must remain securely on your backend server, which creates PaymentIntents and returns client secrets to the app.
Is flutter_stripe compatible with both Android and iOS?
Yes, flutter_stripe wraps native Stripe SDKs for both iOS and Android platforms. Always verify native platform requirements and theme settings in the package documentation.