PAYATHON 2026

支付宝沙箱支付成功后通过 return_url 跳转时报404

支付阿杰

结论

支付已经成功,说明支付流程本身基本正常。返回时出现 404,通常与支付宝沙箱支付服务无关,更可能是 return_url 无法访问、URL 编码有误,或测试环境的 Web 服务配置不正确。

404 表示浏览器已经跳转到目标服务器,但服务器没有返回对应的应用页面。另一种可能是 return_url 在传递过程中被 # 截断或错误解析。

原因分析

当前配置使用了前端 Hash 路由:

http://172.16.140.3:8080/#/activity/pay

这个地址需要注意:

  • 浏览器实际向服务器请求的路径是 /
  • #/activity/pay 属于 URL Fragment,由前端路由在浏览器中处理
  • Fragment 不会发送给服务器

因此,跳转时必须先正常打开:

http://172.16.140.3:8080/

如果根地址返回 404,前端应用就无法加载,也不会进入 #/activity/pay。

另外还要检查两个问题:

  1. 172.16.140.3 是内网地址。执行跳转的浏览器必须能访问该内网。如果支付页面运行在手机、外部网络或其他隔离环境中,这个地址可能无法访问。
  2. # 是 URL 中的特殊字符。如果手工拼接支付宝请求地址时没有正确编码 return_url,# 后面的内容可能不会作为接口参数提交。

排查和解决步骤

1. 直接访问应用根地址

在完成支付的同一台设备和同一个浏览器中访问:

http://172.16.140.3:8080/

如果根地址已经返回 404,请检查 Nginx、Tomcat、前端静态资源服务或网关配置,确认应用是否确实部署在根路径。

如果应用实际部署在某个上下文路径,例如:

http://172.16.140.3:8080/app/

应将地址配置为:

http://172.16.140.3:8080/app/#/activity/pay

2. 确认路由页面本身可以访问

直接打开完整地址:

http://172.16.140.3:8080/#/activity/pay

如果根页面可以打开,但无法进入支付结果页,请检查前端是否注册了对应路由,以及应用的 base、publicPath 或构建部署路径是否正确。

例如,Vue Router 的 Hash 模式可以这样配置:

const router = createRouter({
  history: createWebHashHistory(),
  routes: [
    {
      path: '/activity/pay',
      component: PayResult
    }
  ]
})

3. 正确传递并编码 return_url

通过支付宝 SDK 设置参数时,应把完整 URL 作为 return_url 交给 SDK,不要手工拼接整个支付宝请求地址。

示例:

AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();

request.setReturnUrl("http://172.16.140.3:8080/#/activity/pay");
request.setNotifyUrl("https://example.com/alipay/notify");

如果必须自行构造查询参数,需要对完整的回跳地址进行 URL 编码。例如:

String returnUrl = "http://172.16.140.3:8080/#/activity/pay";
String encodedReturnUrl =
        URLEncoder.encode(returnUrl, StandardCharsets.UTF_8);

编码结果大致如下:

http%3A%2F%2F172.16.140.3%3A8080%2F%23%2Factivity%2Fpay

还要检查 URL 中是否有多余空格。问题描述中的本地地址为:

http://localhost:9000 /#/activity/pay

端口后多了一个空格,应改成:

http://localhost:9000/#/activity/pay

4. 检查内网地址的访问条件

172.16.140.3 属于私有网络地址。它能否用作 return_url,取决于发起支付的浏览器是否处于同一网络,与支付宝服务器能否访问该地址无关。

如果使用手机扫码支付,支付完成后由手机浏览器执行回跳,那么手机也必须能够访问:

172.16.140.3:8080

如果测试设备无法访问内网,可以改用测试域名、VPN、反向代理或临时公网映射地址,并优先使用 HTTPS。

Nginx 配置示例

如果前端应用部署在站点根目录,可以参考以下配置:

server {
    listen 8080;
    server_name 172.16.140.3;

    root /var/www/app;
    index index.html;

    location / {
        try_files $uri $uri/ /index.html;
    }
}

使用 Hash 路由时,服务器通常只会收到对 / 的请求。不过,配置 try_files 仍可避免静态资源路径出现 404,也方便以后切换到 History 路由。

注意事项

  • return_url 只用于支付完成后的浏览器页面跳转,不能单独作为判断支付成功的依据。
  • 支付结果应以后端异步通知 notify_url 的验签结果和主动查询结果为准。
  • 返回页面收到参数后仍要验证签名,不能仅根据页面跳转或前端参数修改订单状态。
  • 检查服务器是否只监听 127.0.0.1,同时确认防火墙、端口映射和反向代理规则。
  • 如果直接访问测试环境的完整 URL 正常,但支付宝跳转后的地址不完整,应重点检查 return_url 的编码,以及实际提交给支付宝的参数值。

备注:内容仅供参考。