支付宝沙箱环境创建支付订单报 504 Gateway Time-out
结论
这是支付宝沙箱网关返回的 HTTP 504 Gateway Time-out。它表示网关未能在规定时间内收到上游服务的响应。返回内容是 Tengine 生成的 HTML 页面,并非支付宝开放平台正常返回的 JSON,说明问题出现在业务响应生成之前,通常与签名、订单参数等常规接口校验无关。
不过,一次 504 并不能说明沙箱已经关闭。常见原因有:
- 沙箱服务暂时异常或负载过高;
- 使用了过期、错误或不稳定的网关地址;
- 本地网络、代理、DNS 或出口链路异常;
- 请求已经受理,但响应在网关处超时;
- 使用动态版本 SDK,导致运行时加载的实现发生变化。
如果同一份代码此前可以正常使用,近期也没有改过参数和密钥,但换到多个网络环境后仍持续返回 504,那么沙箱服务异常的可能性较高。
为什么不像业务参数错误
正常情况下,即使 app_id、签名、密钥或业务参数有误,支付宝网关也会返回结构化的 JSON,例如:
{
"alipay_trade_precreate_response": {
"code": "40004",
"msg": "Business Failed",
"sub_code": "...",
"sub_msg": "..."
}
}
当前收到的却是:
<h1>504 Gateway Time-out</h1>
<hr/>Powered by Tengine
这说明客户端已经连接到支付宝沙箱入口,但入口在等待上游服务时超时了。这段 HTML 不能按支付宝业务错误码解析。
日志中的服务器节点:
openapi-14.rz21a.sandbox.alipay.net
只能说明请求到达了某个沙箱网关节点,无法证明订单一定没有创建成功。
建议的排查顺序
1. 核对沙箱网关地址
通过支付宝开放平台当前提供的沙箱配置或 SDK 常量确认网关地址,不要照搬第三方示例中的历史地址。
常见的沙箱网关形式为:
https://openapi-sandbox.dl.alipaydev.com/gateway.do
优先使用 HTTPS。不要将网关地址替换成响应里显示的内部节点域名,也不要直接请求:
openapi-14.rz21a.sandbox.alipay.net
这是网关内部节点信息,不是应用应当配置的接口地址。
2. 检查基础网络和代理
先测试域名解析和 TLS 连接:
curl -v --connect-timeout 10 \
https://openapi-sandbox.dl.alipaydev.com/gateway.do
这一步不要求得到成功的支付响应,主要检查:
- 域名能否正确解析;
- TCP 和 TLS 能否建立连接;
- 请求是否经过公司代理、VPN 或安全网关;
- 收到的是支付宝页面、代理错误页,还是连接超时。
然后分别使用本机、服务器和其他网络出口测试。如果只有某个环境失败,优先检查该环境的 DNS、代理、防火墙和出口 IP。
3. 检查 SDK 与网关配置
日志中有以下内容:
alipay_sdk=alipay-sdk-java-dynamicVersionNo
如果项目使用动态版本,或者没有锁定依赖版本,需要确认运行时实际加载的 SDK 版本,并在生产构建中锁定明确版本。不能只根据这个参数断定 SDK 有问题,但要排除依赖在业务代码未修改时发生变化的情况。
Java 客户端配置可参考以下结构:
AlipayClient alipayClient = new DefaultAlipayClient(
"https://openapi-sandbox.dl.alipaydev.com/gateway.do",
appId,
merchantPrivateKey,
"json",
"UTF-8",
alipayPublicKey,
"RSA2"
);
重点检查:
appId是否属于当前沙箱应用;- 商户私钥是否与沙箱应用配置的公钥匹配;
- 验签时使用的是否是支付宝公钥,而不是应用公钥;
sign_type为RSA2时,是否使用对应的 RSA2 密钥;- 字符集是否统一为
UTF-8; - 是否混用了正式环境和沙箱环境的应用、账号或密钥。
这些配置错误通常会触发 JSON 格式的业务错误,而不是 504,但排查时仍需要逐项确认。
4. 用最小参数重新发起预创建请求
排查时先去掉不必要的扩展参数,只保留创建订单所需的核心字段:
AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
model.setOutTradeNo("TEST_" + System.currentTimeMillis());
model.setTotalAmount("0.01");
model.setSubject("沙箱支付测试");
request.setBizModel(model);
AlipayTradePrecreateResponse response = alipayClient.execute(request);
if (response.isSuccess()) {
System.out.println("qrCode=" + response.getQrCode());
} else {
System.err.println("code=" + response.getCode());
System.err.println("msg=" + response.getMsg());
System.err.println("subCode=" + response.getSubCode());
System.err.println("subMsg=" + response.getSubMsg());
System.err.println("body=" + response.getBody());
}
如果最小请求依然稳定返回 HTML 504,而不是支付宝 JSON,基本可以排除 biz_content 中复杂业务参数引起的问题。
超时后不要直接生成新订单
504 只表示客户端没有及时收到响应,不代表支付宝一定没有处理请求。如果直接更换 out_trade_no 重试,可能会创建多笔业务订单。
可以按以下流程处理:
- 保存本次请求使用的
out_trade_no; - 收到 504 后,通过
alipay.trade.query查询订单; - 如果查到订单,按查询结果继续处理;
- 确认查不到订单后,再使用原
out_trade_no进行有限次数的重试; - 为重试设置间隔和次数上限。
查询示例:
AlipayTradeQueryRequest queryRequest = new AlipayTradeQueryRequest();
AlipayTradeQueryModel queryModel = new AlipayTradeQueryModel();
queryModel.setOutTradeNo(outTradeNo);
queryRequest.setBizModel(queryModel);
AlipayTradeQueryResponse queryResponse =
alipayClient.execute(queryRequest);
if (queryResponse.isSuccess()) {
System.out.println("tradeStatus=" + queryResponse.getTradeStatus());
} else {
System.err.println("subCode=" + queryResponse.getSubCode());
System.err.println("subMsg=" + queryResponse.getSubMsg());
}
遇到网络超时时,可以采用简单的退避方式,例如等待 2 秒、5 秒和 10 秒后重试,但不能无限重试。
回调地址也需要单独检查
示例中的通知地址是:
https://jmicro.cn/jmpay/wx/notify
路径中包含 wx 不一定有问题。但如果这个接口实际处理的是微信支付回调,就需要换成支付宝专用的回调地址。
notify_url 需要满足以下条件:
- 可以从公网访问;
- HTTPS 证书有效;
- 不要求登录或额外鉴权;
- 能正确处理支付宝异步通知;
- 验签成功后返回纯文本
success; - 不与微信支付的签名验证和报文格式混用。
通知地址无法访问通常不会直接导致 alipay.trade.precreate 的同步请求返回 504,但错误的回调配置会影响后续支付状态更新,因此也要检查并修正。
如何判断是沙箱侧故障
如果符合以下情况,可以按沙箱服务异常向支付宝开放平台支持渠道提交问题:
- 使用的是当前有效的官方沙箱网关;
- HTTPS、DNS 和本地网络均正常;
- 在不同机器或不同网络出口都能复现;
- 最小请求仍返回同一类 HTML 504;
- 问题持续发生,并非单次偶发;
- 正式环境或其他支付宝接口链路正常;
- 请求始终没有收到支付宝 JSON 响应。
提交问题时可以提供:
- 发生时间和时区,例如
2025-06-02 15:36:20 Asia/Shanghai; - API 名称:
alipay.trade.precreate; - 沙箱
app_id; - HTTP 状态码;
- 完整响应体;
- 网关响应中的服务器节点;
- SDK 名称和实际版本;
- 是否能通过其他网络复现。
不要提交应用私钥、完整密钥文件或其他敏感凭据。虽然通常无法通过请求 URL 中的签名值反推出私钥,但公开日志时仍应对 sign、订单号、用户信息和回调参数做脱敏处理。
最终处理建议
先把网关明确配置为当前官方提供的 HTTPS 沙箱地址,再使用固定版本的 SDK 和最小订单参数复测。收到 504 时,应将请求结果视为”未知”:先调用 alipay.trade.query 核实订单状态,再决定是否重试。
如果多个网络环境持续返回相同的 Tengine 504 页面,客户端无法修复支付宝上游的超时。此时应保存发生时间、接口名称、节点和响应内容,并提交给支付宝开放平台排查。沙箱环境通常达不到正式环境的稳定性,因此业务代码也需要处理超时查询、幂等控制和有限重试。
备注:内容仅供参考。
