加纳街头的二手车大多来自美国:先经拍卖行成交,再运到特马港,最后摆上路边的车行或挂上网络车源。卖家的话术高度统一——"无事故、低里程、一手车主"。
2026年8月,加纳标准局宣布,自2026年10月1日起禁止进口车龄15年及以上的二手车。买家突然必须搞清楚一辆车的真实车型年份,而不是广告里卖家随手填的那个数字。
TrustCheck 联合创始人 Elliot 的团队原本做的是企业、电话号码和价格的核验工具,这次他们加了一个免费工具:粘贴 VIN 码,返回车辆的真实信息、召回记录、车主投诉和碰撞评级。数据全部来自免费公开接口,不需要 API 密钥——用 NHTSA 的 vPIC 解码 VIN,调 NHTSA 的召回、投诉和五星碰撞评级数据,再结合美国环保署 fueleconomy.gov 的油耗数据与加纳当前油价,估算每月燃油开销(单位塞地)。
接口本身没问题,麻烦都藏在接口与接口之间的缝隙里。Elliot 把踩过的坑按代码顺序列了出来。
第一坑:VIN 得先洗干净
人们对着挡风玻璃照片手敲 VIN,常把 0 和 O、1 和 I 搞混。标准里 VIN 本来就不含 I、O、Q 三个字母,正是为了防这种混淆。所以对 17 位输入,可以放心把它们映射回去:I 变 1,O 和 Q 变 0。Elliot 说,就这一处改动,让大量"VIN 无效"的报错变成了真实结果。
第二坑:校验位只对部分车有意义
VIN 第 9 位是校验位,由其余 16 位加权求和后对 11 取模算出。Elliot 的第一版代码只要校验位对不上就弹"这个 VIN 可能是假的",这是错的。校验位是北美市场车型(VIN 以 1 到 5 开头)的强制要求,日本、欧洲、海湾地区生产的很多车根本不用它,而加纳市场上这类车不少。
于是规则改成:只有北美 VIN 校验失败才给强警告,其他情况只作提示。他的判断很直接——对一半的车乱喊狼来了,工具就会被用户无视,误报同样是 bug。
第三坑:NHTSA 自己跟自己不一致
这是最大的意外。VIN 解码器、召回接口和投诉接口对同一款车的写法并不统一:解码器给出型号"Sierra"、系列"1500",召回库里登记的是"SIERRA 1500";雷克萨斯"RX 350"在召回库里写作"RX350";召回接口认"C300",投诉接口认"C-CLASS"。
这个问题是在一辆 2017 款 GMC Sierra 上暴露的。页面当时骄傲地显示 0 条召回,而 NHTSA 实际有 6 条召回和 433 条投诉。Elliot 的原话是:告诉用户"没有召回"而实际有六条,比没有这个工具更糟。
修法是一串兜底:只有当按原名查不到任何结果时才启动。先尝试"型号+系列"的组合,再尝试去掉空格和标点的规范化名称,再从配置级别里推出别名。哪条路径查到了召回,就把那个名称存下来,投诉接口复用同一个名字,保证报告的两部分描述的是同一辆车。resolveModel() 会下载 NHTSA 自己那份按品牌和年份的车型名单(缓存 30 天),再做规范化匹配。
教训写得很清楚:组合同一家服务商的多个接口时,别假设它们共享标识符,要用真实、脏乱的输入去测,尤其是皮卡和豪华配置车型。
第四坑:一个接口要 9 秒
热门车型的投诉接口单次能跑 9 秒左右。串行调用下来,整份报告要 15 秒以上,手机流量下用户会以为页面坏了。团队做了三件事:
- 并行请求。召回、碰撞评级和环保署车型列表互不依赖,用 Laravel 的 Http::pool 一起发出,超时 25 秒;第二轮再并行拉取依赖第一轮结果的数据。
- 区分缓存时长。完整结果缓存 7 天;只要有任一数据源失败,部分结果只缓存 15 分钟,免得 NHTSA 一次短暂抖动被锁死一周。
- 夜间预热。站内有 312 个车型页面(热门车型×2010 至 2022 年),定时任务在凌晨 1 点到 5 点半之间每小时加载 24 个车型年份,到早上常用页面已经是热的。
前端也做了处理:点击查询后,报告区域先显示骨架屏和诚实的步骤提示("正在查询召回记录…"),而不是一个空转的加载图标。用户看得见进展,就愿意多等。
第五坑:自建 VIN 历史,但不存个人数据
美国的数据抓不到加纳最要命的那类骗局:同一辆车调低里程后重新挂牌,或者同一组照片被几个卖家共用。所以每次查询都会记一条"目击":VIN、日期,以及卖家声称的里程、年份和价格。下一个查同一 VIN 的人能看到之前的记录,以及这类警告——两次查询之间里程下降超过 1000 公里(疑似调表);同一 VIN 由多个不同电话号码出售(疑似盗图);声称的车型年份反复变化。
难点在于,统计不同卖家需要卖家号码,而 Elliot 不想建一个电话号码库。号码和查询者 IP 只以 HMAC 哈希形式存储。哈希能用来计数和比对("3 个不同卖家"),但读不回原号码。这里用带密钥的 HMAC 而不是普通 SHA-256 是有原因的:电话号码空间很小,无密钥哈希几分钟就能暴力反推。
调表检测本身很简单:按日期顺序遍历目击记录,跟踪迄今见过的最高里程,一旦出现比峰值低 1000 公里以上的记录就标记。每个访客对每个 VIN 每天只留一行,刷新页面伪造不出历史。
第六坑:不是每辆车都有 VIN
日本市场车型常用车架号,比如 NZE141-1234567,格式是车型代码、连字符、序列号。NHTSA 解不了这类号码,很多海湾和欧洲 VIN 也解不全。工具没有直接报错,而是接受车架号格式,改用卖家声明的品牌、型号和年份出报告,并明确标注哪些部分来自卖家而非 VIN。一个说清来源的部分答案,对站在车行里的人依然有用。
Elliot 给其他开发者的几条经验:政府公开接口被低估了,召回、投诉、碰撞评级和油耗全都免费且无需密钥;bug 会出现在系统之间的连接处,而不是任何一个系统内部,要用目标市场的真实输入去测;安全类工具里,虚假的"一切正常"是最坏的 bug,他宁可显示"这项我们查不了",也不显示"0 条召回";部分结果短缓存、完整结果长缓存;不收集个人数据也能建出有用的共享历史,带密钥的哈希让你能计数而无需知情。
工具已在 trustcheckapp.com/tools/car-check 上线,免费使用。
热门跟贴