Skip to content

dominicjuma/CashiPaymentKMM

Repository files navigation

Cashi Payment App

Cross-platform payment automation app with a Kotlin Multiplatform Mobile (KMM) base, Appium test suite, and backend API.

Demo Video

Screen_recording_20250724_005329.mp4

Features

Core Functionality

  • Send Payment: Users can send payments by entering recipient email, amount, and currency (USD/EUR)
  • Transaction History: Real-time display of payment history fetched from Firebase Firestore
  • Input Validation: Shared KMP validation for email format, amount > 0, and supported currencies

Technical Implementation

  • Kotlin Multiplatform: Shared business logic, API calls, and validation between platforms
  • Firebase Integration: Firestore for transaction storage with real-time updates
  • REST API: Ktor Backend API with POST /payments endpoint for payment processing
  • Cross-Platform Ready: Architecture supports Android (implemented) and future iOS/desktop platforms

📱 KMP Architecture & Cross-Platform Potential

Project Structure

cashipaymentapp/
├── shared/                           # KMP shared module
│   ├── src/
│   │   ├── commonMain/kotlin/
│   │   │   └── com.getcashi.payment/
│   │   │       ├── core/            # Core utilities
│   │   │       ├── data/            # API client, repositories
│   │   │       ├── di/              # Dependency injection
│   │   │       ├── domain/          # Business logic & models
│   │   │       └── validation/      # Input validation logic
│   │   ├── androidMain/kotlin/      # Android-specific implementations
│   │   ├── androidUnitTest/kotlin/
│   │   │   └── com.getcashi.payment.bdd/
│   │   │       └── PaymentBddSpec   # BDD tests
│   │   ├── androidTest/kotlin/      # Android integration tests
│   │   ├── commonTest/kotlin/       # Common tests
│   │   ├── iosMain/kotlin/          # iOS-specific implementations (future)
│   │   └── jvmMain/kotlin/          # JVM-specific implementations
├── androidApp/                      # Android UI (Jetpack Compose)
│   ├── src/
│   │   ├── main/                    # Main Android app code
│   │   └── test/[unitTest]/java/
│   │       └── com.getcashi.payment.android.appium/  # Appium UI automation tests
│   │           ├── cucumber/        # Cucumber BDD tests
│   │           ├── pages/           # Page Object Model
│   │           ├── tests/           # Test cases
│   │           ├── utils/           # Test utilities
│   │           ├── BaseAppiumTest    # Base test class
│   │           ├── ComposeDiagnosticTest
│   │           └── SimpleConnectionTest
├── backend/                         # REST API (Ktor + Docker)
└── load-testing/                    # JMeter performance tests

Overview

This is a Kotlin Multiplatform Mobile (KMP) payment application that follows Clean Architecture principles with clear separation of concerns across multiple layers.

Architecture Layers

1. Presentation Layer

  • PaymentScreen.kt: Jetpack Compose UI with modern Material 3 design
  • PaymentViewModel.kt: MVVM pattern with StateFlow and Channel for effects
  • PaymentScreenState: Immutable state management
  • PaymentScreenEvent: Sealed class for user interactions
  • PaymentScreenEffect: Side effects like toasts and keyboard handling

Key Features:

  • Form validation with real-time error feedback
  • Transaction history display
  • Payment success dialogs
  • Currency selection
  • Accessibility support with semantic properties

2. Domain Layer (domain)

Use Cases:

  • SendPaymentUseCase: Orchestrates payment validation and submission
  • GetTransactionHistoryUseCase: Manages transaction data retrieval

Models:

  • Payment: Core payment entity
  • Transaction: Transaction data model
  • Currency: Enum for supported currencies
  • PaymentStatus: Payment state enumeration

Repositories (Interfaces):

  • PaymentRepository: Payment operations contract
  • TransactionRepository: Transaction data contract

3. Data Layer (data)

API Layer (data.api)

  • HttpClientFactory: Platform-specific HTTP client creation using expect/actual
  • PaymentApiClient: REST API client with Ktor
    • Comprehensive error handling (4xx, 5xx, network errors)
    • Retry mechanism with exponential backoff
    • Request/response logging
    • Timeout configurations

Repository Implementation (data.repository)

  • PaymentRepositoryImpl: Implements payment business logic
  • TransactionRepositoryImpl: Manages transaction data flow
  • TransactionSync: Platform-specific Firebase integration using expect/actual

Data Transfer Objects (data.dto)

  • ApiResponse: Generic API response wrapper
  • CreatePaymentRequest/Response: Payment API contracts
  • ValidateRecipientRequest/Response: Recipient validation contracts

Data Mapping (data.mapper)

  • Converts between API DTOs and domain models
  • Firebase document mapping utilities

4. Core Layer (core)

Configuration (core.config)

  • AppConfig: Application constants and configuration
    • API URLs for development and production
    • Payment limits and validation rules
    • Network timeout configurations

Platform Abstractions (core.platform)

  • Platform: Platform-specific information using expect/actual
  • Utility Functions: Date formatting, currency formatting, timestamps

Result Handling (core.result)

  • Result: Sealed class for operation outcomes
  • AppError: Comprehensive error types (API, Network, Firebase, Validation)

5. Validation Layer (validation)

  • FormFieldValidator: Generic validation interface
  • FormFieldState: Field-level validation state
  • PaymentValidationRules: Business validation rules

6. Dependency Injection (di)

  • Koin Module: Dependency injection setup
  • Single instances for repositories and API clients
  • Factory instances for use cases

Key Architectural Patterns

1. Clean Architecture

  • Clear separation between layers
  • Dependency inversion (domain doesn't depend on data)
  • Use cases encapsulate business logic

2. **MVI Pattern (Model-View-Intent)

  • Unidirectional Data Flow: User interactions → Events → ViewModel → State updates → UI
  • Single Source of Truth: All UI state consolidated in immutable PaymentScreenState
  • Event-Driven: User actions modeled as sealed class events (PaymentScreenEvent)
  • StateFlow for reactive state management
  • Channel for one-time effects (toasts, navigation, keyboard actions)
  • Immutable State Updates: State changes via copy() operations only

3. Repository Pattern

  • Abstract data access behind interfaces
  • Multiple data sources (API + Firebase)
  • Consistent error handling

4. Expect/Actual Pattern

  • Platform-specific implementations
  • Shared business logic across platforms
  • Firebase integration for Android
  • HTTP client factory abstraction

Data Flow

Unidirectional data flow

UI Event → ViewModel → Use Case → Repository → API/Firebase
                ↓
UI State ← ViewModel ← Use Case ← Repository ← Response

Key Technologies

Shared/Common

  • Kotlin Multiplatform: Code sharing across platforms
  • Ktor: HTTP client for API communication
  • Kotlinx Serialization: JSON serialization
  • Kotlinx Coroutines: Asynchronous programming
  • Koin: Dependency injection

Android Specific

  • Jetpack Compose: Modern declarative UI
  • Material 3: Latest design system
  • Firebase Firestore: Real-time database
  • StateFlow/Channel: Reactive state management

Error Handling Strategy

  1. Layered Error Handling: Each layer handles specific error types
  2. Sealed Error Classes: Type-safe error representation
  3. Result Wrapper: Consistent success/failure handling
  4. User-Friendly Messages: Meaningful error messages for UI

Validation Architecture

  1. Field-Level Validation: Real-time validation as user types
  2. Form-Level Validation: Complete form validation before submission
  3. Business Rule Validation: Use cases enforce business constraints
  4. Server-Side Validation: API validates recipient existence

Firebase Integration

  • Real-time Sync: Transactions sync to Firebase after payment
  • Offline Support: Local state management with remote sync
  • Platform Specific: Android-only Firebase implementation using expect/actual

Security Considerations

  1. Request Headers: Platform identification and versioning
  2. Error Masking: Generic error messages to prevent information leakage
  3. Input Validation: Multiple validation layers
  4. Network Security: HTTPS enforcement, timeout configurations

Shared KMP Components

  • Payment Models: Data classes for payment requests/responses
  • API Client: Ktor-based HTTP client for backend communication
  • Validation Logic: Email format, amount, currency validation
  • Firebase Integration: Firestore operations with expect/actual declarations
  • Business Logic: Payment processing workflows

Cross-Platform Benefits

  • Code Reuse: code sharing between Android and future iOS
  • Consistent Validation: Same business rules across all platforms
  • Unified API Layer: Single source of truth for backend communication
  • Testable Architecture: Shared tests run on all target platforms

This architecture provides excellent separation of concerns, testability, and maintainability while leveraging KMP's code sharing capabilities effectively.

🔧 Getting Started

Prerequisites

  • Android Studio with Kotlin Multiplatform plugin
  • JDK 11+ for backend services
  • Docker for containerized backend deployment
  • Firebase Project with Firestore enabled
  • Node.js for Appium UI testing
  • JMeter for API performance testing

Backend API Setup

# Start the backend services
cd backend
docker-compose up -d

# Verify API is running
curl http://localhost:8080/payments/health

Running Android App

# Install and run on device/emulator
./gradlew :androidApp:installDebug
./gradlew :androidApp:run

Running Tests

BDD Tests (Spek Framework)

# Run behavior-driven tests for shared KMP module
./gradlew shared:testDebugUnitTest --tests "com.getcashi.payment.bdd.PaymentBddSpec"

# Run all Android unit tests in shared module
./gradlew shared:testDebugUnitTest

# Run with verbose output for debugging
./gradlew shared:testDebugUnitTest --tests "com.getcashi.payment.bdd.PaymentBddSpec" --info

Example scenarios covered:

  • Valid Payment Processing: Given valid payment details, when submitted, then payment is processed successfully and synced to Firestore
  • Invalid Recipient Validation: Given payment with invalid recipient email, when submitted, then validation error is returned and no Firestore sync occurs
  • API Server Error Handling: Given valid payment details but API server error, when submitted, then payment fails with appropriate error message

Test Structure:

  • Uses Spek2 framework with Gherkin-style Given/When/Then syntax
  • Mocks PaymentApiClient and TransactionSync dependencies
  • Tests SendPaymentUseCase with PaymentRepositoryImpl
  • Covers success paths, validation failures, and error handling scenarios

Unit Tests (JUnit/Kotest)

# Test shared KMP logic (validation, API response handling)
./gradlew :shared:test

# Test Android-specific code
./gradlew :androidApp:testDebugUnitTest

UI Tests (Appium)

Prerequisites:

  • Java 11+ and Android SDK configured
  • Node.js 16+ for Appium server
  • Android emulator or physical device

Setup:

# Install Appium globally
npm install -g appium

# Install required drivers
appium driver install uiautomator2
appium driver install espresso  # For Compose apps

# Create Android Virtual Device if needed
avdmanager create avd -n Pixel_7_API_34 -k "system-images;android-34;google_apis;x86_64"

Test Structure: Located in androidApp/src/test/java/com/getcashi/payment/android/appium/:

appium/
├── BaseAppiumTest.kt              # Base test configuration
├── pages/PaymentPage.kt           # Page Object Model for payment screen
├── tests/PaymentAppiumTest.kt     # JUnit test cases
├── cucumber/
│   ├── CucumberTestRunner.kt      # Cucumber BDD test runner
│   └── steps/PaymentSteps.kt      # BDD step definitions
├── utils/
│   ├── AppiumWaits.kt            # Custom wait utilities
│   ├── ScreenshotUtils.kt        # Screenshot capture utilities
│   └── TestDataGenerator.kt      # Test data generation helpers
└── resources/features/
    └── payment.feature            # BDD feature files

Running Tests:

Option 1: Automated Script (Recommended)

# Make script executable
chmod +x run-appium-tests.sh

# Run all UI tests with automatic setup/cleanup
./run-appium-tests.sh

Option 2: Manual Execution

# 1. Start Appium server
appium --config appium-config.json
# Or: appium --port 4723 --log-level info

# 2. Start Android emulator (new terminal)
emulator -avd Pixel_7_API_34 -no-snapshot-load
adb wait-for-device

# 3. Build and install app
./gradlew clean assembleDebug installDebug

# 4. Run specific test suites
./gradlew test --tests "*CucumberTestRunner"     # BDD tests
./gradlew test --tests "*PaymentAppiumTest"      # JUnit tests
./gradlew test --tests "*Appium*"               # All Appium tests

Test Scenarios Covered:

  • Payment Flow: Complete payment submission with success validation
  • Form Validation: Email format, amount validation, empty form handling
  • Currency Selection: USD/EUR currency switching
  • Transaction History: Verify payments appear in real-time history
  • Error Handling: Invalid input validation and error message display

BDD Feature Tests: The Cucumber tests cover user scenarios defined in payment.feature:

  • Send successful payment with transaction history verification
  • Validate invalid email format with error handling
  • Test zero amount validation
  • Multi-currency payment support

Test Reports: After execution, reports are available at:

  • HTML Report: build/reports/tests/test/index.html
  • Cucumber Report: build/reports/cucumber-report.html
  • Screenshots: build/appium-screenshots/ (captured on failures)

Key Features:

  • Page Object Model: Maintainable UI interaction abstractions
  • BDD Support: Cucumber integration with Gherkin syntax
  • Automatic Screenshots: Failure debugging with visual evidence
  • Compose Support: Optimized for Jetpack Compose UI testing
  • Parallel Execution: Support for concurrent test runs
  • CI/CD Ready: Integration with automated build pipelines

Troubleshooting:

# Check Appium server status
curl http://127.0.0.1:4723/status

# Verify device connection
adb devices

# Check app installation
adb shell pm list packages | grep com.getcashi.payment.android

# View test logs with details
./gradlew test --tests "*PaymentAppiumTest" --info

Performance Tests (JMeter)

# Test /payments endpoint under load
cd load-testing
jmeter -n -t payment-api-performance.jmx -l results.jtl -e -o reports/

# Simulates 5 concurrent users hitting POST /payments
# Measures response times and throughput

🔌 API Endpoints

Core Challenge Endpoints

Method Endpoint Description Payload
POST /payments Primary challenge endpoint - Process payment {"recipientEmail": "[email protected]", "amount": 100.0, "currency": "USD"}
GET /payments/health API health check for testing -

Request/Response Examples

Send Payment

POST /payments
{
  "recipientEmail": "[email protected]",
  "amount": 25.50,
  "currency": "USD"
}

Response:
{
  "success": true,
  "data": {
    "id": "uuid-here",
    "recipientEmail": "[email protected]", 
    "senderEmail": "[email protected]",
    "amount": 25.50,
    "currency": "USD",
    "status": "COMPLETED",
    "timestamp": 1642435200000,
    "transactionReference": "TXN_ABC123"
  }
}

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages