Calculate transaction fees from CSV records
StripeSoftware Engineer · Technical ScreenLast updated
Implement a fee calculation engine that parses CSV transaction records, applies multi-attribute pricing rules and merchant volume discounts, and accurately rounds fee amounts in cents.
Problem Statement
Payment processors charge merchants transaction fees based on transaction characteristics, card brands, cross-border status, and merchant processing volume. You are tasked with implementing a fee calculation engine that processes an ordered list of CSV records.
Each input record is a comma-separated string with the following columns:
transaction_id,merchant_id,amount_cents,card_brand,merchant_country,card_country
Fee Rules
For each transaction, compute the total fee in cents according to the following logic:
- Base Percentage Fee:
- Domestic (
merchant_country == card_country):2.0% - Cross-Border (
merchant_country != card_country):3.0%
- Domestic (
- Card Brand Surcharge:
AMEX: add1.0%to the percentage fee.VISAandMASTERCARD: add0.0%.
- Volume Discount:
- If the merchant's cumulative processed volume (sum of
amount_centsof previously processed transactions in the current run) is at least1,000,000cents ($10,000), deduct0.5%from the percentage fee. - The discount applies to subsequent transactions, not the transaction that crossed the threshold.
- If the merchant's cumulative processed volume (sum of
- Fixed Fee:
- A flat fee of
30cents applies to every transaction.
- A flat fee of
- Calculation & Rounding:
percentage_fee = amount_cents * (effective_rate / 100.0)- Round
percentage_feeto the nearest integer cent using half-up rounding (i.e.,floor(percentage_fee + 0.5)). total_fee = rounded_percentage_fee + 30
Implement the function calculate_transaction_fees(records: list[str]) -> list[tuple[str, int]] returning a list of (transaction_id, fee_cents) in the same order as the input.
Interface
def calculate_transaction_fees(records: list[str]) -> list[tuple[str, int]]:
pass
Example
Input
records = [
"txn_1,m_1,10000,VISA,US,US",
"txn_2,m_1,5000,AMEX,US,CA",
"txn_3,m_2,20000,MASTERCARD,GB,GB"
]
Output
[
("txn_1", 230),
("txn_2", 230),
("txn_3", 430)
]
Explanation
txn_1: Domestic VISA. Rate =2.0%. Prior volume = 0. Fee =round(10000 * 0.02) + 30 = 200 + 30 = 230. Merchantm_1cumulative volume becomes10000.txn_2: Cross-border AMEX. Rate =3.0% + 1.0% = 4.0%. Prior volume =10000 < 1000000, so no discount. Fee =round(5000 * 0.04) + 30 = 200 + 30 = 230.txn_3: Domestic MC form_2. Rate =2.0%. Fee =round(20000 * 0.02) + 30 = 400 + 30 = 430.
Constraints
1 <= len(records) <= 100,0001 <= amount_cents <= 100,000,000($1,000,000.00)card_brandis one of{"VISA", "MASTERCARD", "AMEX"}.- All country codes are 2-letter uppercase ISO strings.
- Transaction IDs are unique.
- The input contains no header row.
Hints
Hint 1
Track running volume per merchant using a hash map before calculating each transaction's applicable rate, updating it only after the fee is computed.
Hint 2
Be careful to represent percentage rates accurately; working with basis points (1% = 100 bps) or standard floating-point numbers can avoid precision drift before the half-up rounding step.
Hint 3
Half-up rounding for non-negative numbers can be implemented as `int(math.floor(val + 0.5))` or using Python's `decimal` module with `ROUND_HALF_UP`.
Follow-up questions
- How would you refactor the fee rules to be easily configurable via external rule definitions (e.g., JSON or database) without modifying application code?
- How would your design change if transactions could arrive out of order and include an event timestamp?
- If transaction volume spans multiple months, how would you handle resetting merchant tiers at the start of each billing cycle?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.