I converted the screenshot version into text, including some test cases, to help everyone prepare!
Split Tender
Many of Stripe's merchants rely on Stripe Terminal to accept in-person payments at the point of sale. In physical retail, it's common for a customer to cover a purchase with multiple payment methods. For example, they might cover a $100 purchase with a $40 gift card combined with a $60 credit card. This is called a split-tender transaction, and supporting it is a key requirement for retail merchants on Terminal.
For this multi-part question, we will be writing a system to process split-tender payments. When a transaction occurs, the system first deducts from the customer's available gift card balance, then charges the remaining balance to the customer's credit card. Given a chronological stream of payment events, your task is to calculate the correct credit card charge for each transaction. The question is broken down into four parts, each introducing a new event type: gift card expiration, regional credit card surcharges, and complex refund logic.
Function Description
Complete the function process_events in the editor below.
Function Parameters
string events[n]: Lines for each event in chronological order. Lines have a format defined by one of three schemas:
timestamp,ADD_GIFTCARD,customer_id,card_id,amount,valid_before
timestamp,CHARGE,charge_id,customer_id,amount,zip_code
timestamp,REFUND,charge_id,refund_amount
string surcharge_rates[m]: A list of non-overlapping ZIP code ranges mapped to a surcharge percentage in the format start_zip-end_zip:rate, where start and end are inclusive.
Example: 90000-99999:0.05 (representing 5%).
General Constraints and Assumptions
- Events are in chronological order by timestamp.
- All event lines are well-formed.
charge_idvalues are unique acrossCHARGEevents.REFUNDevents always reference a priorCHARGEevent.- Each
charge_idwill receive at most oneREFUNDevent. card_idvalues fromADD_GIFTCARDevents are unique.surcharge_ratescontains non-overlapping, valid ZIP code ranges.zip_codevalues are five-digit numeric strings.
Monetary Representation and Precision
- All monetary amounts in the input and output are represented as non-negative integer numbers of cents. For example, $40.00 is represented as
4000. - Surcharge rates are decimal fractions; for example,
0.05represents 5%. - Each surcharge calculation results in a whole number. You don't need to round.
Returns
string[n]: An array of strings, one per input event, in the same order.
For CHARGE events, return the formatted charge string using the schema:
CC_CHARGE_AMOUNT,GIFT_CARD_ID_1:AMOUNT_USED,GIFT_CARD_ID_2:AMOUNT_USED
For all other event types, return an empty string "" unless a later part specifies otherwise.
The length of the output array must exactly match the length of the input events array.
Part 1: Basic Split Tendering
For Part 1, process ADD_GIFTCARD and CHARGE events. All customer balances start at 0.
When an ADD_GIFTCARD event is received, add the specified amount to the designated customer's total gift card balance. Return an empty string "".
When a CHARGE event is received, attempt to cover the transaction cost using the customer's available gift card balance first.
- If the gift card balance is greater than or equal to the charge amount, deduct the charge amount from their gift card balance. The credit card charge is 0.
- If the charge amount exceeds the gift card balance, drain the entire gift card balance to 0. The remaining unpaid amount becomes the credit card charge.
Output Format for CHARGE: Return a string starting with the credit card charge, followed by a comma-separated list of the gift cards debited and their amounts (CARD_ID:AMOUNT). If no gift cards were debited, output only the credit card charge.
CC_CHARGE_AMOUNT,GIFT_CARD_ID_1:AMOUNT_USED,GIFT_CARD_ID_2:AMOUNT_USED
Note: In Part 1, each customer will hold at most one active gift card at a time. You do not need to implement card prioritization or sorting logic until Part 2.
Example Input
Suppose we receive the following events in order:
events = [
"1,ADD_GIFTCARD,cust1,gc1,5000,10", # cust1 gift card gc1 with 5000 cents ($50.00), expiration: t=10
"2,ADD_GIFTCARD,cust2,gc2,2000,15",
"3,CHARGE,chg1,cust2,3000,10000", # cust2 is charged 3000
"4,CHARGE,chg2,cust1,3000,10000"
]
Example Output
[
"", # ADD_GIFTCARD always returns an empty string
"",
"1000,gc2:2000", # gc2 drained for 2000, remaining 1000 goes to the credit card
"0,gc1:3000" # gc1 covers the full 3000, so the credit card charge is 0
]
Part 2: Expiration Dates
All constraints from Part 1 still apply. In this part, each gift card has its own individual balance, and a customer may hold multiple gift cards simultaneously, tracked by card_id. Additionally, gift cards have expiration dates: they must be used before their valid_before time.
When a CHARGE event occurs at time T, evaluate the customer's available gift cards:
- A gift card is valid only if
Tis strictly less than itsvalid_beforevalue. IfTis at or aftervalid_before, the gift card is expired and its balance permanently voided. - The system must charge valid gift cards by the earliest expiration date first. Completely drain one gift card before moving to the next.
- Gift cards with no expiration date are considered valid forever and should be used after all valid gift cards with finite expiration timestamps.
- If multiple gift cards share the exact same expiration timestamp, prioritize the card whose
card_idappears first lexicographically.
Output Format for CHARGE: Identical to Part 1. Gift cards must be debited according to the priority rules above. Now that multiple gift cards can be consumed in a single charge, cards must be sorted lexicographically by card_id in the final output string to ensure deterministic matching.
Example Input
events = [
"1,ADD_GIFTCARD,cust1,gc1,5000,10",
"2,ADD_GIFTCARD,cust1,gc2,4000,5",
"3,CHARGE,chg1,cust1,6000,10000",
"11,CHARGE,chg2,cust1,1000,10000"
]
Example Output
[
"",
"",
"0,gc1:2000,gc2:4000", # cards sorted lexicographically
"1000"
]
Part 3: Surcharges
All constraints from previous parts still apply. Credit card transactions are now subject to regional processing fees using the zip_code and surcharge_rates.
When a CHARGE event occurs, first split the raw charge amount between gift cards and credit card exactly as before. However, our system must now apply a surcharge on the final CC_CHARGE amount according to the following rules:
- Identify which range in
surcharge_ratesthe event'szip_codefalls into. If it does not fall into any range, the rate is 0. - Calculate the surcharge strictly on the portion of the bill falling to the credit card. Gift card deductions are not subject to surcharges.
- The surcharge is calculated as
credit_card_portion × rate, then added to the originalcredit_card_portionto arrive at the finalCC_CHARGE. For example, a $100 credit card portion at a 5% surcharge (0.05) yields a finalCC_CHARGEof $105.00.
Output Format for CHARGE: Identical to Part 1 and Part 2, but the CC_CHARGE value must reflect the newly calculated total including the surcharge.
Example Input
events = [
"1,ADD_GIFTCARD,cust1,gc1,5000,10",
"2,CHARGE,chg1,cust1,15000,90210"
]
surcharge_rates = [
"80000-89999:0.02",
"90000-99999:0.05"
]
Example Output
[
"",
"10500,gc1:5000"
]
Part 4: Refunds
All constraints from previous parts still apply. You must now handle REFUND events targeting a historical charge_id.
A REFUND event has the following format:
timestamp,REFUND,charge_id,refund_amount
The refund amount represents the total amount to return to the customer, including any refundable credit card surcharge. Refund amounts are guaranteed not to exceed the total amount originally paid for the referenced charge, including surcharge. Each charge_id will receive at most one REFUND event.
When a refund occurs, route the money back to the customer in the following priority:
- Real dollars: Refund back to the credit card first, up to the amount that was actually charged to the credit card for the referenced
charge_id, including surcharge. - Store credit second: If
refund_amountexceeds the amount refundable to the credit card, refund the remaining amount as store credit by creating a new gift card for the original customer. The newcard_idmust be formatted asREFUND_{charge_id}. This gift card has no expiration date.
Refund-created gift cards participate in future CHARGE events like any other gift card. Refund-created gift cards never expire. When choosing gift cards for a future charge, non-expiring gift cards are used after all valid gift cards with finite expiration timestamps.
Output Format for REFUND: Return a flat string containing the amount refunded to the credit card and the amount refunded to the store credit gift card, separated by a single comma:
CC_REFUND,GC_REFUND
Example Input
events = [
"1,ADD_GIFTCARD,cust1,gc1,5000,10",
"2,CHARGE,chg1,cust1,15000,90210",
"3,REFUND,chg1,12000"
]
surcharge_rates = [
"90000-99999:0.05"
]
Example Output
[
"",
"10500,gc1:5000",
"10500,1500" # CC_REFUND, GC_REFUND
]
Appendix: Additional Test Cases
The following test cases were shown in subsequent debugging screenshots. These are separate from the original problem's four example sections.
Test Case 13
Input:
events = [
"1,ADD_GIFTCARD,cust_1,gc_1,5000,10",
"2,CHARGE,chg_1,cust_1,15000,90210",
"3,REFUND,chg_1,12000"
]
surcharge_rates = ["90000-99999:0.05"]
Expected output:
["", "10500,gc_1:5000", "10500,1500"]
Test Case 16
Input:
events = [
"1,ADD_GIFTCARD,cust_1,gc_1,10000,10",
"2,CHARGE,chg_1,cust_1,20000,15000",
"3,REFUND,chg_1,21000",
"15,CHARGE,chg_2,cust_1,5000,15000",
"16,ADD_GIFTCARD,cust_1,gc_2,3000,20",
"17,CHARGE,chg_3,cust_1,9000,15000"
]
surcharge_rates = ["10000-20000:0.10"]
Expected output:
[
"",
"11000,gc_1:10000",
"11000,10000",
"0,REFUND_chg_1:5000",
"",
"1100,REFUND_chg_1:5000,gc_2:3000"
]
Discussion
Loading comments…