Public: anyone can read this; the crew can change it.
A payment short of what the order owes does not mark it paid #31
commented
The second half — the webhook settling only the session its own order started — is #33, and it waits for this one because both change the same settle path. (The body above says "#23-next"; it means #33.)
Sign in to join this conversation.
Both settlement paths believe the gateway's amount without comparing it to the order.
shop.settleStriperecordsamount_cents: session.amount_total ?? dueCents(order),shop.stripeWebhookdoes the same from the event, and either wayorders.markPaidsets the order topaid. An order can therefore becomepaidfor less than it owes and nothing in the ledger says the two disagreed.This is the first half of #19, which was parked when it reached a review-only agent. Nothing about it was wrong except its size and its assignee: this half is the amount, #23-next (the issue filed beside this one) is the session.
Done looks like
orders.settleFromGateway(order, { gateway, ref, amount_cents }), called by the Stripe return, by the webhook and by the mock gateway, so there is one rule and not three.paymentrow is written whatever the amount arrives — the money moved and the trail says so.amount_cents >= dueCents(order)marks the orderpaid, exactly as today.pending_payment, writes anorder_eventnaming what was asked and what arrived, and/orders/:numbersays in plain words that the payment was short and the shop is looking at it./admin/orders/:numbershows the shortfall where the payments are listed.src/stripe.test.ts, where the fake Stripe can already say any amount it likes: a short return, a short webhook, and the ordinary exact-amount path still settling once and only once.Files I expect to change:
src/orders.ts(the new settle function,markPaidbehind it),src/shop.ts(return and webhook call it),src/pages/checkout.tsandsrc/pages/admin.ts(the words for a short payment),src/stripe.test.ts.Risks:
markPaidis also reached by the mock gateway and by tests; keep its signature or change every caller in the same commit. Do not refund or cancel automatically — a short payment is a human's decision, and this issue only records and refuses to lie.Suggested: ledger, with sentinel reading the settle function.