Monaf Horany
All work

004

2021 — 2024

Orjeen

A cross-platform commerce app for a Saudi online store, with instalment and card payment gateways integrated end to end.

payment gateways
2
shipped on
iOS + Android
market
KSA

Architecture

Orjeen payment flowThe Flutter app starts a checkout against the backend, which creates a pending order and redirects the customer to either the Tabby instalment gateway or the Urway card gateway. Each gateway confirms the result directly to the backend through a server-to-server callback, and only that callback settles the order state. The customer's return to the app is treated as a display concern, not as proof of payment.1 · begin checkout2 · redirect3 · server-to-server callback settles the orderFlutter appOrjeenBackendorder authorityTabbyinstalmentsUrwaycardOrdersPostgreSQL
The Flutter app starts a checkout against the backend, which creates a pending order and redirects the customer to either the Tabby instalment gateway or the Urway card gateway. Each gateway confirms the result directly to the backend through a server-to-server callback, and only that callback settles the order state. The customer's return to the app is treated as a display concern, not as proof of payment.
  • Client
  • Service
  • Data store
  • External

The problem

Orjeen ran an online store serving the Saudi market. The app needed regionally correct payment methods — instalments are a mainstream expectation in the Gulf, not a niche option — and delivery addresses precise enough to actually find a building.

Gulf customers expect Tabby instalments alongside ordinary card payment, and both have to be trustworthy: a payment that half-succeeds is worse than one that fails cleanly. Street addressing in the region is often unreliable, so a typed address is frequently not enough for a courier to complete a delivery.

The approach

I integrated Tabby for instalments and Urway for card payment, treating the gateway callback rather than the client's return trip as the authority on whether a payment happened. The app was structured MVVM with Cubit state management. Addresses are confirmed by dropping a map pin, so the order carries coordinates rather than only a text address.

Decisions that mattered

  1. 01

    MVVM with Cubit

    Cubit over full BLoC: the app's state transitions are mostly straightforward, and Cubit expresses them without the event-class boilerplate that buys nothing at this complexity.

  2. 02

    Trust the callback, not the client

    Payment state is settled by the gateway's server-to-server callback. A customer closing the app mid-redirect, losing signal, or double-tapping cannot desynchronise the order from the money.

  3. 03

    Meeting the existing store where it was

    The business already ran on WooCommerce. Rather than force a migration as a precondition, the app consumed the WooCommerce REST API and additional services filled the gaps — the store kept operating throughout.

Hard problems

  1. 01

    Two gateways, one checkout

    Tabby and Urway have different flows, different callback shapes and different failure modes. The checkout presents one coherent path to the customer while reconciling both behind a common interface, so neither gateway's quirks leak into the ordering logic.

  2. 02

    Addresses a courier can actually use

    Geolocation and geocoding let customers confirm delivery by map pin. The order stores coordinates alongside the written address, which is the difference between a delivery attempt and a delivery.

  3. 03

    Rebuilding without stopping

    The app moved from an Ionic/Angular build to Flutter while the store stayed open. The migration ran feature by feature against a live backend rather than as a big-bang cutover.

My role

Built the Flutter application, integrated both payment gateways, and worked across the backend that served it.

Status

Delivered and operated for the client. The store and its app listings are no longer live, so this case study describes the engineering rather than linking to a running product.

Stack

Mobile
FlutterMVVMCubitFCMFirebase Analytics
Payments
TabbyUrway
Location
GeolocationGeocoding
Backend
NestJSNode.jsWooCommerce REST