4. 支付核心链路高频问题

支付核心链路是面试官判断候选人是否“真做过支付”的分水岭。很多人能背出“收单、路由、风控、渠道网关、回调、重试”这六个词,但一旦被追问“路由失败后订单状态怎么流转”“回调重复到达如何保证幂等”“重试和补偿的边界在哪”,回答就开始发散。本章的目标不是让你背链路名词,而是建立一条可复述、可追问、可落地的回答主线。

面试官问“讲一下支付核心链路”,本质是在考察三件事:你是否理解资金与状态的流转顺序;你是否能说清每个环节的失败处理;你是否知道不同公司在这条链路上的侧重点差异。
收单 风控 路由 渠道网关 回调与重试 创建订单 准入与拦截 选渠道 请求外部 状态收敛 支付核心链路:正向流转与失败兜底并行

一、核心原理:链路是状态机,不是函数调用

支付链路最容易被误解成一条同步调用链:收单调风控,风控调路由,路由调渠道,渠道返回结果。真实系统里,这条链路是“同步请求 + 异步回调 + 定时补偿”三线并行的状态机。任何一步都可能超时、失败、重复,因此核心设计原则是:先落状态,再发请求;以最终状态为准,不以单次返回为准。

  • 收单:生成支付单,做参数校验、金额校验、商户校验,写入初始状态(如 INIT)。
  • 风控:同步或异步做准入判断,输出通过、拒绝、人工审核三类结果,拒绝要能回写订单。
  • 路由:根据渠道成本、成功率、限额、可用性选择渠道,路由结果要可追溯、可降级。
  • 渠道网关:负责协议适配、签名、超时控制、请求日志,屏蔽不同渠道差异。
  • 回调:接收渠道异步通知,验签、幂等、更新订单,并触发下游业务。
  • 重试:对超时和未知状态做查询或补偿,区分“可重试”和“不可重试”。

二、方法流程:一条可复述的回答主线

面试时建议按“正向 + 异常 + 兜底”三段式回答,避免从头到尾平铺直叙。正向讲清楚状态流转,异常讲清楚失败分类,兜底讲清楚如何保证最终一致。

  1. 收单创建支付单,状态 INIT,记录商户、金额、币种、业务单号。
  2. 风控准入,通过则进入路由,拒绝则置为 FAIL 并通知业务。
  3. 路由选渠道,生成渠道请求流水,状态置为 PROCESSING。
  4. 渠道网关发起请求,记录请求日志和渠道返回码。
  5. 同步返回成功不等于终态,等待回调或主动查询确认。
  6. 回调验签、幂等更新订单为 SUCCESS 或 FAIL,通知业务方。
  7. 超时或未知状态进入重试与补偿,按策略查询渠道终态。
回答时主动说出“同步返回只代表受理,不代表成功”,这句话能立刻体现你对支付终态的理解,是高频加分点。

三、案例与场景:路由失败与回调重复

场景一:路由失败。用户支付时渠道 A 超时,系统不能直接把订单置为失败,因为渠道可能已扣款。正确做法是保留 PROCESSING,触发渠道查询,确认失败后再置 FAIL,或切换渠道 B 重新支付。这里要强调“未知状态”是支付里最危险也最常见的状态。

场景二:回调重复。渠道因网络问题重复推送回调,系统必须用渠道流水号 + 商户单号做唯一键,先查后更或使用数据库唯一索引,保证幂等。更新成功后返回渠道约定的成功标识,避免渠道继续重推。

// 回调幂等伪代码
if (exists(channelNo, merchantOrderNo)) {
    return SUCCESS; // 已处理,直接应答
}
try {
    insertCallbackLog(channelNo, merchantOrderNo);
    updateOrderStatus(merchantOrderNo, SUCCESS);
    notifyBusiness(merchantOrderNo);
} catch (DuplicateKeyException e) {
    return SUCCESS; // 并发重复,视为已处理
}
return SUCCESS;

四、误区与复盘:别把重试当万能药

最常见的误区是“失败就重试”。支付里必须区分:网络超时可重试,参数错误不可重试,风控拒绝不可重试,渠道明确失败不可重试。盲目重试会造成重复扣款或重复发货。
环节高频追问回答要点
收单如何防重复下单业务单号唯一索引 + 幂等键
风控同步还是异步按拦截时效要求选择,拒绝要回写
路由如何降级成功率、成本、限额、熔断
渠道网关超时怎么处理记录未知态,走查询补偿
回调如何保证幂等唯一键 + 先查后更 + 日志
重试重试边界只重试可恢复错误,设上限和退避

最后是公司侧重点差异:电商支付更关注收单与回调的幂等和履约一致性;金融支付更关注风控、合规与资金安全;聚合支付更关注路由成本与渠道覆盖率;跨境支付更关注汇率、清结算和渠道时区。面试前先判断目标公司属于哪一类,再调整回答重心,比背一套通用答案更有效。