feat(payments): direct-rail order + intake handlers, config and reaper
Wire the Robokassa direct rail into the backend transport. POST /api/v1/user/wallet/order (walletGate + a D36 confirmed-email gate for the direct rail) opens a pending order and returns the signed Robokassa payment URL. The internal, gateway-only /payments/robokassa/result endpoint verifies the Result signature, credits the matched order exactly once via Fund (honoured even if expired), records a succeeded payment event, and answers Robokassa's "OK<InvId>". Add the Robokassa env config, an account HasConfirmedEmail check (D36), the payment_events writer, and a periodic pending-order reaper. The routes register only when a Robokassa merchant login is configured.
This commit is contained in:
@@ -71,3 +71,9 @@ func (s *Service) ExpireOrders(ctx context.Context) (int, error) {
|
||||
}
|
||||
return s.store.expirePending(ctx, ttl, s.clock())
|
||||
}
|
||||
|
||||
// RecordPaymentEvent appends a payment lifecycle event (succeeded/failed/refunded) for the
|
||||
// dispatcher to deliver to the user (live stream, botlink or email).
|
||||
func (s *Service) RecordPaymentEvent(ctx context.Context, accountID uuid.UUID, orderID *uuid.UUID, eventType string, payload []byte) error {
|
||||
return s.store.insertPaymentEvent(ctx, accountID, orderID, eventType, payload, s.clock())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user