Payments that stop short of a terminal state
I connect payment providers and find out why payments hang: webhooks, retries, idempotency, reconciliation. The bugs sit between the provider and your database, not in a particular language or framework, so the stack doesn't matter: the same failures turn up in WooCommerce and Magento, Odoo and Medusa, and in custom backends.
Write to hello@terminalstate.dev — a symptom and one payment id are enough to start.
Paid at the provider, pending on your side?
A payment that sits in pending for hours is almost never stuck at the provider. The money moved, or didn't, within seconds. What is stuck is your knowledge of it: the callback carrying the final status was never applied. Between the provider and the row in your database there are seven places where that happens, and each one has its own check.
The map, with the incidents behind it: Seven places a webhook dies between the provider and your database.
Fixed upstream
The same failures, found in open-source payment code and reproduced against each project's own code before they were reported. Of eighty-five reports, thirty-three are fixed, twelve of them by my own pull requests, and five more are in progress. A few of them:
- Bagisto · Razorpay: the amount was truncated instead of rounded, so totals like ₹19.99 were charged and no order was placed. Fixed by my PR. PR #11524
- Paid Memberships Pro · Stripe: the webhook answered 200 when re-fetching the event from Stripe failed, so Stripe never redelivered it. Fixed by my PRs. PR #3890 · PR #3898
- Adyen for Magento 2 · split payments: orders failed with “Full order amount has not been authorized” because authorised amounts were compared at a different precision than they are stored. Fixed by Adyen on 28 Oct, not yet released. #3352 · fix #3397
- Nexi Checkout for WooCommerce: when the status request after a payment failed, nothing retried it, so a Swish payment whose buyer didn't come back to the shop was cancelled although the customer was charged. Fixed by the maintainers the same day, released in 2.14.9. #367
Work
-
Callback delivery audit
5–7 days · $2,500–4,000Read-only: your logs, exports and database. Nothing is written and nothing is deployed. You get a document: where callbacks are lost, what to fix now, what can wait, and where the same thing will break again in six months.
-
Discrepancy forensics
1–2 weeks · $3,000–6,000When the money doesn't add up between the provider, your ledger and the bank. The cause, confirmed on your data rather than argued from the code, and a read-only check you keep running afterwards. The check is open: payout-bridge.
-
Payment provider integration
2–4 weeks · $6,000–12,000A new provider in production: webhook signatures per its docs, a status mapping that covers every combination it sends, a second path to the final status besides the callback, tests on real samples, and a runbook.
-
Incident retainer
$2,000–4,000 a monthA set number of hours each month for stuck payments, queues and the database under payment load.
Diagnostics are fixed-price, 50% upfront. The first stage needs read-only access only.
How an audit starts
- You describe the symptom and send the id of one stuck payment. I reply with which of the seven places it usually is, and what I would need to read.
- You export what you can: payments and their status history, inbound webhook logs, delivery attempts. callback-audit runs the first pass on those files, on your side if you prefer.
- Within a week: the document, and a walk-through of it.
Public work
callback-audit is a read-only tool that runs the checks that can be run from exports and tells you which place to look at next. MIT-licensed.
payout-bridge walks from your ledger to the provider's report (Stripe, Adyen) to the bank statement and names every difference: payments still pending on your side, refunds and disputes your books never saw, double charges, fees above the contract, payouts that arrived short or not at all. Read-only, MIT-licensed.
AI integration. The same discipline, applied to model APIs. Six models on one contract-extraction task: accuracy a tie, cost 35× apart, most errors from the labels — extraction-bench. More on the AI integration page.
Contact
Email: hello@terminalstate.dev. A symptom and one payment id are enough to start.