← 返回题目列表

小程序支付流程是怎样的?前端和服务端分别负责什么?

中等 第 28 / 32 题 更新于 2026/07/29
小程序微信支付订单支付回调

简化版

小程序支付通常是前端创建业务订单,服务端统一下单拿到支付参数,前端调用 wx.requestPayment 拉起支付,支付结果以服务端回调为准。前端页面返回成功只能作为体验提示,真正改订单状态必须依赖微信支付回调和服务端验签。

详细版

标准流程:

  1. 前端提交商品、数量、地址等信息。
  2. 服务端校验价格、库存和用户身份,创建待支付订单。
  3. 服务端调用微信支付统一下单接口,返回支付参数。
  4. 前端调用 wx.requestPayment
  5. 微信支付平台异步通知服务端。
  6. 服务端验签、校验金额和订单号,更新订单状态。
  7. 前端轮询或查询订单状态展示结果。

关键点:

  • 金额不能由前端决定。
  • 支付成功以服务端回调为准。
  • 回调可能重复到达,必须幂等。
  • 取消支付、支付失败、回调延迟要区分。
  • 订单超时关闭需要定时任务或支付平台关单能力配合。

完整版教学

一、支付链路为什么不能只看前端返回

wx.requestPayment 的成功回调表示用户侧支付动作完成得比较顺利,但它不是订单系统的最终事实。网络抖动、页面关闭、回调延迟、恶意篡改都可能让前端状态和支付平台状态不一致。真正可信的是微信支付平台发给服务端的异步通知,并且服务端要验签。

这个原则在面试里非常关键:前端只负责拉起支付和展示体验,服务端负责创建订单、生成支付参数、接收回调和更新状态。任何“前端说成功就发货”的设计都存在严重风险。

用户点击支付
  → 服务端创建订单
  → 微信支付统一下单
  → 前端拉起收银台
  → 微信异步回调服务端
  → 服务端确认订单成功

二、订单和支付单要分清

业务订单和支付单不是同一个概念。业务订单描述用户买了什么、多少钱、收货地址是什么;支付单描述这次向支付平台发起的支付请求。一个订单可能因为重试、超时、改价而对应多次支付尝试,所以系统里最好有清晰的支付记录。

举例:订单 O1001 金额 99 元,第一次支付单 P1 用户取消,第二次支付单 P2 支付成功。业务订单最终是已支付,但不能把 P1 的取消覆盖掉 P2 的成功。面试答出这个区分,说明你理解支付不是一个简单按钮事件。

对象关注点状态例子
业务订单商品、价格、履约待支付、已支付、已取消
支付单支付渠道请求待支付、支付成功、支付失败
回调记录平台通知证据已验签、重复通知、异常

三、金额必须由服务端计算

前端可以展示价格,但不能成为价格来源。攻击者可以改请求参数、改本地缓存、甚至直接构造接口请求。如果服务端信任前端传来的 totalFee=1,原价 199 元的商品就可能被 1 分钱买走。

正确做法是前端只传商品 ID、规格、优惠券 ID、地址等业务输入,服务端读取商品表、活动规则和用户权益后计算金额。支付回调时还要核对平台通知金额是否等于订单应付金额,防止串单或异常回调。

// 前端不要传最终金额作为可信值
createOrder({ skuId: 'sku_1', count: 2, couponId: 'c_8' })

// 服务端根据 sku、库存、活动、优惠券计算应付金额
// payAmount = skuPrice * count - couponDiscount

四、回调幂等是支付系统的基本功

微信支付回调可能因为网络原因重复发送。服务端必须做到同一个支付结果处理多次,最终效果和处理一次相同。常见做法是用订单状态机和唯一支付交易号控制。

假设支付平台对同一交易通知 3 次,如果你的库存扣减逻辑没有幂等,就可能扣 3 次库存、发 3 张券、发送 3 条通知。正确做法是在事务里判断订单是否已经是已支付;如果已支付,直接返回成功给支付平台,不再重复执行业务动作。

收到回调
  ├─ 验签失败:拒绝
  ├─ 金额不一致:报警
  ├─ 订单已支付:直接返回成功
  └─ 待支付:更新订单 + 扣库存 + 记录流水

五、前端状态展示要处理延迟

用户支付完成回到小程序时,服务端回调可能还没处理完。此时前端如果立即显示“支付失败”,用户会非常困惑。更稳妥的体验是展示“支付结果确认中”,然后查询订单状态,必要时短时间轮询。

例如支付完成后每 1 秒查一次,最多查 5 次。如果 5 秒内订单变为已支付,就展示成功;如果仍未确认,提示用户稍后在订单页查看。这样既避免无限轮询,也能覆盖回调延迟。

六、取消、失败、超时关闭要分开

用户取消支付不是系统错误,支付失败也不一定代表订单取消。订单通常会保持待支付一段时间,比如 15 分钟,超时后关闭订单并释放库存。前端要根据不同状态给不同按钮:取消后可以继续支付,超时后可能要重新下单。

如果涉及库存,锁库存和扣库存策略也要设计。常见方案是下单锁库存、支付成功扣实库存、超时释放锁定库存。轻量系统可以简单一些,但面试中至少要说出“支付状态”和“库存履约”不是同一个动作。

支付心法:前端负责拉起和反馈,服务端负责可信事实;订单成功只能由验签后的支付回调确认。

七、常见误区与追问

  • 误区:wx.requestPayment success 就可以直接发货。 前端回调不具备最终可信性,发货必须依赖服务端支付回调确认。
  • 误区:金额从前端传过来更方便。 前端参数可篡改,服务端必须重新计算金额并在回调中核对。
  • 误区:支付回调只会来一次。 平台可能重复通知,服务端必须幂等处理。
  • 追问:回调比前端返回慢怎么办? 前端展示确认中并查询订单状态,短时间轮询后给订单页兜底。
  • 追问:用户取消支付订单要关闭吗? 通常不立即关闭,可保留待支付,到超时时间再关单释放资源。
  • 追问:如何防止串单? 回调验签后校验商户订单号、交易号、金额、商户号和订单状态。

八、加强记忆

小程序支付用“两条线”记:用户交互线是前端拉起支付、展示结果;资金事实线是服务端下单、平台回调、验签落库。所有金额由服务端算,所有成功由回调定,所有重复通知用幂等挡住。把这三点讲清楚,支付题基本不会飘。