Work/Payments
FikazonPay
A concept: get paid through a verified email or link.
In the labConcept only: design documents exist, but no code, no live service and no payment has ever been processed.
Web
The problem
“Why does my bank account number have to be my public identity?”
In Nigeria a bank account number has quietly become a person's public identity. Freelancers paste it into chats and screenshots. Clients mistype it. Changing banks means telling everyone again. Nothing proves that the person quoting an account owns it, so impersonation is easy. Payers abroad, who know nothing about a ten-digit account number, struggle most. The concept narrowed to the receiving side of money coming into Nigeria: verify the recipient once, instead of once for every sender and every beneficiary.
Who had it
- Nigerian recipientsBe paid reliably without handing out bank details again and again.
- Senders abroadPay family, school fees or rent without a day of beneficiary checks.
- Freelancers and remote workersShare one trusted way to be paid, and change banks quietly.
What the answer had to survive
- Must run on licensed partners, not on its own licence.
- In the first design, FikazonPay never holds customer money.
- The recipient's name must come from the bank, not be typed.
- Settlement is usually next business day, so never promise instant.
- Impersonation and mistyped details must be hard.
What we built
One verified payment identity, with the bank account kept behind it.
The concept separates identity from infrastructure. A person registers once, verifies who they are and links a bank account. They receive a permanent payment identity, an email address or a link. A payer opens it and sees the verified legal name, pulled from the bank, before confirming. The payer needs no account. A licensed payment provider collects and settles straight into the recipient's own bank, so the account behind the identity can change without the payer learning new details. All of this is design, not yet code.
What it does
Planned: identity
- Verified recipient namePlanned. The bank confirms the account holder's legal name. The user cannot edit it.
- Permanent payment identityPlanned. An email address and a payment link replace an account number in chats and invoices.
- Change banks quietlyPlanned. The bank behind the identity can change without any payer being told.
Planned: paying
- Pay without an accountPlanned. A payer sees the verified name, amount and fee, then pays by card, transfer or USSD.
- Invite the recipientPlanned. If the recipient is not registered, the payer can send an invitation. No money is taken.
- Flexible fee allocationPlanned. The fee can be carried by the payer, the recipient, or split between them.
Planned: safety
- No held fundsPlanned. A licensed provider splits the payment and settles to the recipient's bank. FikazonPay takes only its fee.
- Fraud controlsPlanned. Verified-name display, a cooling-off period on bank changes, lookalike-name detection and limits for new identities.
- Reconciliation built inPlanned. Unclear provider states become a normal, logged state with a manual resolution path.
Later versions
- Several destinations per identityConsidered for a later version: routing rules by purpose or split.
- Purpose-bound paymentsConsidered for a later version: a payer pays for a stated purpose and the money goes to the right institution.
- Payment requests and balancesConsidered for a later version, and only with licensed partners holding the money.
How it is meant to go
- 1
Register once
Intended flow. A person signs up, verifies email and phone, and links a bank account.
- 2
Bank confirms the name
Intended flow. The bank returns the legal name, and the person receives a payment identity: an email handle and a link.
- 3
Share the link
Intended flow. They share the link or email instead of an account number.
- 4
Payer checks the name
Intended flow. The payer opens the link and sees the verified name, bank, amount and fee before confirming.
- 5
Pay and settle
Intended flow. The payer pays by card, transfer or USSD. The provider settles into the recipient's own bank, usually next business day.
How it works inside
This is the intended design, not a built system. A web app and an API sit in front of a core that knows nothing about any one payment provider. Provider adapters plug into capability-shaped ports, so a provider can be swapped. A licensed provider does the regulated work: collecting, splitting and settling to the recipient's bank.
Cut the network to see what this system does without it.This one lives on the internet, so it waits, like any website. Its staying power is on our side: backups, health checks and tested recovery.
On the device
- Payer or recipient browserIntended: where payment links are opened.
Our cloud
- Payment web appIntended: identity, profile and payment links.
- FikazonPay APIIntended: identity, routing, ledger, fees, risk, reconciliation.
- Domain core and portsIntended: provider-neutral logic behind capability interfaces.
- Ledger databaseIntended: append-only events and ledger entries.
Outside services
- Licensed payment providerIntended: verifies accounts, collects, splits, settles.
- Recipient's bankIntended: receives the settled payment directly.
- Email serviceIntended: notifications and invitations.
- Licensed partner (later)Considered for a later version: collection and custody.
Every part and every link, as text
- Payer or recipient browser — Intended: where payment links are opened. (on the device)
- Payment web app — Intended: identity, profile and payment links. (our cloud)
- FikazonPay API — Intended: identity, routing, ledger, fees, risk, reconciliation. (our cloud)
- Domain core and ports — Intended: provider-neutral logic behind capability interfaces. (our cloud)
- Ledger database — Intended: append-only events and ledger entries. (our cloud)
- Licensed payment provider — Intended: verifies accounts, collects, splits, settles. (outside services)
- Recipient's bank — Intended: receives the settled payment directly. (outside services)
- Email service — Intended: notifications and invitations. (outside services)
- Licensed partner (later) — Considered for a later version: collection and custody. (outside services)
- Payer or recipient browser → Payment web app: Register, open payment link (needs internet)
- Payment web app → FikazonPay API: Requests (needs internet)
- FikazonPay API → Domain core and ports: Use cases (needs internet)
- Domain core and ports → Licensed payment provider: Resolve name, start checkout (needs internet)
- Payer or recipient browser → Licensed payment provider: Payer pays (needs internet)
- Licensed payment provider → Recipient's bank: Settles to recipient (needs internet)
- Licensed payment provider → FikazonPay API: Signed webhooks (needs internet)
- FikazonPay API → Ledger database: Events and ledger (needs internet)
- FikazonPay API → Email service: Notifications, invitations (needs internet)
- Licensed partner (later) → Domain core and ports: Later: collection, custody (needs internet)
The hard parts
Design story: cutting the 72-hour hold
- The situation
- An early idea held unclaimed money for 72 hours until the recipient registered. It was convenient, but it created a custody position and the highest regulatory scrutiny in Nigerian payments.
- What we did
- We removed the hold. In the second design nothing is collected until a verified destination exists. A payer can only send an invitation, with no money involved.
- The lesson
- We take regulatory exposure seriously and design it out where possible.
Design story: a port that is not one vendor
- The situation
- A provider interface built after one vendor's API ends up shaped like that vendor and cannot be swapped.
- What we did
- We split the ports by capability and gave each adapter its own tables. We planned one contract test suite run against a fake, a sandbox and a second provider, plus a rule that the core never imports an adapter.
- The lesson
- Vendor independence is designed in, not hoped for.
Design story: fixing the product, not the pitch
- The situation
- Paying by email inside Nigeria is a mild convenience, because bank transfers are already near-instant. The design also had a cooling-off control that would frustrate real senders.
- What we did
- We reframed the problem as the receiving side of incoming money. Verification cost moves to the recipient, once, not the sender, every time. Payment links became the main flow, and we chose not to compete on exchange rates.
- The lesson
- We test an idea against real constraints and change direction early, before building.
Design story: honest settlement wording
- The situation
- The first overview implied instant settlement. Split settlement to a Nigerian bank is normally next business day.
- What we did
- We flagged the mismatch and required copy that does not promise instant. We also made reconciliation a normal state with a manual path, and forbade inferring state from a successful API response.
- The lesson
- Promises must be ones the system can keep.
The stack
- Backend
- Java and Spring Boot (planned)Hexagonal design (ports and adapters)
- Data
- PostgreSQL (planned)Redis (planned)Double-entry ledger
- Services
- Licensed payment providerAmazon SES email (planned)
- Testing
- Contract tests across several providersIn-memory fakesArchitecture rule tests
How the thinking has gone
- 1Two concept documentsA business overview and a technical design were written. The second design drops held funds.
- 2A phased planA plan was drafted: provider checks, then a core with a fake provider, then a sandbox adapter.
- 3A narrower problemThe concept narrowed to the receiving side of money coming into Nigeria.
- 4A third versionA third concept version was written. There is still no code.
