User guide
How to use Paymob Payment Provider for Egypt, screen by screen.
How a payment actually completes
Odoo backend --secret key--> Intention API --> client_secret
Customer browser --public key + client_secret--> Unified Checkout
Paymob server --HMAC-signed callback--> Odoo webhook --> transaction stateThe callback decides the outcome. The browser return never does.
A customer can close the tab, lose signal, or edit the return URL by hand. None of that changes what Paymob charged. The return route only chooses which page to show them; the transaction state comes from the signed server-to-server callback and nowhere else.
This is the single most important thing about the module, and the reason a payment can be correct in Odoo even when the customer never saw a confirmation page.
Where customers can pay
- Website checkout
- Portal invoices
- Portal quotations
Anywhere Odoo's own payment framework offers a provider, this appears — in EGP, and only in EGP.
Payment Transactions
Accounting → Configuration → Payment Transactions, or from the invoice.
Each row carries Paymob's own identifiers, so a transaction here can be matched against the Paymob dashboard without guesswork.
The states
| State | Meaning |
|---|---|
| Draft | An intention exists; nobody has paid |
| Pending | Awaiting the callback, or an authorisation awaiting capture |
| Done | Paymob confirmed the payment by signed callback |
| Cancelled / Error | Refused, or failed, with Paymob's reason |
Refunds
Refund from the transaction, in whole or in part.
A refund is submitted and left pending until Paymob confirms it by callback. It is not marked done at submission, deliberately: marking it done sooner would report money as returned to a customer before it actually was, and somebody would reconcile against that.
What it will not do
- Card payments only. Mobile wallets, Apple Pay and BNPL each need their own integration ID and their own testing. They are not claimed until they have it.
- No saved cards. Paymob supports card tokens, but storing one is a commitment to its lifecycle and to consent handling, and neither is built here — so it is not advertised.
- No manual capture. An authorise-then-capture is recognised on an inbound callback but cannot be started from Odoo.
- EGP only.
Duplicate callbacks
Paymob retries. A repeat callback for a transaction already in its final state is ignored rather than reapplied, so a retry cannot confirm an order twice.
A refund callback is the deliberate exception — a second refund on the same transaction is a real event, not a duplicate.
Test mode
Enable the provider in Test mode with test keys. The guard refuses a live key on a test provider and a test key on a live one, so you cannot silently end up charging real cards during a rehearsal.
Verification status
No payment has ever been taken through this module. There are no Paymob merchant credentials on the development account, so nothing has reached Paymob's sandbox or production — not one intention, not one callback.
Verified over real HTTP against Paymob's documented payload shapes: HMAC-SHA512 verification over the documented twenty-field order including tampering, wrong secrets and field-order sensitivity; state derivation from Paymob's boolean combinations; duplicate and late callbacks; refunds; timeouts; connection errors; and the live-key guard.
Verified in shape only: the Intention API request body. Not verified: acceptance by Paymob, a real checkout session, a real settled payment.
Run a sandbox payment before you take a real one.