A complete Flutter e-commerce application with Midtrans payment & Raja Ongkir integration, built using Clean Architecture, BLoC pattern, Firebase, and Go Router.
- ✅ User Authentication (Email/Password & Google Sign-In)
- ✅ Product Listing with Categories
- ✅ Product Detail Page with Image Gallery
- ✅ Shopping Cart Management
- ✅ User Profile Management
- ✅ Address Search with Raja Ongkir API
- ✅ Shipping Service Selection
- ✅ Checkout with Auto-fill User Profile
- ✅ Midtrans Payment Integration
- ✅ Order History & Status Tracking
- ✅ Clean Architecture Implementation
- ✅ State Management with BLoC
- ✅ Dependency Injection with GetIt
- ✅ Navigation with GoRouter
- ✅ Form Validation
- ✅ Optimized Widget Rebuilding
- ✅ Google Sign-In
- ✅ Raja Ongkir Shipping Integration
- ✅ Order Status Page
- ✅ Cross-platform (Android & iOS)
- ✅ BLoC Architecture for All Features
This project follows Clean Architecture principles with three main layers:
lib/
├── core/ # Core utilities and base classes
│ ├── error/ # Error handling
│ ├── network/ # Network utilities
│ └── usecases/ # Base use case
├── features/ # Feature modules
│ ├── auth/ # Authentication
│ ├── products/ # Product listing & detail
│ ├── cart/ # Shopping cart
│ ├── payment/ # Payment & checkout
│ ├── orders/ # Order management
│ └── shipping/ # Shipping services
└── injection_container.dart # Dependency injection
Each feature follows:
- Domain Layer: Entities, Repositories (interfaces), Use Cases
- Data Layer: Models, Data Sources, Repository Implementations
- Presentation Layer: BLoC, Pages, Widgets
- AuthBloc: User authentication and profile management
- AuthFormBloc: Form validation for login/signup
- AddressSearchBloc: Address search with Raja Ongkir
- ProductBloc: Product listing and categories
- ProductDetailBloc: Individual product details
- CartBloc: Shopping cart management
- CheckoutBloc: Checkout process and shipping
- OrderBloc: Order management and history
- Separate BLoCs for each feature domain
- Optimized widget rebuilding with
buildWhen - Form validation handled in dedicated BLoCs
- Independent loading states for different data
- Categories loaded once without rebuilding product widgets
- Image caching with
cached_network_image - Efficient state management with Equatable
- Minimal widget rebuilds using BLoC listeners
- Domain entities with immutable data
- Repository pattern with Either for error handling
- Dependency injection with GetIt
- Separation of concerns across layers
- Flutter SDK (3.10.7 or higher)
- Dart SDK
- Firebase Account
- Midtrans Account (Sandbox for testing)
- Android Studio / VS Code
- Git
git clone <repository-url>
cd flutter_midtransflutter pub get- Go to Firebase Console
- Create a new project or use existing one
- Add Android app with package name:
com.example.flutter_midtrans - Download
google-services.json - Place it in
android/app/
- In Firebase Console, add iOS app
- Download
GoogleService-Info.plist - Place it in
ios/Runner/
- Enable Authentication (Email/Password & Google)
- Enable Cloud Firestore
- Create Firestore collections:
users(for user profiles)orders(for order data)
- Sign up at Midtrans
- Get your Server Key from Dashboard → Settings → Access Keys
- Create
.envfile in project root:
CLIENT_KEY=your_midtrans_api_key
SERVER_KEY=your_midtrans_api_keyNote: I'm using Next.js backend, available on my nextjs-midtrans repository.
- Sign up at Raja Ongkir
- Get your API Key from Dashboard
- Add API key to
.envfile
PAYMENT_API_KEY=your_rajaongkir_api_key
SHIPPING_COST_API_KEY=your_rajaongkir_api_key
SHIPPING_DELIVERY_API_KEY=your_rajaongkir_api_key- Get SHA-1 fingerprint:
cd android
.\gradlew signingReport- Add SHA-1 to Firebase Console → Project Settings → Your Android App
- Add URL scheme in
ios/Runner/Info.plist:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>com.googleusercontent.apps.YOUR-CLIENT-ID</string>
</array>
</dict>
</array>flutter runUpdate android/app/build.gradle.kts:
plugins {
id("com.android.application")
id("kotlin-android")
id("com.google.gms.google-services") // Add this
}Update android/build.gradle.kts:
buildscript {
dependencies {
classpath("com.google.gms:google-services:4.4.0") // Add this
}
}Update ios/Podfile:
platform :ios, '12.0'- Launch app → Login/Sign Up screen
- Sign up with email/password or use Google Sign-In
- User profile is automatically created in Firestore
- View all products from DummyJSON API
- Filter by categories
- View product details with image gallery
- Add products to cart
- View cart items
- Update quantities
- Remove items
- See total price
- Shipping information auto-filled from user profile
- Search and select shipping address via Raja Ongkir
- Select shipping service (required)
- View shipping cost (displayed but not added to total)
- Review order summary
- Proceed to payment
- Redirected to Midtrans payment page
- Choose payment method (Sandbox mode)
- Complete payment
- Order status updated automatically
- View all orders
- Check order status
- See order details
Use Midtrans Sandbox test credentials:
Credit Card:
- Card Number:
4811 1111 1111 1114 - CVV:
123 - Exp Date: Any future date
- OTP:
112233
Other Methods:
- Products API: https://dummyjson.com/products
- Midtrans Snap API: https://app.sandbox.midtrans.com/snap/v1/transactions
- Raja Ongkir API: https://api-sandbox.collaborator.komerce.id/
lib/
├── core/
│ ├── error/
│ │ └── failures.dart
│ ├── network/
│ │ └── network_info.dart
│ └── usecases/
│ └── usecase.dart
├── features/
│ ├── auth/
│ │ ├── data/
│ │ │ ├── datasources/
│ │ │ ├── models/
│ │ │ └── repositories/
│ │ ├── domain/
│ │ │ ├── entities/
│ │ │ ├── repositories/
│ │ │ └── usecases/
│ │ └── presentation/
│ │ ├── bloc/
│ │ └── pages/
│ ├── products/
│ ├── cart/
│ ├── payment/
│ ├── orders/
│ └── shipping/
├── injection_container.dart
├── router.dart
└── main.dart
dependencies:
flutter_bloc: ^8.1.3
equatable: ^2.0.5
get_it: ^7.6.4
go_router: ^13.0.0
firebase_core: ^2.24.2
firebase_auth: ^4.16.0
cloud_firestore: ^4.14.0
google_sign_in: ^6.2.1
http: ^1.1.2
dartz: ^0.10.1
cached_network_image: ^3.3.1
webview_flutter: ^4.4.4
flutter_dotenv: ^5.1.0- Ensure
google-services.json(Android) andGoogleService-Info.plist(iOS) are in correct locations - Check Firebase project configuration
- Verify package name matches Firebase app
- Verify Server Key is correct
- Use Sandbox mode for testing
- Check network connectivity
- Verify API Key is correct in
.envfile - Ensure
.envfile is in project root - Check API quota limits
flutter clean
flutter pub get
flutter run- Product search functionality
- Wishlist feature
- Product reviews and ratings
- Push notifications for order updates
- Multiple payment methods
- Promo codes and discounts
- Add shipping cost to total amount
- Fork the repository
- Create feature branch (
git checkout -b feature/AmazingFeature) - Commit changes (
git commit -m 'Add AmazingFeature') - Push to branch (
git push origin feature/AmazingFeature) - Open Pull Request
This project is licensed under the MIT License.
For questions or support, please open an issue in the repository.
- DummyJSON API for product data
- Midtrans for payment gateway
- Raja Ongkir for shipping services
- Vercel for backend services
- Flutter community for amazing packages