FastPrepTransaction Fee Calculator — Volume-Based Discounts

Transaction Fee Calculator — Volume-Based Discounts

Stripe logoStripe● MediumFULLTIMENEW GRADPHONE SCREEN
Learn

Problem statement

Related parts: Start with Parts 1 and 2.

Part 3: Volume-Based Discounts

Adding Discounts

Now we add volume discounts. Merchants who sell more get cheaper fees. You need to count how many successful transactions a merchant has made.

Discount Table:

Total Transactions so farDiscount
1-100% (Normal price)
11-5010% off
51-10015% off
101+20% off

Configuration Data:

You will get a dictionary with fees for many countries. It looks like this:

country_fees = {
    "ie": {"card": (0.019, 20), "klarna": (0.025, 40), "bank_transfer": (0.006, 0)},
    "de": {"card": (0.025, 25), "klarna": (0.030, 45), "bank_transfer": (0.007, 0)},
    "fr": {"card": (0.027, 28), "klarna": (0.032, 48), "bank_transfer": (0.008, 0)},
    "default": {"card": (0.029, 30), "klarna": (0.035, 50), "bank_transfer": (0.008, 0)}
}

Example Data

Input:

Imagine acct_1 has done 10 transactions already. The 11th transaction (py_11) happens. The 12th transaction (py_12) happens.

Output:

  • Transaction 11: Base fee is calculated. Then, apply a 10% discount.
  • Transaction 12: Base fee is calculated. Apply a 10% discount.

Math Detail: For py_11 (Ireland Card): Base = 1500 × 0.019 + 20 = 48.5. Discount = 10%. New Fee = 48.5 × 0.9 = 43.65. Round down -> 43.

What You Need To Do

  • Keep a count of transactions for every merchant.
  • Check the merchant's count before the current transaction to find the discount.
  • Only increase the count if the transaction is "payment_completed".
  • Process rows in order. The order in the CSV matters.
  • Use the provided dictionary for country fees. If the country isn't there, use "default".

Questions to Ask the Interviewer

  • Do I apply the discount before rounding or after?
  • What if a merchant sells in different countries? Does that count towards the same volume total?
  • Does the volume count ever reset (like every month)?

Function

calculateDiscountedFees(csvData: String, countryFees: String[][]) → String[]

Examples

Example 1

csvData = "id,reference,amount,currency,date,merchant_id,buyer_country,transaction_type,payment_provider,status\npy_1,1,1000,eur,2024-12-24,acct_1,ie,payment,card,payment_completed\npy_2,2,2500,eur,2024-12-24,acct_2,de,payment,card,payment_failed\npy_3,3,3400,eur,2024-12-25,acct_2,ie,payment,klarna,payment_completed\npy_4,4,5000,eur,2024-12-25,acct_1,fr,payment,bank_transfer,payment_completed\npy_5,5,2000,eur,2024-12-26,acct_1,ie,payment,card,payment_pending"countryFees = [["ie","card","190","20"],["ie","klarna","250","40"],["ie","bank_transfer","60","0"],["de","card","250","25"],["de","klarna","300","45"],["de","bank_transfer","70","0"],["fr","card","270","28"],["fr","klarna","320","48"],["fr","bank_transfer","80","0"],["default","card","290","30"],["default","klarna","350","50"],["default","bank_transfer","80","0"]]return = ["id,transaction_type,payment_provider,fee","py_1,payment,card,39","py_2,payment,card,0","py_3,payment,klarna,125","py_4,payment,bank_transfer,40","py_5,payment,card,0"]

The two unsuccessful rows have fee 0 and do not affect volume. The remaining payments use their Ireland or France rules. No merchant reaches its eleventh successful payment, so no discount applies.

Example 2

csvData = "id,reference,amount,currency,date,merchant_id,buyer_country,transaction_type,payment_provider,status\nt1,1,1000,usd,2025-01-01,m1,us,payment,card,payment_completed\nt2,2,1000,usd,2025-01-01,m1,us,payment,card,payment_completed\nt3,3,1000,usd,2025-01-01,m1,us,payment,card,payment_completed\nt4,4,1000,usd,2025-01-01,m1,us,payment,card,payment_completed\nt5,5,1000,usd,2025-01-01,m1,us,payment,card,payment_completed\nt6,6,1000,usd,2025-01-01,m1,us,payment,card,payment_completed\nt7,7,1000,usd,2025-01-01,m1,us,payment,card,payment_completed\nt8,8,1000,usd,2025-01-01,m1,us,payment,card,payment_completed\nt9,9,1000,usd,2025-01-01,m1,us,payment,card,payment_completed\nt10,10,1000,usd,2025-01-01,m1,us,payment,card,payment_completed\nt11,11,1000,usd,2025-01-01,m1,ie,payment,card,payment_completed"countryFees = [["ie","card","190","20"],["default","card","290","30"],["default","klarna","350","50"],["default","bank_transfer","80","0"]]return = ["id,transaction_type,payment_provider,fee","t1,payment,card,59","t2,payment,card,59","t3,payment,card,59","t4,payment,card,59","t5,payment,card,59","t6,payment,card,59","t7,payment,card,59","t8,payment,card,59","t9,payment,card,59","t10,payment,card,59","t11,payment,card,35"]

The first ten successful payments use the undiscounted default card fee of 59. The Ireland payment is merchant m1's eleventh success, so its base fee 39 receives a 10% discount and floors to 35.

Constraints

  • Process transactions in CSV order.
  • Only payment_completed transactions increase a merchant's count.
  • Use the merchant's transaction number including the current successful payment to select the discount tier.
  • Apply the discount before rounding down.
  • If a country is not present, use default.
  • FastPrep adapter: each countryFees row is [country, provider, rateBasisPoints, fixedFee]; for example, 190 basis points represents the source rate 0.019.
  • FastPrep adapter: return the source's newline-delimited CSV result as a String[], one CSV line per array element.

More Stripe problems

See Stripe hiring insights
public String[] calculateDiscountedFees(String csvData, String[][] countryFees) {
    // Write your code here
}
csvData"id,reference,amount,currency,date,merchant_id,buyer_country,transaction_type,payment_provider,status\npy_1,1,1000,eur,2024-12-24,acct_1,ie,payment,card,payment_completed\npy_2,2,2500,eur,2024-12-24,acct_2,de,payment,card,payment_failed\npy_3,3,3400,eur,2024-12-25,acct_2,ie,payment,klarna,payment_completed\npy_4,4,5000,eur,2024-12-25,acct_1,fr,payment,bank_transfer,payment_completed\npy_5,5,2000,eur,2024-12-26,acct_1,ie,payment,card,payment_pending"
countryFees[["ie","card","190","20"],["ie","klarna","250","40"],["ie","bank_transfer","60","0"],["de","card","250","25"],["de","klarna","300","45"],["de","bank_transfer","70","0"],["fr","card","270","28"],["fr","klarna","320","48"],["fr","bank_transfer","80","0"],["default","card","290","30"],["default","klarna","350","50"],["default","bank_transfer","80","0"]]
expected["id,transaction_type,payment_provider,fee", "py_1,payment,card,39", "py_2,payment,card,0", "py_3,payment,klarna,125", "py_4,payment,bank_transfer,40", "py_5,payment,card,0"]
Checking account…