← 返回博客列表 Stripe VO 真实 Coding 复盘:交易费用计算两题递进,考的是工程建模不是刷题
Stripe

Stripe VO 真实 Coding 复盘:交易费用计算两题递进,考的是工程建模不是刷题

2026-06-09

这轮 Stripe VO 整体给我的感觉很明确:更偏真实业务建模,而不是算法刷题。开场流程非常干脆,简单自我介绍后,两位面试官直接进入 coding 环节,全程围绕「交易系统中的费用计算」展开,一共两道题,逻辑逐步递进。我对接了 oavoservice 团队协助完成这轮 technical interview,下面把题目与解题节奏完整还原出来。

一、整体节奏:先 clarify,再动手

Stripe Coding 的一个鲜明特点是:写代码之前的澄清比代码本身更重要。两道题都是先抛业务背景,让你自己问清楚规则边界,再开始实现。如果上来就闷头写,很容易写出「能跑但不像生产代码」的东西。

阶段 重点
Clarify 不同交易类型 / 状态是否计费?边界规则是什么?
建模 解析、交易模型、费用计算、输出结果四层解耦
实现 避免把业务逻辑写死,方便扩展和测试
Followup 新增交易类型 / 费率调整时改动是否可控

二、Part 1:解析交易 CSV,计算每个用户费用

第一题给一个交易记录的 CSV 字符串,要求解析后计算每笔交易中每个用户需要支付的费用。题目表面像字符串解析,但真正写代码前,面试官先抛了几个关键澄清问题:

规则确认清楚后,这题的重点就很明确了:不在 CSV parsing 本身,而在你能否在不把业务逻辑写死的前提下,把费用规则表达清楚。

我的做法是刻意避免把所有逻辑堆在一个函数里,而是先把职责拆开:

from dataclasses import dataclass
from typing import List, Dict

@dataclass
class Transaction:
    """交易模型:只描述基础信息,不掺杂费用逻辑"""
    user_id: str
    amount: int          # 以最小货币单位存储,避免浮点误差
    status: str          # completed / pending / refunded
    method: str
    country: str

def parse_transactions(csv_text: str) -> List[Transaction]:
    """解析层:只负责把原始字符串转成结构化对象"""
    txns = []
    for line in csv_text.strip().splitlines():
        uid, amount, status, method, country = line.split(",")
        txns.append(Transaction(uid, int(amount), status, method, country))
    return txns

费用计算逻辑单独封装,根据交易类型和状态应用对应规则:

def fee_for(txn: Transaction) -> int:
    """费用层:规则集中在这里,解析逻辑不污染业务逻辑"""
    if txn.status != "completed":     # pending / refunded 不计费
        return 0
    if txn.method == "refund":
        return 0
    # 基础规则:2.9% + 固定 30(最小货币单位)
    return round(txn.amount * 0.029) + 30

def total_fee_per_user(csv_text: str) -> Dict[str, int]:
    result: Dict[str, int] = {}
    for txn in parse_transactions(csv_text):
        result[txn.user_id] = result.get(txn.user_id, 0) + fee_for(txn)
    return result

这样拆分的好处很直接:解析逻辑和业务规则不会互相污染,未来新增交易类型或费用规则,只需改动对应模块,不会牵一发而动全身。

面试官的 followup 几乎都围绕工程可维护性:

这些问题本质上不是在考「能不能写出来」,而是在看你是不是习惯用工程化方式思考

三、Part 2:基于国家与支付方式的动态费率

第二题在第一题基础上深化,只对 completed 的交易做进一步处理,并引入国家支付提供商两个新变量。不同国家、不同支付方式对应不同费率结构,要算出最终实际费用。

这里我选择用 查找表(Lookup Table) 处理费率,而不是堆一堆 if-else:

# (payment_provider, buyer_country) -> (variable_rate, fixed_fee)
RATE_TABLE = {
    ("visa", "US"):  (0.029, 30),
    ("visa", "DE"):  (0.014, 25),
    ("visa", "FR"):  (0.014, 25),
    ("visa", "AT"):  (0.014, 25),   # 同费率国家也分别列出,保持实现简单可读
    ("paypal", "US"): (0.034, 49),
}
DEFAULT_RATE = (0.039, 30)          # 兜底费率

def dynamic_fee(txn: Transaction) -> int:
    if txn.status != "payment_completed":
        return 0
    rate, fixed = RATE_TABLE.get((txn.method, txn.country), DEFAULT_RATE)
    return round(txn.amount * rate) + fixed

这个设计的优势很明显:

对于德国、法国、奥地利这类费率相同的国家,我也选择在查找表里分别列出,而不是额外做国家分组抽象——保持实现简单、可读,这正是 Stripe 想看到的取舍。

四、面试整体评价

整体来看,这轮 Stripe VO 不难在算法本身,而是考你是否具备把业务问题工程化的能力。面试官更关注:

如果平时更习惯用 LeetCode 模板思路解题,很容易在这种题里显得「能写出来,但不太像实际工程代码」。

五、总结

Stripe Coding 的评分锚点是工程化实现质量:先 clarify 再动手、按职责分层、用数据(查找表)代替硬编码分支、随时回应扩展性 followup。把这套思维练成肌肉记忆,比多刷几十道 hard 更管用。


FAQ

Q1:Stripe VO 的 Coding 到底考什么?

考真实业务建模而非算法技巧。本轮两题都围绕「交易费用计算」递进:Part 1 解析 CSV 算每个用户费用,Part 2 引入国家 / 支付方式做动态费率。重点是分层解耦与扩展性。

Q2:为什么用 Lookup Table 而不是 if-else?

费率规则随国家 × 支付方式组合膨胀,if-else 会越堆越乱。查找表把规则集中成数据,新增组合只改一行表,主流程不动,可读性和可测试性都更好。

Q3:面试官的 followup 一般问什么?

几乎都围绕工程可维护性:新增交易状态怎么办、费率调整要不要重构、如何保证可测试。答题时强调「分层 + 纯函数 + 规则即数据」即可对上他们的评分点。

Q4:怎么准备 Stripe Coding?

把「先 clarify 再动手」练成习惯,刻意训练分层(解析 / 模型 / 规则 / 输出)写法,并对每个设计点准备好扩展性回答。如果想要这两道真题的限时陪练,或需要 VO代面 / VO辅助 的实时对接,可以发岗位 JD 先做题型预测再排练习计划。


正在准备 Stripe 面试?

Stripe VO Coding 考的是工程建模 + 分层解耦 + 扩展性思维,不是刷题量。oavoservice 提供 Stripe 全流程陪练:交易费用建模、Lookup Table 取代 if-else 的取舍演练、followup 应答训练,也支持 VO代面 / VO辅助 的实时对接。教练含前大厂资深工程师,熟悉 Stripe「愿意 merge 的代码质量」评分风格。

立即添加微信 Coding0201获取 Stripe 真题与陪练

联系方式