PAYATHON 2026

对接扫描支付宝订单码支付后页面是否会跳转?

支付阿杰

明确结论

如果使用支付宝当面付扫码模式,例如通过 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,支付完成后,浏览器可能同步返回该地址。

是否会跳转,取决于实际使用的支付宝产品和接口,不能只根据“支付宝支付”这一点来判断。

推荐实现方式

可以按下面的流程处理:

  1. 服务端调用 alipay.trade.precreate 创建订单。
  2. 前端展示接口返回的二维码。
  3. 服务端通过 notify_url 接收支付宝异步通知。
  4. 前端定时请求商户服务端,查询订单状态。
  5. 服务端根据异步通知记录判断状态,或者调用 alipay.trade.query 核实交易状态。
  6. 前端确认订单支付成功后,跳转到商户自己的结果页面。

各环节的关系如下:

用户扫码支付
    ↓
支付宝完成交易
    ↓
支付宝通知商户 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 的规则处理。

备注:内容仅供参考。