What you'll build

In this part you'll build the full checkout flow — a summary screen, Paystack payment, and an order record saved to Firestore when payment succeeds.

By the end of this part:

Set up Paystack

Go to dashboard.paystack.com and sign up or sign in. Under Settings → API Keys, copy your Test Public Key — it starts with pk_test_.

Use test keys during development. Paystack test mode lets you pay with test card numbers without real money moving. Switch to live keys (pk_live_) only when you're ready to go live.

Add your Paystack public key to your .env file or as a constant in a config file:

// lib/config.dart
const kPaystackPublicKey = 'pk_test_your_key_here';

The flutter_paystack package should already be in your pubspec.yaml from Part 1. If not:

flutter pub add flutter_paystack

Initialize the plugin in main.dart:

await PaystackPlugin.initialize(publicKey: kPaystackPublicKey);

Create the order model

BlocWeave prompt

Create the order data model at lib/models/order.dart. An Order has fields: id (String), userId (String), items (List), totalAmount (double), currency (String, default 'GHS'), status (String: 'pending', 'paid', 'shipped', 'delivered'), deliveryAddress (Map<String, String> with keys: name, phone, address, city), paystackReference (String), createdAt (DateTime). Create an OrderItem class with: productId, productName, selectedSize, quantity, unitPrice. Add fromFirestore, toMap, and a fromCart(List, userId, address, reference) factory constructor.

Build the checkout screen

BlocWeave prompt

Build the checkout screen at lib/features/checkout/checkout_screen.dart. The screen shows: 1. An order summary section — list of cart items with quantities and prices, and a total 2. A delivery details form — fields for full name, phone number, delivery address, and city. All fields are required. 3. A "Pay GHS X.XX with Paystack" button at the bottom When the Pay button is tapped: - Validate the form; show inline errors if any field is empty - Generate a unique payment reference: "SHOP__" - Create a Charge object with: amount (in kobo/pesewas — multiply GHS by 100), currency "GHS", email from currentUser, reference - Call PaystackPlugin.checkout() with the charge and a CheckoutMethod.card - On success (transaction.status == true): call the createOrder service method, clear the cart, and navigate to the order confirmation screen - On failure or cancellation: show a SnackBar with an error message

Build the order service

BlocWeave prompt

Create lib/services/order_service.dart with two methods: 1. Future createOrder(Order order) — saves the order to Firestore at orders/{orderId}, returns the document ID 2. Stream<List> getUserOrders(String userId) — streams the user's orders ordered by createdAt descending

Add an order confirmation screen

BlocWeave prompt

Create lib/features/checkout/order_confirmation_screen.dart. Show a success animation (use Flutter's built-in AnimatedContainer or a simple checkmark that scales in), the order reference number, a summary of what was ordered, and two buttons: "Continue shopping" (navigates to /) and "View my orders" (navigates to /orders).

Test the payment flow

  1. Fill the cart with a few products
  2. Tap Checkout — the checkout screen should show the items and total
  3. Fill in delivery details
  4. Tap Pay — Paystack's payment sheet should open
  5. Use Paystack's test card: 4084 0840 8408 4081, expiry 01/99, CVV 408, PIN 0000
  6. Payment should complete — the confirmation screen appears
  7. Check Firestore — an order document should exist under orders/
  8. Check the cart — it should be empty

Pesewas vs GHS: Paystack amounts are in the smallest currency unit. For GHS, that's pesewas (100 pesewas = 1 GHS). Multiply your GHS amount by 100 before passing it to the Charge object. A GHS 180.00 dress should be passed as 18000.

Project structure after Part 5

lib/
  features/
    checkout/
      checkout_screen.dart
      order_confirmation_screen.dart
  models/
    order.dart
  services/
    order_service.dart

What's next

In Part 6 we build the order history screen — a list of the user's past orders with status indicators and an expandable detail view showing what was in each order.