PAYATHON 2026

H5支付沙箱环境跳转后重定向失败并出现白屏

支付阿杰

结论

同一套接入参数,有时能从 openapi-sandbox.dl.alipaydev.com 跳转到 mobileclientgw-sandbox.dl.alipaydev.com 并拉起支付,有时却出现白屏,问题通常出在以下几个环节:

  1. 支付宝沙箱网关不稳定或响应超时;
  2. 当前网络无法稳定访问沙箱域名;
  3. 页面运行在受限 WebView 中,重定向、Cookie 或 JavaScript 被拦截;
  4. SDK 返回的表单被二次处理,签名参数、编码或提交方式发生了变化。

沙箱环境主要用于联调,稳定性不能和生产环境相比。仅凭白屏无法确定具体原因,需要结合浏览器开发者工具中的请求状态、响应内容和重定向链路来判断。

原因分析

1. 沙箱网关响应异常

H5 支付通常调用 alipay.trade.wap.pay。服务端生成支付表单后,浏览器会先向以下地址提交请求:

https://openapi-sandbox.dl.alipaydev.com/gateway.do

网关随后返回页面,或者将浏览器重定向到移动端收银台域名。

如果第一个请求长时间处于 Pending 状态、返回 5xx、连接被重置或响应内容为空,问题通常出在沙箱网关或网络链路上。同一份表单重复提交时偶尔成功、偶尔白屏,也更像是网络或沙箱服务波动。

2. 网络、DNS 或代理影响

公司代理、VPN、DNS、防火墙或安全网关都可能影响沙箱域名的访问。常见情况包括:

  • 主网关可以访问,但后续收银台域名无法打开;
  • HTTPS 握手失败;
  • 请求长时间没有响应;
  • 重定向请求被代理拦截;
  • 手机网络正常而公司 Wi-Fi 异常,或者情况正好相反。

可以分别使用移动网络、家庭网络和公司网络测试,确认故障是否只出现在某种网络环境中。

3. WebView 限制重定向

如果支付页面是在 App 内置 WebView、微信内置浏览器或其他受限容器中运行,可能遇到以下问题:

  • WebView 不允许页面跳转;
  • 新窗口请求被拦截;
  • JavaScript 被禁用;
  • Cookie 或本地存储受限;
  • 自定义 URL Scheme 无法拉起支付宝;
  • HTTPS 页面加载了 HTTP 资源,被浏览器拦截。

可以先在 Chrome、Safari 等系统浏览器中提交同一份表单。如果系统浏览器能够稳定打开,只有 WebView 出现白屏,就需要重点检查客户端容器配置。

4. 表单内容被修改

支付宝 SDK 通常会返回一段可以直接输出并提交的 HTML 表单。不要自行解析、拼接或重新编码其中的字段,否则可能改变以下内容:

  • sign
  • biz_content
  • return_url
  • notify_url
  • 字符编码
  • 表单提交方式

签名或业务参数有误时,网关通常会返回明确的错误页面。不过在某些浏览器或异常链路中,也可能表现为页面没有正常渲染。

排查步骤

第一步:检查网关请求

在浏览器开发者工具的 Network 面板中找到发往 gateway.do 的请求,检查以下信息:

  • 请求方法是否为 POST;
  • HTTP 状态码;
  • 请求是否一直处于 Pending;
  • 响应中是否有 Location 头;
  • 响应正文是否包含支付宝错误码或错误信息;
  • 浏览器是否成功发起了对 mobileclientgw-sandbox.dl.alipaydev.com 的请求;
  • Console 中是否出现 CSP、跨域、证书或混合内容错误。

如果 gateway.do 一直没有响应,通常不是前端跳转代码造成的。如果网关已经返回重定向,但下一跳失败,应检查网络状况以及 WebView 对目标域名的处理。

第二步:保存并直接测试原始表单

服务端取得 SDK 返回值后,应将其原样输出。不要只提取网关 URL,也不要通过 Ajax 请求支付网关。

以 Java 为例:

AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
request.setReturnUrl(returnUrl);
request.setNotifyUrl(notifyUrl);
request.setBizContent(bizContent);

String form = alipayClient.pageExecute(request).getBody();

response.setContentType("text/html;charset=UTF-8");
response.getWriter().write(form);
response.getWriter().flush();

如果浏览器端通过接口取得表单,可以把完整表单写入页面后再提交:

const container = document.createElement('div');
container.innerHTML = formHtml;
document.body.appendChild(container);

const form = container.querySelector('form');
if (!form) {
  throw new Error('支付宝返回内容中未找到 form');
}

form.submit();

更稳妥的做法是由服务端直接返回 HTML 页面,减少 JSON 转义、前端模板过滤或 DOM 清洗对表单内容的影响。

不要使用下面这种方式:

fetch('https://openapi-sandbox.dl.alipaydev.com/gateway.do', {
  method: 'POST'
});

支付网关的跳转依赖浏览器页面导航。Ajax 请求可能受到跨域限制,也不能代替正常的表单提交。

第三步:核对环境配置

确认以下配置全部来自同一个沙箱环境:

  • 沙箱应用的 app_id;
  • 沙箱应用私钥;
  • 与私钥匹配的支付宝公钥或证书;
  • 网关地址;
  • 签名算法;
  • 字符集;
  • 沙箱买家账号。

典型的网关配置如下:

String gatewayUrl =
    "https://openapi-sandbox.dl.alipaydev.com/gateway.do";
String charset = "UTF-8";
String signType = "RSA2";

不要混用正式环境的 app_id、密钥、公钥或账号。具体参数应以当前支付宝开放平台控制台和所用 SDK 的配置方式为准。

第四步:排除 WebView 问题

可以按以下顺序进行对比测试:

  1. 电脑 Chrome 或 Edge;
  2. 手机系统浏览器;
  3. 手机移动网络;
  4. App 内置 WebView;
  5. 微信、企业应用等内置浏览器。

如果只有 WebView 无法打开,需要检查客户端的页面导航和新窗口处理。以 Android WebView 为例,至少要允许 JavaScript,并正确处理 URL 跳转:

webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setDomStorageEnabled(true);

webView.setWebViewClient(new WebViewClient() {
    @Override
    public boolean shouldOverrideUrlLoading(
            WebView view,
            WebResourceRequest request) {
        Uri uri = request.getUrl();

        if ("http".equals(uri.getScheme())
                || "https".equals(uri.getScheme())) {
            return false;
        }

        // 非 HTTP(S) 地址可能用于唤起外部应用。
        // 是否允许以及如何处理,应结合客户端安全策略实现。
        return true;
    }
});

这段代码只是通用排查示例,并不表示所有支付宝跳转都应该在 WebView 内部处理。实际接入方式仍需遵循当前支付宝 H5 支付文档和客户端安全要求。

第五步:记录可定位的信息

出现白屏时,记录以下内容:

  • 发生时间;
  • out_trade_no;
  • 使用的网络和浏览器;
  • gateway.do 的状态码与耗时;
  • 完整的重定向链路;
  • 支付宝响应中的错误码、sub_code 和 sub_msg;
  • SDK 日志和网关返回内容。

不要在日志或截图中公开应用私钥、完整签名、用户隐私信息或敏感支付参数。

如何判断责任环节

可以根据具体表现缩小排查范围:

现象优先排查方向
gateway.do 一直 Pending沙箱服务、DNS、代理或网络链路
gateway.do 返回 4xx 或错误页面请求参数、签名、应用配置
已返回 302,下一跳失败收银台域名访问、Cookie、网络或 WebView
系统浏览器正常,App 内白屏WebView 配置及 URL 跳转处理
同一表单偶发成功沙箱稳定性或网络波动
每次都稳定失败配置、签名、表单处理或运行容器问题

解决建议

如果表单、签名和环境配置均已确认无误,而且白屏只在沙箱中偶发,可以尝试:

  • 更换网络,并使用系统浏览器验证;
  • 不在支付跳转链路中使用代理、抓包证书或内容过滤插件;
  • 保持 SDK 返回的表单原样提交;
  • 间隔一段时间后重新进行沙箱联调;
  • 使用新的订单号测试,避免重复订单状态影响判断;
  • 保存失败时间、请求链路和订单号,交由支付宝技术支持核查;
  • 上线前在正式环境完成全流程验证,但不能用正式环境代替尚未完成的参数和签名检查。

注意事项

return_url 只负责支付完成后的前端跳转,不能单独作为支付成功的依据。返回页面没有打开,不代表订单一定没有支付。成功跳回业务页面,也不能证明支付一定成功。

支付结果应以服务端异步通知为主。业务系统完成验签,并校验应用标识、商户订单号、金额和订单状态后,才能更新业务数据。必要时,还可以调用订单查询接口确认结果。沙箱页面白屏和异步通知属于两条不同的链路,需要分别排查。

备注:内容仅供参考。