UPI Payment MVP — Concept & Technical Flow Documentation

Document Version: 1.2.0
Document Purpose: Stakeholder & Technical Architecture Presentation
Scope: Complete explanation of the features, system architecture, data models, and technical flows implemented in this Payment MVP.


1. Executive Summary & Purpose

This MVP (Minimum Viable Product) was developed as an end-to-end, functional mobile payment prototype for QR-based UPI payments.

It provides an interactive, production-grade reference implementation that handles the complete payment lifecycle:

  1. Camera-based QR Scanning: Real-time scanning, flashlight control, and simulator test presets.
  2. Strict UPI Protocol Validation: Parses and validates standard upi://pay URI payloads against Indian banking specs.
  3. Payment Confirmation & Safety: Interactive preview screen with amount entry, notes, and double-click debouncing.
  4. Local SQLite Persistence: Atomic state machine (PENDING ➔ SUCCESS / FAILED / CANCELLED) with crash recovery.
  5. UPI Intent Dispatch: Hands off payments to installed UPI apps (Google Pay, PhonePe, Paytm, BHIM) via payment gateway integration.
  6. Financial Dashboard & History: Real-time summary metrics, filterable history, and detailed payment receipts.

2. System Architecture

The application is structured into four decoupled layers following the Clean Architecture & Provider State Management pattern:

┌─────────────────────────────────────────────────────────────────────────┐
│                 1. PRESENTATION LAYER (Flutter UI)                      │
│  HomeScreen │ QrScannerScreen │ PaymentPreviewScreen │ ResultScreen    │
│  TransactionHistoryScreen     │ TransactionDetailScreen                 │
└────────────────────────────────────┬────────────────────────────────────┘
                                     │ User Actions & UI Binding
                                     ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                 2. STATE MANAGEMENT LAYER (Provider)                    │
│             PaymentProvider (Coordinates UI, State & DB)                │
└──────────────┬─────────────────────┬────────────────────┬───────────────┘
               │                     │                    │
               ▼                     ▼                    ▼
┌──────────────────────┐ ┌──────────────────────┐ ┌──────────────────────┐
│  3. QR SERVICE       │ │  3. LOCAL STORAGE    │ │  3. GATEWAY SERVICE  │
│  QrService           │ │  LocalStorageService │ │  RazorpayService     │
│  • UPI URI Parsing   │ │  • SQLite Database   │ │  • Intent Invocation │
│  • Parameter Checks  │ │  • Metrics & History │ │  • Response Handler  │
└──────────┬───────────┘ └──────────┬───────────┘ └──────────┬───────────┘
           │                        │                        │
           ▼                        ▼                        ▼
┌──────────────────────┐ ┌──────────────────────┐ ┌──────────────────────┐
│  4. DEVICE CAMERA    │ │  4. LOCAL SQLITE     │ │  4. INSTALLED UPI    │
│  mobile_scanner      │ │  sqflite (Encrypted) │ │  GPay, PhonePe, BHIM │
└──────────────────────┘ └──────────────────────┘ └──────────────────────┘

2.1 Mermaid Architecture Diagram

[Diagram]

2.2 Architectural Components Breakdown

Layer Component / File Responsibility
Presentation HomeScreen Main dashboard: displays wallet balance, quick actions (Scan, Pay by UPI ID), summary stats, and recent 5 transactions.
Presentation QrScannerScreen Full-screen camera viewfinder, flashlight toggle, camera lens switch, and simulator test preset injector.
Presentation PaymentPreviewScreen Merchant verification, amount input/quick-add chips, transaction note input, and double-click debounced pay button.
Presentation PaymentResultScreen Post-payment receipt screen displaying status (Success/Failed/Cancelled), Payment ID, RRN, timestamp, and action buttons.
Presentation TransactionHistoryScreen Chronological list of all transactions with real-time status filter chips (All, Success, Pending, Failed, Cancelled).
Presentation TransactionDetailScreen Complete transaction breakdown with one-tap clipboard copy for Transaction ID, UPI ID, and Reference ID.
State Management PaymentProvider Central ChangeNotifier coordinating state across screens, database reads/writes, and payment callbacks.
Business Logic QrService Pure Dart utility for parsing, sanitizing, and validating standard upi://pay URI query strings.
Persistence LocalStorageService Singleton managing SQLite database initialization, migrations, CRUD operations, and summary calculations.
Integration RazorpayService Wrapper managing the payment gateway SDK, event listeners, intent payload construction, and response callbacks.

3. End-to-End Technical Flows

3.1 High-Level User Journey Flow

[Diagram]

3.2 Flow 1: QR Scanning, Parsing & Strict Validation Pipeline

The QR scanning flow uses mobile_scanner to detect bar codes and routes the raw string to QrService for strict format verification.

[Diagram]

UPI QR Specification Validation Matrix

Parameter Key Field Name Status Specification & Validation Rule Enforced by QrService
pa Payee VPA / UPI ID Mandatory Must be formatted as handle@bank. Cannot start or end with @, cannot be empty.
pn Payee / Merchant Name Optional If missing, extracted from handle portion of pa. Decodes percent-encoded characters (e.g. ABC%20Store ➔ ABC Store).
am Transaction Amount Optional If present, must parse to a valid positive decimal (> 0). If absent, user is prompted to input amount.
cu Currency Code Optional Defaults to INR. Strictly rejects any currency other than INR (e.g., rejects USD, EUR).
tn Transaction Note Optional Note or description of purchase. Pre-fills payment description.
tr Reference ID Optional Merchant's unique transaction reference identifier.
mc Merchant Category Code Optional Merchant business classification code.

3.3 Flow 2: Payment Execution & Double-Spend Prevention Flow

This flow illustrates how the app guarantees transactional safety by recording a PENDING state before delegating to external payment handlers, preventing lost states if the user kills the app.

[Diagram]

4. Local Database Schema & State Machine

4.1 SQLite Table Definition (transactions)

The app uses sqflite for offline-first, crash-resilient transactional storage.

Column Name SQL Type Constraints Description
id TEXT PRIMARY KEY Unique UUID generated client-side at initiation (e.g. txn_1728349281000).
razorpay_payment_id TEXT NULLABLE Gateway payment reference ID returned upon successful settlement.
razorpay_order_id TEXT NULLABLE Gateway order identifier (if generated).
merchant_name TEXT NOT NULL Payee or store name extracted from QR or manual input.
upi_id TEXT NOT NULL Destination Virtual Payment Address (handle@bank).
amount REAL NOT NULL Final amount paid in INR.
currency TEXT NOT NULL DEFAULT 'INR' Currency code (always INR).
status TEXT NOT NULL Lifecycle state: 'PENDING', 'SUCCESS', 'FAILED', 'CANCELLED'.
error_code TEXT NULLABLE Diagnostic error code returned on failure.
error_message TEXT NULLABLE Human-readable explanation of failure.
created_at TEXT NOT NULL ISO-8601 creation timestamp.
updated_at TEXT NULLABLE ISO-8601 last update timestamp.
raw_response TEXT NULLABLE Raw payload string for debugging and audit trail.

4.2 Transaction State Transitions

[Diagram]

State Definitions & Invariants

State Trigger Invariant Rules
PENDING Tap "Pay Now" on PaymentPreviewScreen Pre-written to SQLite. If app process is terminated while in UPI app, record remains PENDING rather than disappearing.
SUCCESS Gateway EVENT_PAYMENT_SUCCESS callback Terminal. Stores razorpay_payment_id. Adds amount to Total Paid metrics.
FAILED Gateway EVENT_PAYMENT_ERROR with decline code Terminal. Stores error_code and error_message. Increments failed counter.
CANCELLED User exits or dismisses the UPI intent sheet Terminal. Marked cancelled without incrementing failure statistics.

5. Screen-by-Screen Implementation Details

Screen File Location Key Capabilities & Features Implemented
Home Screen home_screen.dart • ReapCash Wallet Card: Displays user's reward savings balance (5% perk).
• Quick Action Buttons: "Scan Any QR" and "Pay by UPI ID / Number".
• Financial Analytics Row: Total Amount Paid, Total Transactions, Successful Count, Failed Count.
• Recent Activity Section: Shows last 5 transactions with color-coded status badges and one-tap access to full details.
QR Scanner qr_scanner_screen.dart • Camera Viewfinder: Built with mobile_scanner with overlay target box.
• Hardware Controls: Flashlight toggle and camera flip (front/back).
• Simulator Preset Dialog: Built-in test injector allowing testers to test Valid QRs, Missing Amounts, Invalid schemes, and Custom URLs without needing a physical camera.
Payment Preview payment_preview_screen.dart • Merchant Card: Verified badge, merchant name, and payee UPI ID.
• Amount Controller: Pre-filled if QR contained am, editable if absent. Includes quick-add chips (+₹100, +₹200, +₹500).
• Note Input: Optional transaction remarks.
• Double-Click Safety: Disables button during initiation to prevent duplicate transactions.
• Test Lab Modal (🧪): Simulates instant Success, Failure, and Cancellation outcomes on emulators.
Payment Result payment_result_screen.dart • Status Banners: Color-coded animated icons (Green for Success, Red for Failure, Amber for Cancelled).
• Transaction Breakdown: Amount, Merchant, Date/Time, Transaction ID, Payment ID.
• Share & Download Receipt: Generates formatted receipt data.
• Navigation: Direct routes to "Pay Another" or "Done (Return Home)".
Transaction History transaction_history_screen.dart • Real-Time Filter Chips: Filter by All, Success, Pending, Failed, or Cancelled.
• Newest-First Ordering: Chronological SQLite sorting.
• Empty State Screen: Clean illustration and call-to-action when no transactions match.
Transaction Details transaction_detail_screen.dart • Detailed Audit View: Full breakdown including raw error strings.
• One-Tap Copy: Clipboard buttons for Transaction ID and Reference IDs.
• Receipt Download Button: Triggers receipt confirmation.

6. Testing, Presets & Verification Scenarios

6.1 Automated Unit & Widget Test Suite

All tests execute via flutter test and pass with 0 failures:

Test ID Test Category Scenario Tested Input Data Expected Result Status
UT-01 QR Parsing Complete valid QR payload upi://pay?pa=test@upi&pn=Test%20Merchant&am=100&cu=INR Validated UpiQrData with amount 100.0, merchant Test Merchant PASSED
UT-02 QR Parsing Missing amount QR upi://pay?pa=merchant@upi&pn=ABC%20Store&cu=INR Validated UpiQrData with amount = null, hasPredefinedAmount = false PASSED
UT-03 QR Parsing Non-UPI URL https://example.com/payment Rejection: "Invalid QR format. Scanned code is not a valid UPI QR code." PASSED
UT-04 QR Parsing Missing Payee ID (pa) upi://pay?pn=Store&am=50&cu=INR Rejection: "Invalid UPI QR: Payee UPI ID (pa) is missing." PASSED
UT-05 QR Parsing Malformed UPI ID upi://pay?pa=invalidupiid&pn=Store&am=50&cu=INR Rejection: "Invalid UPI ID format. Must be in the format name@bank." PASSED
UT-06 QR Parsing Non-INR Currency upi://pay?pa=test@upi&am=50&cu=USD Rejection: "Unsupported currency 'USD'. Only INR is supported." PASSED
UT-07 QR Parsing Zero / Negative Amount upi://pay?pa=test@upi&am=-10&cu=INR Rejection: "Invalid amount value. Must be greater than 0." PASSED
UT-08 State Machine Payment Success Callback Mock PaymentSuccessResponse Record updated to SUCCESS, razorpayPaymentId stored PASSED
WT-01 Widget Test Home Screen Rendering Widget render check Verifies ReapCash Wallet Card, Action buttons, Stats Cards PASSED

6.2 Interactive Simulator Test Presets (In-App)

For testing on simulators and emulators where a physical camera is unavailable:

Test Preset How to Trigger in App Description & Verified Behavior
Preset 1: Standard Merchant Scanner ➔ Keyboard Icon ➔ Select "Test 1" Pre-fills pa=coffee@okhdfcbank, pn=Blue Tokai Coffee, am=240.00. Opens preview with amount locked to ₹240.00.
Preset 2: Dynamic Amount Scanner ➔ Keyboard Icon ➔ Select "Test 2" Pre-fills pa=kirana@axl, pn=Gupta General Store. Opens preview with amount input field empty for user entry.
Preset 3: Invalid Scheme Scanner ➔ Keyboard Icon ➔ Select "Test 3" Injects https://example.com. Triggers validation error dialog without crashing.
Preset 4: Test Lab Simulator Preview Screen ➔ Test Flask Icon (🧪) Allows developer/stakeholder to simulate Success, Failure, or Cancellation without needing real UPI apps.

7. Configuration & Platform Specifications

7.1 Runtime & Environment Configuration

Setting Configuration Method Default Value Description
Razorpay Key ID --dart-define=RAZORPAY_KEY=... or In-App Settings rzp_test_51MockupKey Test gateway key used to initialize intent sessions.
UPI Intent Timeout Hardcoded in razorpay_service.dart 180 seconds Time allowed for user to complete authorization in UPI app before timing out.
Currency Enforced in qr_service.dart 'INR' Sole permitted currency code.

7.2 Native Platform Permissions

Platform File Permissions / Queries Configured
Android AndroidManifest.xml • android.permission.CAMERA
• android.permission.INTERNET
• <queries> configured for upi://, paytmmp://, gpay://, phonepe://, bhim package names.
iOS Info.plist • NSCameraUsageDescription configured for camera viewfinder.
• LSApplicationQueriesSchemes configured for upi, paytmmp, gpay, phonepe, bhim.

8. Summary for Stakeholders

This MVP successfully demonstrates:

  1. Camera scanning with sub-second decoding and error handling for bad QRs.
  2. Adherence to UPI URI specifications, preventing invalid amounts or currencies.
  3. Double-spend protection and persistent SQLite ledger guaranteeing transaction history survives app restarts and crashes.
  4. Intuitive UX, providing familiar screens for scanning, confirmation, receipts, and history filters.