Skip to main content
Every time money moves in OwnPay - a customer pays, a gateway deducts fees, a refund is issued - the system records it as a pair of balanced journal entries. This is double-entry bookkeeping, the same method used by accounting software and banks. It means you can always trace where money came from and where it went, and the total debits always equal the total credits.

How double-entry works in OwnPay

When a $100 payment completes through Stripe (with a $2.90 gateway fee), OwnPay creates four ledger entries across three accounts: The net effect: $100.00 credit = $97.10 debit + $2.90 debit. The books balance to zero.

Account types

OwnPay uses standard GAAP account categories:

Balance calculation

All monetary math uses PHP’s bcmath extension - never floating-point arithmetic. Balances are validated at 4-decimal precision using bccomp().
Never manually update the op_ledger_accounts.balance column. Always use LedgerService - direct SQL edits will cause reconciliation mismatches.

Double-post prevention

OwnPay guards against recording the same payment twice. Before inserting ledger entries, the system acquires a row lock:
If a matching row exists, the operation is skipped. This runs inside a database transaction, so concurrent requests are serialized safely.

Brand isolation

Ledger accounts are scoped to a merchant_id (brand). Brand A’s cash balance is completely independent of Brand B’s. The repository enforces this at the query level:

Reconciliation

You can verify your ledger balances against gateway settlements at any time. OwnPay includes a CLI reconciliation command:
This compares OwnPay’s recorded transactions against the gateway’s reported totals and flags any discrepancies. For the GUI-based version, see the Balance Verification page in the admin dashboard.
Last modified on August 25, 2026