FastPrepAsynchronous Payment Event Processing
Problem · Hash Table

Asynchronous Payment Event Processing

Learn this problem
MediumStripe logoStripeNEW GRADINTERNOA
See Stripe hiring insights

Problem statement

Stripe processes asynchronous payment events. Build a small-scale processor that receives events, parses them, and aggregates the latest state and totals for every payment.

Complete processEvents. The events array is given in received order. Each event is a comma-separated string with these seven fields:

event_id,event_time,event_type,payment_id,payment_event_type,merchant_id,amount

A missing field is written as -. This Part 1 exercise contains only payment events and the following payment event types:

  • create: the payment does not exist yet. Create it for the supplied merchant_id, initialize both accumulated amounts to 0, and set its state to created. The amount field is -.
  • authorize: the payment is currently created or authorized. Add amount to amount_authorized and set the state to authorized. The merchant_id field is -.
  • capture: the payment is currently authorized or partially_captured. Add amount to amount_captured. The merchant_id field is -.

After a capture, the payment is partially_captured when amount_captured < amount_authorized, and it is successful when the two amounts are equal.

Event IDs are globally idempotent. Process only the first received event with a given event_id; ignore every later row with that ID without changing any payment or timestamp.

For every accepted event, set the payment's last_event_at to that event's event_time. A payment is attached to exactly one merchant.

Output

Return one string per payment, in the order that each payment's accepted create event was processed. Use this exact field order:

payment_id,merchant_id,state,amount_authorized,amount_captured,last_event_at

Numeric totals start at 0. Output missing text fields as an empty field rather than -.

Function

processEvents(events: String[]) → String[]

Examples

Example 1

events = ["evt1,10,payment,p1,create,m1,-","evt2,20,payment,p1,authorize,-,100","evt3,30,payment,p1,capture,-,40","evt4,40,payment,p1,capture,-,60"]return = ["p1,m1,successful,100,100,40"]

The payment moves from created to authorized, then to partially_captured, and finally to successful. Its latest accepted event time is 40.

Example 2

events = ["c1,1,payment,pA,create,shopA,-","a1,2,payment,pA,authorize,-,80","c2,3,payment,pB,create,shopB,-","a1,4,payment,pA,authorize,-,80","a2,5,payment,pA,authorize,-,20","b1,6,payment,pB,authorize,-,50"]return = ["pA,shopA,authorized,100,0,5","pB,shopB,authorized,50,0,6"]

The second row with event ID a1 is ignored globally, so it does not add another 80 or change the last event time. Results follow payment creation order.

Example 3

events = ["e1,7,payment,p1,create,m1,-","e2,8,payment,p2,create,m2,-","e3,9,payment,p2,authorize,-,120","e4,10,payment,p2,capture,-,20"]return = ["p1,m1,created,0,0,7","p2,m2,partially_captured,120,20,10"]

Payment p1 has only a creation event, so both numeric totals remain 0. Payment p2 has captured less than its authorized amount.

Constraints

  • 1 <= events.length <= 10^5.
  • Every event contains exactly seven comma-separated fields, and no field contains a comma.
  • Every non-missing identifier is non-empty and contains only letters, digits, underscores, or hyphens.
  • 0 <= event_time <= 10^9.
  • Every authorize or capture amount is in [1, 10^9], and every accumulated amount fits in a signed 64-bit integer.
  • Except for repeated event IDs, events follow the valid transition table in received order, and a capture never makes amount_captured exceed amount_authorized.

More Stripe problems

drafts saved locally
public String[] processEvents(String[] events) {
    // Write your code here.
}
events["evt1,10,payment,p1,create,m1,-","evt2,20,payment,p1,authorize,-,100","evt3,30,payment,p1,capture,-,40","evt4,40,payment,p1,capture,-,60"]
expected["p1,m1,successful,100,100,40"]
checking account