Skip to content

// project

PaymentsLab-KMP

An Integration Lab for the Android payments ecosystem: every gateway behind one abstraction, with a live look at what actually happens on each transaction.

The brief

Payments is the hardest integration surface on Android: every gateway ships a different SDK, most of them are Activity-callback-era, the client can lie about the outcome, and the interesting logic (signatures, webhooks, idempotency, recovery) lives on the server. PaymentsLab-KMP runs real payment flows across a 66-gateway catalog behind a single PaymentGateway abstraction, and visualizes them step by step. A Ktor server does the order creation, signature verification and webhook reconciliation a real integration requires. Beyond one-shot pay-in it models five money-movement rails.

What shipped

  • 44-module registry (15 local + 29 composed) spans 66 cataloged payment gateways.
  • Five money-movement rails plus split payments, all idempotency-keyed and MOCK_MODE-honest.
Kotlin MultiplatformCompose MultiplatformKtorAndroidiOSRoom
GitHub Doori (sibling KMP app) Install it 44 modules · 66 gateways · 5 rails
built onkmp-build-logickmp-toolkit
written up inOne Brain Two Bodies

// case study

The short version

The problem

Every payment gateway ships a different, mostly Activity-callback-era SDK, and the client can lie about the outcome: the logic that actually decides whether money moved (signatures, webhooks, idempotency, recovery) has to live somewhere the client can't fake it.

The decision

Put a Ktor server between the client and the truth: order creation, signature verification and webhook reconciliation happen there, a Room journal is written before the SDK even launches so a process death mid-payment is always recoverable, and a redaction layer keeps every secret and PII out of logs and screens.

The result

66 cataloged gateways now sit behind one PaymentGateway contract, with a client-side Success read only as a hint until the server confirms it. The same discipline now extends to five money-movement rails beyond one-shot checkout, every one of them MOCK_MODE-honest until real sandbox keys are set.

66 gateways cataloged

Watch the two-minute tour ↓
Evidence: 66 cataloged gateways now sit behind one PaymentGateway contract, with a client-side Success read only as a hint until the server confirms it. The same discipline now extends to five money-movement rails beyond one-shot checkout, every one of them MOCK_MODE-honest until real sandbox keys are set.

// guided tour

Two minutes, narrated

A storyboarded walkthrough of the real app — tap the speaker for the voiceover, or read along with the captions.

PaymentsLab-KMP — narrated product tour

// shipping

Where you can actually get it

Every line below is checkable. Add the repository in an F-Droid client and the app installs, signed with the same key its listing pins.

  • F-DroidLive in a self-hosted repository. 33 MB, signed, tagged NonFreeDep and NonFreeNet because integrating real gateway SDKs is the whole point of the app. open
  • GitHub ReleasesSigned APK per tag. open

// pipeline

The build that put it there

Read live from GitHub Actions and the F-Droid index. Not a badge: the actual runs, what shipped, and the certificate you can check the download against.

reading the pipeline

44

Gradle modules (15 local + 29 composed)

66

gateways cataloged

5

money-movement rails

1

PaymentGateway contract

// multiplatform

One codebase, every surface

The real screens (and, where it's live, the running build) per platform — not a mockup.

Android screen (1 of 5)

// design notes

How it works

The one idea worth stealing

A client-side Success is a hint, never proof. Only the server decides the true state, after signature verification and webhook reconciliation. A server that owns price and truth, a client that always confirms before trusting, a journal written to Room before the SDK launches so a process death mid-payment is always recoverable, and a redaction layer so no secret or PII ever renders or logs.

44 modules, 66 gateways

One Gradle module per native-SDK provider is contributed into a registry via Koin's getAll<PaymentGateway>(), so adding gateway N+1 touches no existing code. There are 15 local modules plus 25 composed from kmp-toolkit (19 of them standalone provider gateway modules). The in-app catalog spans 66 registered gateways: 7 native-SDK integrations, 47 hosted-webview gateways behind one archetype, 8 mobile-money flows and 4 catalog-only / KYC-gated entries, each with its own status badge and region.

Five money-movement rails + split payments

Beyond one-shot checkout the server models payouts (/payouts: money out to a beneficiary), mandates & subscriptions (/mandates + scheduled debits and cancel), a card vault (/vault: tokenize once, charge later by id), marketplace Connect onboarding (/connect: sub-merchant KYC + split payouts) and an internal double-entry wallet ledger (/wallet: seed / debit / refund against a real running balance), plus split payments, a two-leg orchestration that compensates if one leg fails. Ten provider modules ride these rails (Paystack, Flutterwave, Paytm, Xendit, M-Pesa, Peach, NMI, Stripe Connect, plus wallet and a record-only cash gateway), every one MOCK_MODE-honest until real sandbox keys are set.

One contract, real SDKs

Razorpay, Cashfree, Stripe (+ Google Pay), Square, Omise and a raw UPI intent flow all implement the same tiny PaymentGateway interface. The Activity-callback SDKs are bridged into suspending coroutines by a PaymentHost that never leaks an Activity upward. A generic hosted-webview archetype covers the whole class of gateways with no native SDK behind the same contract. Env-backed credentials auto-degrade from SANDBOX_READY to MOCK_MODE honestly instead of silently pretending to work.

Pure, replayable state machine

The lifecycle is a pure (State, Event) → Effects reducer, zero coroutines/DI/IO, with the orchestrator just executing its effects. A payment's path is a recorded event log that replays byte-for-byte identically, the auditing property money movement wants. The MVI base comes from my own kmp-toolkit library, shared with other apps.

VAPT-grade security

core:security holds real Android Keystore AES-256-GCM at-rest encryption, FLAG_SECURE + recursive tapjacking protection, device-integrity checks (root, emulator, debugger, Frida/Xposed hook detection, SSL-pinning-bypass detection), and a certificate-pinning config, with detection kept deliberately separate from enforcement policy.

// architecture

How it's built

Gateway registry: adding provider N+1 touches no existing code

Client Success is a hint: the server decides truth

Five rails beyond one-shot pay-in

// under the hood

Tech stack

Architecture

  • Kotlin Multiplatform
  • Compose Multiplatform
  • 44 Gradle modules (15 + 25 composed)
  • Koin registry (getAll)
  • kmp-toolkit (shared MVI base)

Backend & rails

  • Ktor server
  • HMAC-SHA256 signatures
  • Webhook reconciliation
  • Payouts · mandates · vault · connect · wallet ledger

Data & Security

  • Room (process-death journal)
  • Android Keystore AES-256-GCM
  • Certificate pinning
  • Device-integrity checks

Build & quality

  • kmp-build-logic convention plugins
  • Roborazzi screenshot tests
  • ktlint
  • detekt
  • GitHub Actions CI

// directions

Same screen, 3 treatments

Pick a treatment to see it whole. Where one ships a dark counterpart, drag the divider to compare the two faces of it — same layout, same content, only the light changes.

checkout lifecycle — order summary, light
order summarysingle mode — no dark counterpart

// gallery

Screens (28)

Swipe or use the arrows · tap a screen to enlarge

See how everything connects →

frequently asked

What does he do at Dice.tech?

SDE-2, Android & Product Owner at Dice.tech (June 2023 - Present), platform owner of the app behind 50k+ monthly active users (22k+ daily, platform owner at Dice.tech). See the source.

What did he do to improve GPS accuracy?

Took GPS accuracy to 95%: up from 50%, by predictive dead reckoning. See the source.

How did he reduce production crashes?

80% crash reduction: Crashlytics + structured concurrency fixes. See the source.

How much of the app is Jetpack Compose?

~87% of the UI layer: 455k of 523k UI-layer LOC, verified screen by screen against the legacy XML. See the source.

Where did he study?

B.Tech, Computer Science & Engineering, NIT Bhopal (MANIT) (2017 - 2021). See the source.

What is the Neev Consulting role?

Consulting Engineer, Platform & AI at Neev Consulting (April 2026 - Present). Built the LLM assistant layer of an ERPNext/Frappe consulting ERP: business-context resolution, capability discovery, and an AI capability gate that defaults OFF with a test proving it. Models client to project to PO to milestone to GST invoice to payment end to end. See the source.

What is Doori?

Doori: Offline-first mileage, travel & expense tracker on one Kotlin codebase across Android, iOS, Wear OS, watchOS & Desktop. See the source.

What is Gaddi?

Gaddi: A Hinglish social-deduction bluffing game of power, satire & second chances. Gaddi ke liye kuch bhi karega. See the source.

What is PaymentsLab-KMP?

PaymentsLab-KMP: An Integration Lab for the Android payments ecosystem: every gateway behind one abstraction, with a live look at what actually happens on each transaction. See the source.

What is Candidai?

Candidai: A native, multiplatform AI career-intelligence engine, and the open-source project it's built on. See the source.

Does he write, outside of code?

Yes: The Loopdown, his field-notes writing hub, where the recurring bug characters are named after real production incidents. See the source.

What's he like to work with?

Answered by his own teammates, not by him: see the EB Profiles, one question per member, in their own words. See the source.

Is he available, and how do I reach him?

Open to remote (worldwide / India) and hybrid in Pune / Bengaluru. Email siddharthpandalai990@gmail.com. See the source.

What has he contributed outside employer work?

Shared Kotlin Multiplatform libraries used across his own apps, plus merged upstream pull requests on career-ops: see the repos and the running count. See the source.

Has anything he's built shipped for real?

Yes: see the Play Store shelf for the apps that are actually live and installable, not just source. See the source.

What can I try on this site besides reading it?

Every route on the site, as a tile you can open: 3D builds, labs and canvases, not screenshots. See the source.