Stripe SDE VO 面经|Integration 怎么考
Stripe Integration 面试全解析:从 GitHub 下载 repo、在 issue 里读题,高频题 Bikemap 分 GeoJSON 解析、HTTP POST 下载地图、staticmap 绘图、地标最近点查找等部分,附 Python 参考实现与准备建议。
Integration 面试是什么
Stripe 从 Intern 到 Senior,几乎都用同一套 integration 题库,区别只在于面试官的期望,以及你能走到第几步。面试通常一小时,形式和传统的 LeetCode 式面试完全不同:
- 你要从 GitHub 下载一个公开的 repository,用自己的 IDE 打开。
- 题目说明藏在 GitHub 的 issue 里,不能下载、不能复制,只能在浏览器和 IDE 之间来回切换。
这种设置是有意的:它模拟真实开发中在读代码、调试、查文档之间不断切换的场景,也能看出你在有限时间里的节奏掌控能力。
整场面试不考算法推导,考的完全是工程师的 integration 实战能力:
- 能否快速理解已有代码
- 能否在不破坏结构的前提下扩展功能
- 能否读懂文档、发起请求、解析数据
- debug 时能否保持思路清晰
题目一般分成五个部分,但几乎没人能写完。Stripe 很清楚时间紧张,更看重实现质量、代码整洁度,以及面对未知需求时的反应。每个 Part 都在向更贴近生产环境的方向推进。
高频题:Bikemap
背景是一个骑行路线可视化系统,需要逐步实现从数据解析到地图渲染的完整链路。
语言建议:题目支持多种语言,但过往经验显示 Python 能节省一半以上的时间。Java、C++ 写 JSON 解析和 HTTP 请求会非常冗长。
Part 1:JSON 解析与坐标提取
给定 ride-simple.json,格式是 GeoJSON,包含大约 500 个 GPS 点。要求解析文件,提取前十个坐标点,按格式输出到标准输出。
听起来简单,但面试官会看:
- 读取逻辑是否合理,比如文件路径是否可配置
- 是否用异常处理保证健壮性
- 能否识别数据的层级结构:Feature → Geometry → Coordinates
不少人在这里浪费时间,因为 JSON 的嵌套层级比想象中深。
import json
import logging
import sys
def load_coordinates(path):
"""读取 GeoJSON,返回路线上的 [lon, lat] 坐标列表"""
try:
with open(path, encoding="utf-8") as f:
data = json.load(f)
except (OSError, json.JSONDecodeError) as e:
logging.error("failed to read %s: %s", path, e)
raise
# 兼容 FeatureCollection / Feature 两种顶层结构
features = data["features"] if data.get("type") == "FeatureCollection" else [data]
for feature in features:
geometry = feature.get("geometry") or {}
if geometry.get("type") == "LineString":
return geometry["coordinates"]
raise ValueError("no LineString geometry found")
if __name__ == "__main__":
path = sys.argv[1] if len(sys.argv) > 1 else "ride-simple.json"
for lon, lat, *_ in load_coordinates(path)[:10]:
print(f"{lat:.6f}, {lon:.6f}")
常见坑:GeoJSON 的坐标顺序是 [经度, 纬度](lon, lat),和平时习惯的「纬度, 经度」相反,输出和画图时很容易搞反。
Part 2:HTTP 请求处理
向指定 URL 发送一个 POST 请求,请求体是 JSON(通常和上一部分的内容类似),服务器返回一张 PNG 地图图片,你要把图片保存到本地。
面试官会观察:
- 是否熟悉常用的 HTTP 库(比如
requests) - 是否正确设置 headers、序列化 JSON
- 出错时是否打印合理的日志
很多人卡在这里,不是逻辑错,而是不熟悉第三方库,或者忘了处理网络错误和文件保存路径。
import logging
import os
import requests
def fetch_map(url, coordinates, out_path="map.png", timeout=10):
"""把坐标 POST 给地图服务,保存返回的 PNG"""
try:
resp = requests.post(url, json={"coordinates": coordinates}, timeout=timeout)
resp.raise_for_status()
except requests.RequestException as e:
logging.error("request to %s failed: %s", url, e)
raise
if "image/png" not in resp.headers.get("Content-Type", ""):
raise ValueError(f"unexpected content type: {resp.headers.get('Content-Type')}")
os.makedirs(os.path.dirname(out_path) or ".", exist_ok=True)
with open(out_path, "wb") as f:
f.write(resp.content)
logging.info("saved map to %s (%d bytes)", out_path, len(resp.content))
return out_path
json= 参数会自动序列化 JSON,并设置 Content-Type: application/json。
Part 3:用 staticmap 库绘制地图
改用 staticmap 库在本地自己画地图:把路线画成折线,生成图片。关键是读懂这个库的文档:先创建地图对象,把路线坐标作为一条线添加上去,再渲染保存。注意它同样使用 (lon, lat) 顺序。
Part 4:地标标记与最近点查找
题目给出一组地标坐标,要求在地图上标注出来,并计算离骑行路线最近的地标。
题目没有要求复杂算法,但面试官会看你是否合理使用数据结构:直接暴力遍历,还是采用更高效的空间结构。
import math
def haversine_km(a, b):
"""两个 (lon, lat) 点之间的球面距离(公里)"""
lon1, lat1, lon2, lat2 = map(math.radians, (*a, *b))
h = math.sin((lat2 - lat1) / 2) ** 2 + math.cos(lat1) * math.cos(lat2) * math.sin((lon2 - lon1) / 2) ** 2
return 2 * 6371 * math.asin(math.sqrt(h))
def nearest_landmark(route, landmarks):
"""landmarks: {name: (lon, lat)};返回 (名称, 到路线上最近一点的距离 km)"""
best = None
for name, pos in landmarks.items():
d = min(haversine_km(pos, p[:2]) for p in route)
if best is None or d < best[1]:
best = (name, d)
return best
暴力解是 O(地标数 × 路线点数)。题目数据量(约 500 个点)下完全够用,先写出来、再讨论优化最稳妥:数据量大时,可以把路线点建成 KD-Tree 或按 geohash 分桶,每次只查附近的点。
准备建议
这套面试本质是考工程思维和真实的开发习惯,不在意你能不能写出最优算法。所以准备的重点不是刷题,而是熟悉 Python 的这些基础:
- I/O 与文件系统、JSON、HTTP(
requests) - 异常处理与日志
- 模块化设计
能展示出 clean code、分层清晰、日志完备、命名规范,往往比写出高效算法更重要。
看完有收获? 欢迎交流。
交流面经、互相 mock、内推信息,都可以找我。
