对接扫描支付宝订单码支付后页面是否会跳转?
支付阿杰
明确结论
如果使用支付宝当面付扫码模式,例如通过 alipay.trade.precreate 生成订单二维码,那么用户支付成功后,展示二维码的商户页面不会由支付宝自动跳转。
支付是在用户的支付宝客户端中完成的,商户页面和支付宝客户端属于两个独立环境。支付完成后:
- 支付宝客户端通常会显示支付结果。
- 商户页面不会自动收到浏览器跳转指令。
- 商户系统需要通过异步通知或主动查询确认支付状态,再由前端跳转到商户自己的支付结果页。
最终跳转地址由商户定义,例如:
https://example.com/payment/result?order_no=202609090001
为什么不会自动跳转
alipay.trade.precreate 用于创建交易并返回二维码内容。用户使用支付宝扫描二维码后,后续支付流程都在支付宝客户端内完成。
二维码展示页一般运行在商户的浏览器、收银机或其他终端上。支付宝无法在支付成功后直接控制这个页面,因此它不会像普通网页支付那样,根据 return_url 自动返回商户页面。
这里需要区分两种场景:
- 扫码支付:通常使用
alipay.trade.precreate。二维码页面需要自行查询支付状态,并在确认成功后跳转。 - 电脑网站支付:通常使用
alipay.trade.page.pay。可根据接口支持情况配置return_url,支付完成后,浏览器可能同步返回该地址。
是否会跳转,取决于实际使用的支付宝产品和接口,不能只根据“支付宝支付”这一点来判断。
推荐实现方式
可以按下面的流程处理:
- 服务端调用
alipay.trade.precreate创建订单。 - 前端展示接口返回的二维码。
- 服务端通过
notify_url接收支付宝异步通知。 - 前端定时请求商户服务端,查询订单状态。
- 服务端根据异步通知记录判断状态,或者调用
alipay.trade.query核实交易状态。 - 前端确认订单支付成功后,跳转到商户自己的结果页面。
各环节的关系如下:
用户扫码支付
↓
支付宝完成交易
↓
支付宝通知商户 notify_url
↓
商户更新本地订单状态
↓
二维码页面轮询商户订单状态
↓
跳转到商户支付结果页
前端轮询与跳转示例
下面的示例每两秒查询一次订单状态。确认支付成功后,当前页面会主动跳转:
const orderNo = "202609090001";
const timer = setInterval(async () => {
try {
const response = await fetch(
`/api/payment/status?order_no=${encodeURIComponent(orderNo)}`,
{
method: "GET",
credentials: "same-origin"
}
);
if (!response.ok) {
return;
}
const result = await response.json();
if (result.status === "SUCCESS") {
clearInterval(timer);
window.location.href =
`/payment/result?order_no=${encodeURIComponent(orderNo)}`;
}
if (result.status === "CLOSED") {
clearInterval(timer);
window.location.href =
`/payment/failed?order_no=${encodeURIComponent(orderNo)}`;
}
} catch (error) {
console.error("查询支付状态失败", error);
}
}, 2000);
商户服务端可以向前端返回统一的订单状态:
{
"order_no": "202609090001",
"status": "SUCCESS"
}
这些状态名称由商户根据自己的业务定义,无须把支付宝返回的字段直接暴露给前端。
服务端状态判断示例
如果本地还没有收到异步通知,服务端可以调用 alipay.trade.query 查询交易状态。通常需要根据 trade_status 进行判断,例如:
function normalizeTradeStatus(tradeStatus) {
switch (tradeStatus) {
case "TRADE_SUCCESS":
case "TRADE_FINISHED":
return "SUCCESS";
case "TRADE_CLOSED":
return "CLOSED";
case "WAIT_BUYER_PAY":
return "PENDING";
default:
return "UNKNOWN";
}
}
不要让浏览器携带支付宝私钥直接调用查询接口。签名、验签和订单核对都应由商户服务端完成。
异步通知处理要点
收到 notify_url 通知后,不能只根据请求中的 trade_status 更新订单。至少要完成以下检查和处理:
- 验证支付宝通知签名。
- 核对
app_id是否属于当前商户应用。 - 核对
out_trade_no是否存在。 - 核对订单金额和币种是否与本地订单一致。
- 保证订单更新具有幂等性,避免重复通知导致重复发货。
- 处理完成后,按照支付宝接口要求返回成功响应。
前端跳转只是为了改善用户体验,不能作为确认支付成功或发货的最终依据。即使用户关闭了二维码页面,服务端仍应通过异步通知完成订单处理。
注意事项
return_url无法解决两个设备或两个页面之间的扫码支付跳转问题。- 前端轮询超时不代表支付失败。网络延迟或异步通知延迟都可能导致状态暂时没有更新。
- 轮询需要设置合理的间隔和最长持续时间,避免产生过于频繁的请求。
- 结果页应重新从服务端读取订单状态,不能只相信 URL 中的参数。
- 如果二维码显示在用户当前使用的手机浏览器中,而扫码支付需要切换到支付宝客户端,支付后的返回行为还可能受到产品类型、客户端和唤起方式影响,应以所接入接口的实际流程为准。
- 如果使用的不是
alipay.trade.precreate,而是alipay.trade.page.pay、手机网站支付或其他支付宝产品,需要分别按照对应接口中return_url和notify_url的规则处理。
备注:内容仅供参考。
