Follow the arrows — money and goods, step by step
If the seller never delivers → buyer does nothing → money auto-refunds after timeout.
Typical transaction completes in a few hours. Maximum timeout is configurable.
The buyer inspects the goods, then decides
"I'm satisfied"
Money → Seller now
No admin needed
Enter return code
Money → Buyer refund
No admin needed
"Something's wrong"
Money frozen → review
Only path needing admin
Auto-release
Money → Seller (48h)
Default — protects seller
Same trust mechanism — reversed direction
Proves buyer RECEIVED
🛡 Code = proof of PHYSICAL RECEIPT
Proves buyer RETURNED
🛡 Code = proof of PHYSICAL RETURN
Both codes generated when buyer pays. Seller sees both from day one.
Buyer NEVER sees either code until the physical handover.
Every social commerce scam — and why it's impossible on TandPay
Buyer sends doctored image of a payment
System checks real MoMo payment status — no screenshots
Buyer calls MTN: "accidental transfer"
Pawapay merchant account — MTN can't reverse it
Takes payment, blocks buyer, vanishes
Money returns to buyer after timeout — zero effort
Seller or third party tries to confirm delivery
Only buyer's phone number can confirm — not even the seller
Buyer claims return without actually returning goods
Code only given after delivery person picks up package — no return = no code = no refund
Pawapay (licensed PSP) holds the money. TandPay provides the technology.
Every physical handover is verified by a code only the buyer can enter from their own phone.
Two-factor verification: you need BOTH the physical code AND the authenticated phone session
Physical proof — comes from the package
4-digit random code generated using cryptographically secure random number generator
Stored as SHA-256 hash in the database — even if the database is breached, the plaintext code cannot be recovered
The seller sees the plaintext code to embed in the package. The buyer never sees it until physical handover
Identity proof — tied to MoMo number via OTP
When buyer pays, they verify their phone via SMS OTP — proves they own the MoMo number
System generates a buyer session token — stored as SHA-256 hash on the transaction, token saved in buyer's browser only
This token is unique to this buyer + this transaction — no other phone, no other browser can use it
Buyer's browser sends: buyer_token + code (4 digits)
Server computes: SHA-256(buyer_token)
Compares with stored hash using constant-time comparison (prevents timing attacks)
Server computes: SHA-256(code)
Compares with stored delivery_code_hash or return_code_hash
Rate limit check: max 10 attempts per 15 minutes
Prevents brute-force guessing of the 4-digit code
Both checks pass → action triggered
Delivery code → release payment · Return code → process refund
Knows the code but does NOT have the buyer_token. Without the token, entering the code is rejected.
Has code ✓ · Has token ✗ = BLOCKED
Might intercept the code but does NOT have the buyer_token (stored only in the buyer's browser).
Has code ✓ · Has token ✗ = BLOCKED
Has the token (from OTP verification) AND gets the code from the physical package.
Has code ✓ · Has token ✓ = ALLOWED
SHA-256 Hashing
All codes and tokens are stored as one-way hashes. Even a database breach reveals nothing.
Constant-Time Comparison
Prevents timing attacks — response time is identical whether the code is right or wrong.
Rate Limiting
10 attempts per 15 minutes per transaction. Brute-forcing a 4-digit code requires 10,000 tries — blocked after 10.
SMS OTP Phone Binding
Buyer's session token is created only after SMS OTP verification — proving ownership of the MoMo phone number.
This two-factor model follows the same principle as chip-and-PIN bank cards: something you HAVE (the code from the physical package) + something you ARE (the verified phone owner).