feat(payments): Robokassa direct-rail payment intake #223
Reference in New Issue
Block a user
Delete Branch "feature/payment-intake-robokassa"
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?
What
The direct-rail (Robokassa) payment intake, end-to-end: a chip-pack purchase opens a money
order, sends the player to Robokassa's hosted-payment page, and a verified server callback credits
the chips exactly once.
Pieces: the public offer page (
/offer/); the provider-agnostic order/fundengine (idempotenton the ledger
(provider, provider_payment_id)unique index, honours an expired order); theinternal/robokassaadapter (SHA-256 sign/verify);POST /wallet/order+ the internal Resultcallback handlers (a D36 confirmed-email gate on the
directrail); the pending-order reaper;the
wallet.orderedge wire (FBS + Connect op) + the public/pay/*gateway routes; the Walletpurchase CTA replacing "Soon" (+ a public-offer link); and the contour deploy env.
Baked decisions
Shp_ordercustom parameter, not the numericInvId(an orderid is a uuid); idempotency key = the order id.
Receiptparameter is sent.balances_chips_chkkept) → E5 isschema-free (no migration, no contour wipe).
Tests
Unit: the credit gate, the Robokassa sign/verify (round-trip, tamper, wrong password), the order
codec. Integration (Postgres): order→callback→credit once, a duplicate callback credits nothing, an
amount mismatch is refused, an expired order is still honoured. Mock e2e: the pack purchase opens
the provider page. CI probes:
/pay/robokassa/resultreaches the gateway,/offer/serves the page.Review on the contour
Wallet → a chip pack → Купить should open the Robokassa sandbox page (IsTest is forced on the
contour, so it can never take real money). A sandbox payment credits the chips.
Owner setup
The
TEST_BACKEND_ROBOKASSA_*secrets are set. The Robokassa test shop needs its Result/Success/Fail URLs at the contour's public base (
/pay/robokassa/{result,success,fail}), SHA256 + POST.Note:
TEST_BACKEND_ROBOKASSA_TESTis unused — the contour forces IsTest itself.Remaining (follow-ups, this stack)
The
payment_eventsdispatcher (the succeeded notification); then the VK and TG-Stars rails andrefunds.
Add the public /pay/robokassa/result callback proxy (rate-limited; forwards the provider's form parameters to the backend intake, the single writer, and echoes its "OK<InvId>" back to Robokassa) and the /pay/robokassa/{success,fail} browser-return redirects into the app. Route /pay/* to the gateway in the contour Caddyfile so the callback reaches the edge, not the landing catch-all. The backend intake now returns the echo body as JSON for the gateway to relay.