Build a Payment Management System
Asked at:
Airbnb
DESCRIPTION
Build a payment management system that processes transactions with priority ordering (credit > credit card > PayPal) and generates refunds intelligently. For each payment type, the system should only refund the most recent transaction (latest timestamp) until the target refund amount is satisfied. For example, if you have payment1: credit $100 at t=5 and payment2: credit $50 at t=10, and need to refund $120, the system should first refund from payment2 ($50), then from payment1 ($70).
Input:
Payments: - payment1: credit, $100, timestamp=5 - payment2: credit_card, $80, timestamp=3 - payment3: credit, $50, timestamp=10 Target refund: $120
Output:
Refunds: - refund1: payment3, $50 - refund2: payment1, $70 Total refunded: $120
Explanation: Credit has highest priority. Among credit payments, payment3 (t=10) is most recent, so refund $50 first. Then refund $70 from payment1 (t=5). Credit card payment is never touched since credit payments satisfied the target.
Constraints:
- Payment types have fixed priority: credit > credit_card > paypal
- Within each payment type, process refunds from latest to earliest timestamp
- Refund amounts cannot exceed the remaining balance of a payment
- Stop processing once the target refund amount is reached
Understanding the Problem
The core challenge is multi-level sorting: first by payment type priority, then by timestamp within each type. You need to track partial refunds since a payment might be only partially refunded to meet the exact target amount. The system must maintain payment state (original amount vs. remaining balance) as refunds are processed. Additionally, you need to link refunds back to their source payments for audit trails.
Building Intuition
A naive approach would iterate through all payments for each refund request, checking types and timestamps repeatedly—this becomes inefficient with many transactions. A better approach uses a priority queue or sorted structure to pre-organize payments by (priority, -timestamp), allowing you to always pop the next eligible payment in O(log n) time. For example, with payments [credit@t=5, paypal@t=10, credit@t=8], pre-sorting gives [credit@t=8, credit@t=5, paypal@t=10] for instant access.
Real-world payment systems handle millions of transactions with complex business rules (chargebacks, fraud detection, accounting reconciliation). This problem teaches priority-based resource allocation, which applies to inventory management (fulfill orders by customer tier), task scheduling (process high-priority jobs first), and financial systems (settle transactions by risk level). Understanding how to efficiently track and modify transaction state is crucial for building reliable financial software.
Common Pitfalls
Implementation
Payment Data Model and Priority System
Define the core data structures to represent payments with their type, amount, timestamp, and remaining balance. Implement a priority mapping (credit=1, credit_card=2, paypal=3) to enable sorting. Create a Payment class that tracks both original and remaining amounts, allowing partial refunds. For example, a payment with original=$100 and remaining=$100 becomes remaining=$30 after a $70 refund.
from dataclasses import dataclassfrom datetime import datetime@dataclassclass Payment:id: strtype: stramount: floattimestamp: datetimeremaining: float = Nonedef __post_init__(self):if self.remaining is None:self.remaining = self.amount@propertydef priority(self) -> int:priority_map = {'credit': 1, 'credit_card': 2, 'paypal': 3}return priority_map.get(self.type, 999)
Payment Sorting and Selection Logic
Build the sorting mechanism that organizes payments by priority first, then by timestamp (descending) within each priority level. Use a custom comparator or tuple-based sorting like (priority, -timestamp, payment_id). This creates a refund queue where the first element is always the next payment to process. For example, [(credit, t=10), (credit, t=5), (credit_card, t=8)] ensures credit payments are exhausted before touching credit cards.
from typing import Listdef sort_payments_for_refund(payments: List[Payment]) -> List[Payment]:"""Sort payments by priority, then by timestamp descending."""return sorted(payments,key=lambda p: (p.priority, -p.timestamp.timestamp(), p.id))def get_refund_queue(payments: List[Payment]) -> List[Payment]:"""Create refund queue with only latest payment per type."""latest_by_type = {}for payment in payments:if payment.type not in latest_by_type or payment.timestamp > latest_by_type[payment.type].timestamp:latest_by_type[payment.type] = paymentreturn sort_payments_for_refund(list(latest_by_type.values()))
Refund Processing Engine
Implement the refund generation algorithm that iterates through the sorted payment queue and allocates refunds. For each payment, calculate refund_amount = min(remaining_balance, remaining_target), create a refund record linking to the payment, and update both the payment's balance and the remaining target. Stop when remaining_target reaches zero. For example, if target=$120 and the first payment has $50, refund $50, update target to $70, and continue to the next payment.
@dataclassclass Refund:id: strpayment_id: stramount: floatdef generate_refunds(payments: List[Payment], target_amount: float) -> List[Refund]:"""Generate refunds from payment queue until target is met."""refund_queue = get_refund_queue(payments)refunds = []remaining_target = target_amountrefund_counter = 1for payment in refund_queue:if remaining_target <= 0:breakrefund_amount = min(payment.remaining, remaining_target)refunds.append(Refund(f"refund{refund_counter}", payment.id, refund_amount))payment.remaining -= refund_amountremaining_target -= refund_amountrefund_counter += 1return refunds
Complete Payment Management System
Integrate the Payment model, sorting logic, and refund engine into a unified PaymentManager class. Provide methods like add_payment() to register transactions and process_refunds(target_amount) to generate refund records. The manager maintains the payment collection, handles sorting on-demand or via a priority queue, and returns a list of Refund objects with payment references and amounts. For example, manager.process_refunds(150) returns [Refund(payment3, $50), Refund(payment1, $100)] showing the complete refund breakdown.
class PaymentManager:def __init__(self):self.payments = []def add_payment(self, payment: Payment) -> None:"""Register a new payment transaction."""self.payments.append(payment)def process_refunds(self, target_amount: float) -> List[Refund]:"""Generate refunds for the target amount using priority logic."""return generate_refunds(self.payments, target_amount)
What We've Learned
- Pattern: Use multi-level sorting (priority + timestamp) to create a deterministic processing order for complex business rules
- Use Case: Apply to resource allocation systems where items have both category priorities and time-based ordering (inventory fulfillment, task scheduling, financial settlements)
- Technique: Track mutable state (remaining balances) separately from immutable data (original amounts) to support partial operations and audit trails
- Optimization: Consider priority queues (heaps) for dynamic scenarios where payments are added continuously during refund processing
Problems to Practice
The payment management system requires processing transactions with priority ordering (credit, credit card, PayPal) and selecting items by timestamp. Heaps are ideal for priority-based processing and efficiently finding maximum/minimum elements, which directly applies to this problem's priority queue requirements.
hard
This problem involves managing multiple sorted streams (similar to multiple payment types) and efficiently selecting elements based on priority. The pattern of using a heap with hashmap tracking is directly applicable to managing refunds across different payment types with timestamp ordering.
Question Timeline
See when this question was last asked and where, including any notes left by other candidates.
Early July, 2025
Airbnb
Senior
Mid June, 2025
Airbnb
Senior
Early March, 2025
Airbnb
Senior
Build a payment management system to process transactions priority - Credit, credit card, paypal For each type, we need to only process refund for the latest timestamp payment1: credit : timestamp: amount payment2: credit : timestamp: amount refund1: linked to payment 1: amount refund2: linked to payment 2: amount target refund : amount generate refunds for the target amount
Comments
Hello Interview Premium
Your account is free and you can post anonymously if you choose.