跳到主要内容

uni-app 接微信支付的完整流程是什么?前端、后端、微信分别做什么?

本文默认语境是 uni-app 发起微信支付,支付渠道是 微信小程序 / 微信客户端生态。面试时要主动说明:不同终端的拉起方式会有差异,但核心链路都绕不开 3 个角色:前端下单请求、后端统一签名、客户端拉起支付、微信异步回调确认结果

面试速答(30 秒版 TL;DR)

  • 微信支付流程不能简单说成“前端调个支付 API 就行”,真正的完整链路是:
    1. 前端请求业务后端创建订单
    2. 后端调用微信统一下单接口,拿到支付参数
    3. 后端把签名后的支付参数返回前端
    4. 前端调用 uni.requestPayment 拉起微信支付
    5. 用户完成支付后,微信通过回调通知后端
    6. 后端验签、更新订单状态,前端再主动查询最终结果
  • 面试里最关键的一句是:
    • 支付结果不能只信前端 success 回调,最终要以后端异步通知和订单查询为准。

心智模型:支付不是一个前端动作,而是一条“交易状态流”

很多人第一次接微信支付,会误以为流程是:

  • 用户点支付
  • 前端拉起收银台
  • 返回成功
  • 订单结束

这个理解太浅,因为支付本质上是一次交易状态流转。

这里至少有 4 个系统参与:

  • 前端应用
  • 业务后端
  • 微信支付平台
  • 用户客户端

这张图最重要的点不是步骤数量,而是你要看出:

  • 前端只负责“发起支付”
  • 后端负责“创建订单、签名、验签、改状态”
  • 微信负责“真正扣款与通知”

1. 为什么微信支付必须后端参与,前端不能自己签

这是支付题里非常核心的安全点。

因为支付流程里会涉及:

  • 商户号
  • API 密钥 / 私钥
  • 签名
  • 金额与订单号校验

这些都不能放到前端。

所以面试里要明确说:

  • 前端只能拿后端生成好的支付参数,不能自己直接和微信支付平台做敏感签名交互。

如果让前端自己签,会有明显风险:

  • 密钥泄露
  • 金额被篡改
  • 订单号伪造

2. 一条完整的支付链路应该怎么讲

2.1 前端先请求业务后端创建订单

用户点击“立即支付”后,前端不是直接调支付,而是先调用业务接口,例如:

const res = await uni.request({
url: '/api/pay/create-order',
method: 'POST',
data: {
skuId: 'sku_1001',
count: 2,
addressId: 'addr_99',
},
})

这一步业务后端通常要做:

  • 校验商品和库存
  • 计算最终金额
  • 创建业务订单
  • 把订单状态置为“待支付”

注意这里有一个高频面试点:

  • 支付金额应以后端计算为准,不能信前端传的金额。

2.2 后端调用微信下单接口,拿支付参数

业务后端创建完订单后,再去调微信支付相关接口,生成预支付信息。

这一步后端通常要完成:

  • 生成商户订单号
  • 组装支付请求参数
  • 做签名
  • 调微信接口
  • 获取 prepay_id 或对应支付参数

然后再把前端调用支付所需字段返回给客户端。

2.3 前端调用 uni.requestPayment

这是 uni-app 侧最核心的支付 API。

示例:

async function pay(orderId: string) {
const { data } = await uni.request({
url: '/api/pay/prepare',
method: 'POST',
data: { orderId },
})

const payInfo = data.data

return new Promise((resolve, reject) => {
uni.requestPayment({
provider: 'wxpay',
timeStamp: payInfo.timeStamp,
nonceStr: payInfo.nonceStr,
package: payInfo.package,
signType: payInfo.signType,
paySign: payInfo.paySign,
success(res) {
resolve(res)
},
fail(err) {
reject(err)
},
})
})
}

这里要特别强调:

  • uni.requestPayment 的参数不是前端自己拼的
  • 它们应当全部来自后端

2.4 支付结果要以后端异步通知为准

前端调用 uni.requestPayment 后,即使进入了 success 回调,也不能立刻把订单强行标记成“支付成功”。

原因是:

  • 前端回调只说明客户端侧支付流程走到了某个阶段
  • 真正可靠的交易确认,必须以后端收到微信异步通知并验签成功为准

这是支付题的关键结论。

你可以直接背这句话:

  • 前端 success 只能说明“支付发起结果看起来成功”,不能单独作为最终到账依据。

3. 为什么支付结果要“前端查询 + 后端回调”双保险

因为支付链路很容易出现时序问题。

例如:

  • 用户付完钱,前端页面被关闭
  • 微信已经回调后端,但前端还没拿到结果
  • 前端拿到 fail,但实际上用户已完成支付
  • 网络抖动导致回调和前端跳转顺序错乱

所以常见工程做法是:

3.1 后端异步通知负责改订单最终状态

后端收到微信通知后:

  1. 验签
  2. 校验金额、商户订单号、支付状态
  3. 幂等更新订单
  4. 记录支付流水

3.2 前端在支付返回页主动轮询或查询订单状态

例如:

const { data } = await uni.request({
url: '/api/pay/query-order-status',
method: 'GET',
data: { orderId },
})

if (data.data.status === 'PAID') {
uni.redirectTo({
url: `/pages/pay/result?orderId=${orderId}`,
})
}

这样做的价值是:

  • 前后端状态更容易收敛
  • 用户看到的是业务订单最终状态,而不是单次前端回调结果

4. 面试里最容易被追问的几个安全与一致性问题

4.1 为什么金额必须后端计算

因为前端参数可以篡改。

如果金额由前端提交并直接信任,就可能出现:

  • 1 分钱买到 100 元商品
  • 修改商品数量或优惠金额

所以金额、优惠、运费、最终应付,都要由后端重新计算并落库。

4.2 为什么异步通知要验签

因为后端不能无条件相信任何外部请求。

验签的作用是确认:

  • 这个通知确实来自微信
  • 内容没有被篡改

4.3 为什么更新订单要做幂等

因为支付通知可能重复到达,或者前端重复请求查询与补偿。

如果没有幂等控制,可能出现:

  • 重复发货
  • 重复加积分
  • 重复记账

所以后端更新支付成功状态时,要按订单号或支付流水号做幂等保护。


5. 典型题 & 标准答法

Q1:uni-app 接微信支付的流程是什么?

标准答法:

  1. 前端调用业务接口创建待支付订单
  2. 后端按订单信息调用微信统一下单接口,拿到预支付参数并签名
  3. 后端把支付参数返回前端
  4. 前端调用 uni.requestPayment
  5. 微信支付完成后,微信异步通知后端
  6. 后端验签、校验金额并幂等更新订单状态
  7. 前端再查询订单状态并展示最终结果

Q2:为什么不能只看 uni.requestPayment 的 success?

  • 因为前端 success 不是最终入账证明
  • 最终支付结果应以后端异步通知和订单查询结果为准

Q3:支付链路里前端和后端分别负责什么?

  • 前端:发起支付、展示支付中状态、查询结果页
  • 后端:创建订单、调微信下单、签名、验签、更新状态、幂等处理

6. 常见追问

6.1 用户支付中途取消怎么办?

前端通常会进入 fail 或取消分支,但业务上不能立刻认定订单彻底失败。

更稳的做法是:

  • 订单先保持待支付
  • 提示用户可继续支付
  • 以后端查询或超时关闭策略为准

6.2 为什么要有“待支付”“支付中”“支付成功”“已关闭”这些状态?

因为支付不是瞬时动作,而是状态机。

状态拆清楚后,系统才好处理:

  • 超时未支付关闭
  • 回调迟到
  • 用户重复进入支付页
  • 支付成功后的发货 / 积分 / 通知

6.3 支付成功页为什么有时会“先失败后成功”?

因为前端回调、后端通知、订单查询三者可能不同步。

所以正确做法不是只看一次前端回调,而是:

  • 展示“支付结果确认中”
  • 主动查询订单状态
  • 以后端最终状态为准

7. 易错点 / 坑

  • 前端直接信任支付 success,立刻把订单记成功
  • 金额由前端传入且后端未复算
  • 后端收到支付通知不验签
  • 订单状态更新没有幂等控制
  • 用户取消支付后直接把订单永久关闭,导致补支付链路混乱
  • 没有支付结果查询页,只依赖一次性回调

速记要点

  • 支付流程 = 前端发起 + 后端签名 + 微信扣款 + 后端回调确认
  • uni.requestPayment 只是拉起支付,不等于最终成功
  • 最终状态以后端异步通知和查询为准
  • 金额必须后端计算
  • 回调必须验签
  • 更新订单必须幂等