Stripe 面试题:Webhook 事件去重与乱序处理,如何保证支付状态正确 – 面试辅助 – 代面试 – 一亩三分地

Stripe 的支付系统中,一个很常见的问题是:同一个事件可能被重复发送,不同事件也不一定按照产生顺序到达。

这道题算法并不复杂,但很适合考察候选人对幂等、状态更新和边界情况的处理。

You are building a simplified webhook processing system for payment events.

Each event contains:

event_id
payment_id
timestamp
status

Possible statuses are:

CREATED
PROCESSING
SUCCEEDED
FAILED

Implement a function that processes incoming webhook events and maintains the latest status of each payment.

Requirements:

  1. The same event_id may be delivered more than once. It should only be processed once.
  2. Events may arrive out of order.
  3. For each payment_id, only the event with the latest timestamp should determine its current status.

Return the final status of every payment after all events have been processed.

Example

Input:

e1,p1,100,CREATED
e2,p1,120,PROCESSING
e2,p1,120,PROCESSING
e3,p1,150,SUCCEEDED
e4,p1,130,FAILED

e5,p2,200,CREATED
e6,p2,240,SUCCEEDED

Output:

p1 -> SUCCEEDED
p2 -> SUCCEEDED

这道题其实只需要维护两类状态。

第一类是已经处理过的 event_id

可以使用一个 Set

processedEvents

每次收到事件时,先检查:

if event_id already exists:
    ignore

这样就解决了重复投递的问题。

第二类状态是每个 payment 当前最新的事件。

例如:

paymentState[payment_id] = {
    timestamp,
    status
}

收到新的事件之后,只需要比较 timestamp。

如果当前 payment 还没有任何记录,就直接保存。

如果新事件:

newTimestamp > currentTimestamp

再更新状态。

否则说明这是一个较旧的事件,即使它刚刚才到达,也应该忽略。

整个流程实际上就是:

去重
  ↓
找到 payment
  ↓
比较 timestamp
  ↓
决定是否更新状态

不需要复杂的数据结构。

容易踩坑的地方

最常见的问题是把“到达顺序”当成“事件发生顺序”。

例如:

SUCCEEDED timestamp=150
FAILED    timestamp=130

如果代码每收到一个 Webhook 就直接覆盖状态,最终就会错误地得到 FAILED

另一个容易忽略的问题是重复事件。

支付系统中的 Webhook 通常需要考虑 retry。如果同一个事件被执行两遍,而事件处理过程中还包含退款、发货或者余额修改,就可能产生更严重的问题。

所以这里的 event_id 去重,本质上是在考 Idempotency(幂等性)

Follow-up

What if two events for the same payment have the same timestamp?

这时候就不能单纯依赖 timestamp。

比较合理的做法是先向面试官确认系统是否提供额外的 sequence number。

例如:

event_id
payment_id
timestamp
sequence
status

然后比较:

(timestamp, sequence)

而不是自己随意假设两个事件的先后关系。

如果系统没有任何额外顺序信息,那么两个完全相同 timestamp 的事件之间可能本身就不存在可靠的先后关系,这一点应该明确说明。

这题真正想看的不是 HashMap 会不会写。

核心是候选人能不能意识到:

重复投递 != 重复执行
到达顺序 != 发生顺序

很多支付系统问题最后都会落到类似的工程细节上。

第一版需求可能只是保存 payment 状态,但一旦加入 retry、乱序或者并发,代码结构是否清晰就会变得非常重要。

如果输入一共有 n 个 Webhook Event,使用 HashSet 和 HashMap 后,平均时间复杂度可以做到:

O(n)

空间复杂度同样是:

O(n)

整体并不难,但非常适合 Stripe 这种偏实际业务场景的 Coding Interview。

csoahelp 面试辅助

Stripe 的面试题很多并不是传统 LeetCode 模板,而是从支付、商户、交易和数据处理场景逐步增加 requirement。

真正困难的地方往往不是代码量,而是现场能否快速判断:

这个条件应该修改现有逻辑,还是增加新的状态?

边界情况应该怎么处理?

面试官继续追问时,现有设计能不能自然扩展?

csoahelp 提供大厂技术面试实时文本辅助以及 Mock Interview 服务,覆盖 Stripe、Google、Meta、Amazon、TikTok、Microsoft 等公司。

面试过程中可以通过实时文本形式辅助理解题意、梳理解题方向、处理 Follow-up,并帮助组织复杂度和思路表达。

对于 Stripe 这类业务场景较强、需求会逐步变化的面试题,提前熟悉这种解题节奏通常比单纯刷大量算法题更有帮助。

我们也有代面试,面试辅助,OA代写等服务助您早日上岸~

Leave a Reply

Your email address will not be published. Required fields are marked *