· Payments

One checkout abstraction for KNET, mada, STC Pay and Tabby on Android

GCC users don't share one payment habit. Kuwait expects KNET; Saudi expects mada and STC Pay; BNPL via Tabby is growing everywhere. Separate checkout flows for each gateway killed conversion until we unified them.

The symptom

At Ozoned Digital, five gateways meant five checkout implementations. Users picked a method, hit a provider-specific error, and abandoned — no cross-fallback, inconsistent retry UX. Measured outcome after unification: +50% transaction success (case study).

The PaymentProvider interface

Every gateway implements the same narrow contract:

Checkout UI asks: "which providers are available?" → user picks → orchestrator calls the provider → single success/failure surface. Adding KNET for Kuwait is a new class, not a fork of the checkout composable.

Card acquirers vs local wallets

We run Tap Payments (GoSell) and Checkout.com (Frames) for card rails, plus Google Pay where supported. Local wallets (KNET, Benefit, mada, STC Pay, Tami) often need app-to-app or WebView redirects — the orchestrator handles lifecycle and deep links uniformly.

Tabby BNPL sits alongside cards: eligibility check, installment selection, then confirm — same state machine as card 3DS.

In-app tender counts too

White-label coffee apps use wallet balance, gift cards and promo codes as first-class tender types — not afterthoughts bolted onto card checkout. The order total splits across tenders before any external gateway is invoked.

Production today

The same abstraction runs across COFE white-label brands in production — ten+ tender types, regional configs per brand, analytics on initiation/success/failure per provider for ops teams.

Need this integrated?

Android payment integration services · hire for a contract.

Ahsan Islam