feat(payments): refund engine (best-effort revoke, never negative) #227
Reference in New Issue
Block a user
Delete Branch "feature/payment-intake-refunds"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The last E5 slice — refunds. Closes E5 (all four money pieces: Robokassa, VK, Telegram Stars, refunds).
One
Refundengine (internal/payments) reverses a paid order best-effort, exactly once:(provider, provider_refund_id)— the refund id is distinct from the fund's payment id, so both rows coexist under the existing partial-unique index;balances_chips_chk);payments.account_risktable (read by the E7 report);paid.No webhooks/worker. No rail pushes an unsolicited refund — all admin-triggered (E7): Robokassa refund API / cabinet (auto-polling deferred — a worker not worth it at low chargeback volume), VK via support, Telegram
refundStarPayment.failedevents not wired (no rail signals a hard post-charge server decline).Migration 00012 is additive (a new table only) → applies via goose incrementally, rollback-safe, no contour wipe.
Tests: integration (full revoke; revoke-after-spend = floor-0 + loss + abuse; duplicate idempotent; unpaid-order guard). Local: all modules build+vet+gofmt, backend unit, full payments integration suite green. Docs: PAYMENTS(+ru) §9, PLAN (E5 -> DONE).