A production-ready Flutter Stripe integration guide (2026) with exact file paths, updated Android setup, and clean architecture using Riverpod.
This project demonstrates Stripe Payment Sheet integration with:
flutter_stripedioflutter_riverpod
Includes:
- Full Android configuration (latest)
- Payment Intent flow
- Clean folder structure
dart pub add flutter_stripe- Android API 21+
- Kotlin 1.8.0+
- Android Gradle Plugin 8+
- Gradle 9+
- Use
FlutterFragmentActivity - Use
Theme.AppCompatorMaterialComponents
📍 Path:
android/gradle.properties
android.useAndroidX=true
android.enableJetifier=true📍 Path:
android/settings.gradle.kts
pluginManagement {
plugins {
id("com.android.application") version "8.13.2" apply false
id("org.jetbrains.kotlin.android") version "2.3.10" apply false
}
}📍 Path:
android/app/build.gradle.kts
kotlin {
compilerOptions {
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17)
}
}📍 Path:
android/gradle/wrapper/gradle-wrapper.properties
distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.1-bin.zip📍 Path:
android/app/src/main/res/values/styles.xml
<resources>
<style name="LaunchTheme" parent="Theme.AppCompat.Light.NoActionBar" />
<style name="NormalTheme" parent="Theme.MaterialComponents" />
</resources>📍 Path:
android/app/src/main/res/values-night/styles.xml
<resources>
<style name="LaunchTheme" parent="Theme.AppCompat.DayNight.NoActionBar" />
<style name="NormalTheme" parent="Theme.MaterialComponents" />
</resources>✔ Fixes:
Theme.Light.NoTitleBar not foundTheme.Black.NoTitleBar not found
📍 Path:
android/app/src/main/kotlin/com/example/stripe_integration/MainActivity.kt
import io.flutter.embedding.android.FlutterFragmentActivity
class MainActivity: FlutterFragmentActivity() {
}📍 Path (CREATE THIS FILE):
android/app/proguard-rules.pro
-dontwarn com.stripe.android.pushProvisioning.PushProvisioningActivity$g
-dontwarn com.stripe.android.pushProvisioning.PushProvisioningActivityStarter$Args
-dontwarn com.stripe.android.pushProvisioning.PushProvisioningActivityStarter$Error
-dontwarn com.stripe.android.pushProvisioning.PushProvisioningActivityStarter
-dontwarn com.stripe.android.pushProvisioning.PushProvisioningEphemeralKeyProvider
-dontwarn kotlinx.parcelize.Parceler$DefaultImpls
-dontwarn kotlinx.parcelize.Parceler
-dontwarn kotlinx.parcelize.Parcelize
-keep class com.stripe.** { *; }
📍 Path:
pubspec.yaml
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.8
flutter_stripe: ^12.6.0
flutter_riverpod: ^3.3.1
dio: ^5.9.2lib/
├── core/
│ └── secret/
│ └── secret.dart
├── stripe_service.dart
└── main.dart
📍 Path:
lib/core/secret/secret.dart
String publishableKey = "pk_test_XXXXXXXXXXXXXXXXXXXXXXXX";
String secretKey = " "; // ⚠️ backend onlyimport 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_stripe/flutter_stripe.dart';
import 'package:stripe_integration/core/secret.dart';
import 'package:stripe_integration/stripe_service.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
Stripe.publishableKey = publishableKey;// Required
await Stripe.instance.applySettings();
print(Stripe.publishableKey); //key access or not
runApp(
ProviderScope(
child: const MaterialApp(
home: PayScreen(),
),
),
);
}✔ Fixes:
StripeConfigException
class PayScreen extends ConsumerWidget {
const PayScreen({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final stripeService = ref.read(stripePaymentProvider);
return Scaffold(
appBar: AppBar(title: const Text('Stripe Payment')),
body: Center(
child: ElevatedButton(
onPressed: () async {
await stripeService.initPaymentSheet(
amount: '20',
currency: 'USD',
merchantName: 'Flutter Workshop',
);
await stripeService.presentPaymentSheet();
},
child: const Text('Pay \$20'),
),
),
);
}
}
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:dio/dio.dart';
import 'package:flutter_stripe/flutter_stripe.dart';
import 'package:stripe_integration/core/secret.dart';
final stripePaymentProvider = Provider((ref) => StripePaymentService());
class StripePaymentService {
final Dio _dio = Dio();
Future<void> initPaymentSheet({
required String amount,
required String currency,
required String merchantName,
}) async {
final paymentIntent = await _createPaymentIntent(amount, currency);
await Stripe.instance.initPaymentSheet(
paymentSheetParameters: SetupPaymentSheetParameters(
paymentIntentClientSecret: paymentIntent['client_secret'],
merchantDisplayName: merchantName,
style: ThemeMode.light,
),
);
}
Future<void> presentPaymentSheet() async {
await Stripe.instance.presentPaymentSheet();
}
Future<Map<String, dynamic>> _createPaymentIntent(
String amount,
String currency,
) async {
final body = {
'amount': (int.parse(amount) * 100).toString(),
'currency': currency,
'payment_method_types[]': 'card',
};
final response = await _dio.post(
'https://api.stripe.com/v1/payment_intents',
data: body,
options: Options(
headers: {
'Authorization': 'Bearer $secretKey',
'Content-Type': 'application/x-www-form-urlencoded',
},
),
);
print("Stripe Key: ${Stripe.publishableKey}");
return response.data;
}
}- Create Payment Intent (API)
- Initialize Payment Sheet
- Present Payment Sheet
-
Card: Do test with above image card information OR use Stripe official test cards
-
Bank: Use Stripe official test bank details
- ❌ Never expose
secretKeyin production - ✅ Always call
applySettings() - 💰 Amount must be in cents
- 🔐 Use backend for real payments
- Stripe Flutter Docs
- Stripe API Docs
Feel free to:
- Fork
- Improve
- Add features
If you found this helpful, consider Giving A ⭐ To The Project.
Crealify
Built with Flutter & Stripe • Clean Architecture • 2026 Ready
