Litestore · Help center
Commerce

Payments

Connect Stripe, read the ledger that records every money movement on an order, and keep track of disputes.

Litestore takes payments through Stripe and records every money movement in a ledger. When totals don't match, the ledger is the figure to use.

Order #1048 payments●Paid
1authorizationCard held$116.16
2captureStripe confirmed$116.16
3refundReturn #R-1007−$48.00
Refunded of order total$48.00 / $116.16
Litestore rejects a refund above the remaining $68.16.
Each authorization, capture and refund is its own ledger row, and refunds can't add up to more than the order total.

Payment records

Litestore writes every capture, refund, dispute and adjustment to a payment ledger. The database rejects any edit or deletion in it.

The ledger is the main subject here. Order totals are a summary, and a summary can be wrong. The ledger is the list of what actually happened to the money, and Litestore builds it so that nobody can quietly turn it into a different list later.

Stripe is the only payment provider Litestore is wired to.

Litestore uses two records for all of this:

PaymentTransaction
PaymentDispute

PaymentTransaction is a row in the ledger. PaymentDispute stores a chargeback.

Ledger entries

Every ledger row has one of five types:

authorization
capture
refund
dispute
adjustment

Together they cover every way money can move on an order. It can be held, taken, given back, reversed by a bank or corrected.

Append-only ledger

The database rejects any attempt to change or delete a ledger row.

To correct a mistake, Litestore adds a new row. It never edits an old one.

Because rows are never changed, the ledger reconciles against the payment provider's records. An editable ledger would only hold the values someone last entered, so it couldn't show the payments, refunds and corrections that actually happened to an order.

The ledger therefore keeps the mistakes as well as the money. A wrong amount and the adjustment that corrected it both stay visible, in order, with the time each was written.

An order's financial history stays complete, and it doesn't depend on anyone being careful.

Duplicate protection

The database only allows one row for each combination of provider, provider reference and type. If Stripe sends the same payment confirmation twice, Litestore counts it once.

This isn't a rare case. Payment providers resend confirmations when they don't get an acknowledgement, which is the right thing for them to do. The ledger therefore has to receive the same event twice and record it once.

The type is part of the combination on purpose. A capture and a refund can share a provider reference, and Litestore won't mistake one for a duplicate of the other.

Order currency

The database rejects a ledger row whose currency doesn't match the order's currency.

A ledger that mixes currencies is worse than one with missing rows. Its totals still add up, but to a meaningless number. By refusing the row, Litestore makes sure every sum on an order is in one currency.

Refund ceiling

Refunds are capped at the order total

As Litestore writes each refund row, it adds up every refund already on the order. If the running total would go past the order total, it rejects the write. A second protection blocks edits and deletes on ledger rows and enforces the currency match.

The recount is what makes this work. Litestore doesn't just check whether this one refund is smaller than the order total. It checks whether all the refunds on the order together would come to more than the customer was billed.

Even when different people issue refunds days apart, through different routes, the refunds can't add up to more than the customer paid.

Base-currency totals

Each order also stores its total converted to the store's base currency at the time of purchase.

Revenue figures use that stored value. They don't fall back to the total in the order's currency.

Because Litestore stores the converted figure at the moment of sale, the store's reports stay consistent as exchange rates move. A quarter's revenue doesn't change because a currency moved afterwards, and last year's numbers stay the numbers you reported last year.

Drift views

Orders and customers both keep cached totals. These should always match what the database calculates from the underlying records.

If they ever differ, the database views OrderMoneyDrift and CustomerMoneyDrift list the order or customer. Litestore never corrects a difference on its own.

Cached totals keep lists fast, and the views keep them honest. The views aren't shown in the admin, so whoever runs the store queries them. You can also ask the assistant whether the store's order revenue matches the Stripe payment ledger.

Dispute records

For each chargeback, Litestore stores these details.

FieldWhat it records
ReasonWhy the customer disputed the charge.
StatusWhere the dispute stands at the provider.
AmountHow much money is in dispute.
Evidence deadlineWhen the evidence is due.
Evidence submittedWhether evidence was submitted.
HandlerThe staff member handling it.

The queue shows which disputes still need a response, so you work through them without leaving the admin. You still file the evidence itself with the payment provider.

Setup

Stripe keys

Set your Stripe secret key and webhook secret. When you open Settings → Payments, Litestore checks the connection and shows the response it receives from Stripe.

Incoming payments

Captures, refunds and disputes write ledger rows as they happen.

Reconciliation

Ask the assistant from time to time to check that order revenue matches the payment ledger, and have whoever runs the store watch the drift views.

You do the day-to-day money work in the Refunds and Disputes queues.

Authoritative totals

Litestore can always recalculate a summary from the ledger rows, which is why the rows themselves can't be edited.

On this page