Javlon Baxtiyorov
← All projects
Open library  ·  in service  ·  2024 – present

Payment Rails

Five payment providers behind one interface.

One Python library that connects your app to all of Uzbekistan's payment providers through a single, consistent API.

Role
Author & maintainer
Impact
5 providers · 1 API
Open source
2★ · Python
PyPI downloads
384 · 99/30d
Year
2024 – present
Fig. 1 — Payment Manifold: five payment provider inlets converging into a unified API outlet PAYME CLICK UZUM PAYNET OCTO MANIFOLD CHAMBER PRESSURE UNIFIED API OUTLET · UNIFIED API COUPLING fig. 1 — payment manifold INLET TO OUTLET
fig. — payment rails

The problem

Every Uzbek product re-builds the same five fragile payment integrations from scratch — the exact code most likely to leak money.

Every product that takes money in Uzbekistan re-implements the same five integrations: different request shapes, different webhook contracts, different verification rules, the same bugs. The cost is paid again by every team, and the surface most likely to leak money is the one most often hand-rolled. I rewrote the webhook layer three times before the state machine felt honest. Money code that 'mostly works' is just a slower bug.

What I built

One gateway class per provider behind a shared interface, with built-in webhook handlers that speak each provider's dialect — including JSON-RPC 2.0 — and normalise them into a single transaction lifecycle. Integrity and verification checks are part of the library, not an exercise left to the integrator. The seam for adding a sixth provider is deliberately small. Naming things across five providers was harder than the integrations. One vocabulary, or it isn't unified.

Key decisions

The library owns the boring, dangerous parts — signature checks, state transitions, callback parsing — and hands back a clean transaction object. It does not own your database or your money logic. The goal was not to abstract payments away, but to make the correct integration the path of least resistance. Shipped it so the next team in Tashkent doesn't lose the same week I did.

The result

Teams drop in one library instead of losing a week per provider, and the dangerous parts — signatures, webhooks, state transitions — are handled correctly by default.

5 providers · 1 API

Built with

PaymeClickUzumPaynetOctoJSON-RPC 2.0 webhooksDjango · FastAPI · FlaskPython

Lessons from the bench

  •  I rewrote the webhook layer three times before the state machine felt honest. Money code that 'mostly works' is just a slower bug.
  •  Naming things across five providers was harder than the integrations. One vocabulary, or it isn't unified.
  •  Shipped it so the next team in Tashkent doesn't lose the same week I did.

See the code

Open unipay-uz on GitHub