---
name: payments-that-balance
description: "Applies “Payments that balance” as a repeatable product-quality gate. Use during backend work when integer money, idempotent webhooks, a ledger that reconciles to the cent."
---

# Payments that balance

Apply this skill during **Backend** work. It supports Node / API, Python, Any stack.

Integer money, idempotent webhooks, a ledger that reconciles to the cent.

## Instructions

Treat payments as a ledger problem, not an API call. Represent money as integer minor units with an explicit currency; floats never touch payment math. Process provider webhooks defensively: verify signatures, deduplicate by event id, and design handlers to be idempotent and correct even when events arrive out of order or twice. Record every state transition (created → paid → refunded → disputed) in an append-style trail you can audit per order. Reconcile on a schedule: totals in the provider dashboard must equal totals in your database, and drift raises an alert, not a shrug. Before launch, walk the full matrix in test mode: success, decline, refund, partial refund, dispute, and duplicate delivery. Never mark anything paid from a client-side callback — only from a verified server-side event.

## Detect the problem

- Money stored as floats
- Marking paid from the client-side callback
- No answer to 'what if the webhook fires twice?'

## Hold the gate

Do not declare this phase complete until every item passes:

- [ ] Money is integer minor units + currency everywhere — floats never touch payments
- [ ] Webhooks: signature-verified, idempotent by event id, safe out of order
- [ ] Every money state transition is recorded — an auditable trail per order/subscription
- [ ] Reconciliation runs on a schedule: provider totals match database totals, drift alerts
- [ ] Test mode covers success, decline, refund, dispute, and duplicate webhook delivery

## Verify the result

Replay the same webhook event twice in test mode — exactly one state change, and the ledger still balances.
