Reusable Flutter base project for Stripe with a backend-first structure, guided comments in code, and starter flows for the most common mobile payment patterns.
- Clean Flutter project structure focused on Stripe instead of the default counter app.
- Safe architecture: no Stripe secret key in Flutter.
- Reusable request and service layer for backend-driven Stripe flows.
- Example UI for 5 Stripe usage patterns:
- Payment Sheet
- CardField
- CardForm
- Apple Pay / Google Pay
- Customer Sheet
- Platform setup fixes for Android and iOS.
This starter demonstrates 5 main client-side patterns:
- Payment Sheet
- CardField
- CardForm
- Platform Pay
- Customer Sheet
For subscriptions, invoices, webhooks, off-session charges, and saved cards on future purchases, you build on the same backend contract shown below.
Never place STRIPE_SECRET_KEY in Flutter.
The old project did that. This starter removes it because the secret key must stay on your backend only.
lib/
app/
stripe_starter_app.dart
theme/app_theme.dart
core/
config/app_env.dart
errors/app_exception.dart
network/backend_client.dart
features/
stripe/
data/
models/
stripe_backend_models.dart
stripe_checkout_request.dart
services/
stripe_checkout_service.dart
presentation/
controllers/stripe_starter_controller.dart
pages/stripe_starter_home_page.dart
widgets/starter_section_card.dart
bootstrap.dart
main.dart
This project reads .env at app startup.
Example:
APP_NAME=Flutter Stripe Starter
STRIPE_PUBLISHABLE_KEY=pk_test_your_publishable_key
STRIPE_BACKEND_URL=http://10.0.2.2:4242
STRIPE_MERCHANT_IDENTIFIER=merchant.com.example.flutterStripeStarter
STRIPE_MERCHANT_COUNTRY_CODE=US
STRIPE_DEFAULT_CURRENCY=usd
STRIPE_RETURN_URL_SCHEME=flutterstripestarter
STRIPE_GOOGLE_PAY_TEST_ENV=trueNotes:
STRIPE_BACKEND_URLis required because this starter expects your secure server to create Stripe objects.10.0.2.2is the Android emulator alias for your local machine.- On iOS simulator, use your local machine IP or localhost depending on your server setup.
STRIPE_MERCHANT_IDENTIFIERis needed for Apple Pay.
You can rename these routes. If you do, update stripe_checkout_service.dart.
Purpose:
- Create a PaymentIntent
- Optionally create or reuse a Customer
- Optionally create an ephemeral key for saved methods
Example request:
{
"amount": 1000,
"currency": "usd",
"description": "Starter checkout",
"customerId": "optional_customer_id",
"receiptEmail": "customer@example.com"
}Example response:
{
"clientSecret": "pi_xxx_secret_xxx",
"customerId": "cus_xxx",
"customerEphemeralKeySecret": "ek_test_xxx"
}Purpose:
- Create a PaymentIntent for CardField, CardForm, or Platform Pay
Example response:
{
"clientSecret": "pi_xxx_secret_xxx"
}Purpose:
- Create or fetch a Stripe Customer
- Create an ephemeral key
- Optionally create a SetupIntent for authentication during saved card creation
Example response:
{
"customerId": "cus_xxx",
"customerEphemeralKeySecret": "ek_test_xxx",
"setupIntentClientSecret": "seti_xxx_secret_xxx"
}Best when you want the easiest and most complete checkout experience.
Client flow:
- Build a
StripeCheckoutRequest - Call backend
/payment-sheet - Initialize Stripe Payment Sheet
- Present Payment Sheet
Entry point:
Best when you need a custom checkout screen with inline card entry.
Client flow:
- Render
CardField - Call backend
/payment-intents - Confirm payment with
Stripe.instance.confirmPayment
Best when you want a larger multi-line card form.
Flow is the same as CardField, but the widget is CardFormField.
Best when you want the fastest wallet checkout on mobile.
Client flow:
- Check wallet support on device
- Call backend
/payment-intents - Confirm with
confirmPlatformPayPaymentIntent
Best when users need to manage saved payment methods.
Client flow:
- Call backend
/customer-sheet - Initialize Customer Sheet
- Present Customer Sheet
This starter already applies the key Android changes Stripe needs:
MainActivityusesFlutterFragmentActivity- App theme uses
Theme.AppCompat minSdkis forced to at least21- release build has Stripe proguard rules
Files:
This starter already includes:
platform :ios, '13.0'- camera usage description for card scanning
- Stripe initialization handled in Dart bootstrap instead of AppDelegate
Files:
- Replace app name and bundle identifiers
- Point
STRIPE_BACKEND_URLto your real backend - Match backend route names if you use different endpoints
- Add webhook handling on the server for payment lifecycle events
- Add subscription endpoints if you need recurring billing
- Add app-specific business validation around amount, currency, and customer mapping
flutter pub get
flutter runIf Stripe actions fail immediately, check:
.envvalues- backend server is running
- emulator/device can reach the backend URL
- Apple Pay / Google Pay merchant configuration