uniapp 开发的支付宝小程序支付完成后如何跳回小程序
结论
在支付宝小程序中发起支付,应使用小程序原生支付 API my.tradePay。支付结束后,支付宝会关闭收银台并返回当前小程序。小程序可以在支付回调中跳转到订单结果页。
如果目前使用 alipay.trade.wap.pay、alipay.trade.page.pay,或通过 WebView、外部链接打开收银台,那么支付完成页中“完成”按钮的去向通常不受小程序控制。设置 return_url 也无法保证用户返回当前小程序。这种情况需要更换支付接入方式,修改支付成功页解决不了问题。
原因
支付宝的网页支付和小程序支付采用不同的流程:
- 网页支付会离开小程序上下文,支付完成页由支付宝控制。
- 小程序支付通过
my.tradePay拉起原生收银台,支付结束后会回到调用该 API 的小程序页面。 return_url用于网页支付完成后的浏览器跳转,并不等同于“返回支付宝小程序”。- 前端收到支付成功回调,只能说明收银台返回了相应结果。订单的最终状态仍应通过服务端查询或异步通知确认。
推荐实现流程
1. 服务端创建支付宝交易
服务端调用适用于支付宝小程序场景的交易创建接口,例如 alipay.trade.create,获取支付宝交易号 trade_no。
应用私钥和签名逻辑不能放在小程序前端。具体请求参数应以当前接入的支付产品和支付宝开放平台文档为准。
服务端可以向小程序返回如下数据:
{
"tradeNo": "2026xxxxxxxxxxxxxxxx"
}
2. 小程序调用 my.tradePay
在 uni-app 项目中,可以通过支付宝平台条件编译调用支付 API:
// #ifdef MP-ALIPAY
my.tradePay({
tradeNO: tradeNo,
success: (res) => {
const resultCode = String(res.resultCode)
if (resultCode === '9000') {
// 收银台返回支付成功,但仍建议向服务端确认订单状态
confirmOrderStatus()
return
}
if (resultCode === '8000') {
uni.showToast({
title: '支付结果确认中',
icon: 'none'
})
confirmOrderStatus()
return
}
if (resultCode === '6001') {
uni.showToast({
title: '已取消支付',
icon: 'none'
})
return
}
uni.showToast({
title: '支付未完成',
icon: 'none'
})
},
fail: (err) => {
console.error('tradePay fail:', err)
uni.showToast({
title: '支付调用失败',
icon: 'none'
})
}
})
// #endif
这里的 tradeNo 是服务端创建交易后返回的支付宝交易号,不是商户订单号。
3. 向服务端确认订单状态
不要只根据 resultCode === '9000',就将订单永久标记为已支付。前端应再次查询自己的服务端,确认订单状态:
function confirmOrderStatus() {
uni.request({
url: 'https://example.com/api/orders/status',
method: 'GET',
data: {
orderNo: currentOrderNo
},
success: (res) => {
if (res.data && res.data.paid === true) {
uni.redirectTo({
url: `/pages/order/result?orderNo=${encodeURIComponent(currentOrderNo)}`
})
} else {
uni.showToast({
title: '支付结果确认中,请稍后查看订单',
icon: 'none'
})
}
},
fail: () => {
uni.showToast({
title: '订单状态查询失败',
icon: 'none'
})
}
})
}
服务端应根据支付宝异步通知或主动查询结果更新订单状态,同时完成签名验证、金额校验和幂等处理。
如果当前使用的是网页支付
先检查后端是否调用了以下接口:
alipay.trade.wap.pay
alipay.trade.page.pay
如果调用了其中一个接口,当前拉起的就是网页收银台。在这套流程中,支付成功页和“完成”按钮通常由支付宝客户端控制,小程序无法通过普通前端代码改变其行为。
支付流程应调整为:
小程序请求创建订单
→ 服务端调用小程序适用的交易创建接口
→ 服务端返回 trade_no
→ 小程序调用 my.tradePay
→ 收银台关闭并回到小程序
→ 小程序向服务端确认订单状态
不要将小程序页面路径直接填写到网页支付的 return_url。小程序页面不是普通的 HTTP 页面,这种设置通常无法建立可靠的返回链路。
注意事项
my.tradePay必须在支付宝小程序环境中调用。- 支付 API 一般应由用户点击按钮触发,不应在页面加载时自动、连续拉起。
- 支付完成后的业务跳转由小程序在回调中处理,可以使用
uni.redirectTo、uni.navigateTo或uni.switchTab。 - 如果目标页面属于
tabBar,必须使用uni.switchTab,不能使用uni.redirectTo。 - 用户可能在支付后直接关闭小程序,因此服务端必须能通过异步通知独立完成订单更新。
- 支付参数和可用接口可能受到支付宝产品签约、应用类型及当前平台规则的限制。接入前,应确认对应应用已在支付宝开放平台获准使用相关支付产品。
备注:内容仅供参考。
