PAYATHON 2026

支付宝沙箱支付一直提示“请求超时,请稍后再试”如何解决?

支付老李

结论

支付宝沙箱页面反复提示 请求超时,请稍后再试,不代表业务服务器一定发生了超时。常见原因有:

  • 支付宝沙箱环境临时异常或正在维护
  • 请求发到了错误的网关
  • 沙箱应用、沙箱买家账号、密钥等配置混入了正式环境数据
  • 签名算法、字符集或请求参数有误
  • 本机网络、代理、防火墙或 DNS 造成连接异常
  • 支付页面链接被重复编码、截断或已经失效
  • 异步通知地址无法从公网访问

排查时,先确认错误发生在哪个阶段,再查看支付宝返回的原始响应。仅凭浏览器显示的 请求超时,无法判断具体原因。

一、先确定超时发生在哪个阶段

1. 调用支付接口时没有收到响应

如果服务端请求支付宝网关时发生连接超时,通常要检查网关地址、网络、代理和 TLS 连接。

沙箱网关应为:

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

正式环境网关通常为:

https://openapi.alipay.com/gateway.do

沙箱应用必须调用沙箱网关。应用 ID、密钥、支付宝公钥和买家账号也必须全部来自同一套沙箱环境。

2. 已跳转到支付宝页面,但页面提示请求超时

这通常说明请求已经到达支付宝。此时主要检查:

  • 支付表单或跳转 URL 是否完整
  • app_id 是否为当前沙箱应用的 AppID
  • sign 是否被重复进行 URL 编码
  • timestamp 格式是否正确
  • biz_content 是否为合法 JSON
  • 支付订单号是否被重复使用
  • 沙箱买家账号能否正常登录
  • 沙箱环境当时是否发生临时故障

3. 支付成功,但业务系统一直没有收到结果

这种情况可能与页面提示或支付接口本身没有直接关系,应检查:

  • notify_url 能否从公网访问
  • 地址是否使用了 localhost、127.0.0.1 或局域网 IP
  • 通知接口是否在规定时间内返回纯文本 success
  • 验签时是否使用了正确的支付宝公钥
  • 防火墙或 Web Application Firewall 是否拦截了支付宝通知

同步跳转使用的 return_url 不能替代异步通知。订单的最终状态应以异步通知或主动查询结果为准。

二、按顺序检查配置

1. 确认没有混用不同环境的配置

下面这些配置必须配套使用:

沙箱 AppID
应用私钥
与应用公钥对应的支付宝公钥
沙箱网关
沙箱买家账号

常见情况是使用了沙箱 AppID,却配置了正式环境的支付宝公钥。也可能是沙箱密钥已经重新生成,代码中仍保留着旧私钥。

还要分清以下三类密钥:

  • 应用私钥:由开发者保存,用于给请求签名
  • 应用公钥:上传到支付宝开放平台
  • 支付宝公钥:由支付宝提供,用于验证支付宝返回的内容

验签时不能用应用公钥代替支付宝公钥。

2. 检查 SDK 初始化参数

以 Java SDK 为例,基本配置如下:

AlipayClient alipayClient = new DefaultAlipayClient(
    "https://openapi-sandbox.dl.alipaydev.com/gateway.do",
    APP_ID,
    APP_PRIVATE_KEY,
    "json",
    "UTF-8",
    ALIPAY_PUBLIC_KEY,
    "RSA2"
);

逐项确认:

  • 网关为 openapi-sandbox.dl.alipaydev.com
  • APP_PRIVATE_KEY 是当前应用的私钥
  • ALIPAY_PUBLIC_KEY 是当前沙箱应用对应的支付宝公钥
  • sign_type 与密钥类型一致,通常使用 RSA2
  • 签名、发送和接收数据时使用相同的字符集

证书模式与普通公钥模式的初始化方式不同。不要混用应用证书、公钥证书和普通字符串公钥。

3. 检查支付请求参数

电脑网站支付可以参考下面的请求结构:

AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
request.setReturnUrl("https://example.com/alipay/return");
request.setNotifyUrl("https://example.com/alipay/notify");

request.setBizContent("""
{
  "out_trade_no": "TEST202609090001",
  "total_amount": "0.01",
  "subject": "沙箱支付测试",
  "product_code": "FAST_INSTANT_TRADE_PAY"
}
""");

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

需要检查:

  • out_trade_no 在商户系统中是否唯一
  • total_amount 是否为合法的金额字符串
  • subject 是否为空
  • 电脑网站支付是否使用了正确的 product_code
  • biz_content 是否为合法 JSON
  • 参数值在签名前后是否发生变化

手机网站支付、App 支付和电脑网站支付使用的 API 与 product_code 不完全相同。应按照实际接入产品的接口文档配置,不能直接套用其他支付产品的参数。

三、记录支付宝的原始响应

排查时不能只记录 支付失败。至少应保存:

  • 请求接口名称
  • app_id
  • out_trade_no
  • 请求时间
  • HTTP 状态码
  • SDK 返回的 code
  • sub_code
  • msg
  • sub_msg
  • 支付宝返回的 trace_id 或类似链路标识,如果响应中存在

Java 示例:

AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
request.setBizContent("""
{
  "out_trade_no": "TEST202609090001"
}
""");

AlipayTradeQueryResponse response = alipayClient.execute(request);

System.out.println("code=" + response.getCode());
System.out.println("msg=" + response.getMsg());
System.out.println("subCode=" + response.getSubCode());
System.out.println("subMsg=" + response.getSubMsg());
System.out.println("body=" + response.getBody());

不同版本的 SDK 可能提供不同的方法。如果没有对应的 getter,可以直接记录完整响应体。生产环境的日志不能输出私钥、完整签名或敏感账户信息。

接口返回了明确的业务错误时,应先根据 sub_code 和 sub_msg 处理。只有完全没有收到有效响应时,才应把网络超时作为重点排查方向。

四、检查本机到沙箱网关的网络

在部署应用的同一台机器上测试连接:

curl -I --connect-timeout 10 \
  https://openapi-sandbox.dl.alipaydev.com/gateway.do

返回内容不一定是有效的支付业务结果。只要 DNS 解析和 HTTPS 握手能够完成,通常就说明基础网络可以访问沙箱网关。

连接失败时,再检查 DNS:

nslookup openapi-sandbox.dl.alipaydev.com

同时确认:

  • 系统时间是否准确
  • HTTPS 证书是否被本地代理替换
  • 公司网络是否限制外部 HTTPS 请求
  • 应用进程是否设置了错误的 HTTP 代理
  • 容器或服务器的 DNS 是否正常
  • 防火墙是否阻断了目标域名或 443 端口

不要长期关闭 TLS 证书校验来解决连接问题。这样做有安全风险,还可能掩盖代理或证书链配置错误。

五、检查请求 URL 是否被破坏

如果应用生成的是自动提交表单,应将 SDK 返回的完整 HTML 直接输出给浏览器,不要再次拼接或编码:

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

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

常见问题有:

  • 对整个表单进行 URL 编码
  • 重复编码 sign 参数
  • 请求经过前端路由时丢失查询参数
  • 反向代理限制 URL 长度
  • 把 HTML 表单当成普通 URL 跳转
  • 模板引擎转义了表单中的特殊字符

可以在浏览器开发者工具中查看跳转请求,确认参数没有被截断或重复转义,也没有异常的 301/302 循环。

六、不要重复使用测试订单号

有些测试代码会把 out_trade_no 写死。前一次支付已经创建交易后,如果继续使用同一个订单号,却修改金额或商品名称,可能引起订单冲突,或者进入异常页面。

测试时可以为每次请求生成新的订单号:

String outTradeNo =
    "TEST" + java.time.format.DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS")
        .format(java.time.LocalDateTime.now());

数据库中仍应为订单号设置唯一约束。只使用时间戳不能保证高并发时绝对唯一,正式系统可以增加随机值,或者使用可靠的分布式 ID。

七、正确处理超时和未知状态

服务端调用超时,不代表支付宝一定没有创建交易。此时贸然重新提交业务,可能带来重复支付风险。

可以按下面的流程处理:

  1. 保存本地订单和请求状态。
  2. 调用支付接口。
  3. 收到明确的失败响应后,按照错误码处理。
  4. 如果连接超时或响应不完整,将订单标记为 支付结果未知。
  5. 使用 alipay.trade.query,按 out_trade_no 主动查询交易。
  6. 确认交易不存在后,再按照业务规则决定是否重新发起支付。
  7. 结合异步通知更新订单的最终状态。

不能因为页面显示 请求超时,就直接把订单状态改为支付失败。

八、排除沙箱环境自身的问题

如果配置、签名和网络都正常,但多个不同订单在不同浏览器中仍然出现相同提示,可以继续做交叉验证:

  • 重新登录沙箱买家账号
  • 清除支付宝沙箱页面的 Cookie 和缓存
  • 使用无痕窗口或其他浏览器测试
  • 更换网络后测试
  • 重新创建一笔订单,不要刷新旧支付页面
  • 查看支付宝开放平台当时是否发布了维护或故障提示
  • 间隔一段时间后再次测试

沙箱环境主要用于联调,稳定性不一定与真实生产环境完全相同。如果只有支付宝托管页面报错,接口又没有返回明确错误码,应保留错误发生时间、AppID、订单号、完整响应和页面截图,再向支付宝技术支持反馈。不能根据沙箱页面偶发的一次超时,就认定正式环境也会发生相同问题。

注意事项

  • 私钥不能提交到前端、代码仓库或公开日志。
  • 异步通知必须验签,并核对 app_id、商户订单号、金额和交易状态。
  • 不能把浏览器同步跳转作为判断支付成功的唯一依据。
  • 不要无限重试支付创建接口。
  • 排查时应保留原始响应,不要只记录二次封装后的异常信息。
  • 沙箱和正式环境的配置应通过环境变量或独立配置文件隔离,避免发布时混用。
  • 如果错误只出现在特定 SDK 或框架中,还要检查代理、超时、字符编码和参数序列化设置。具体配置项取决于所用语言、SDK 版本和部署方式。

备注:内容仅供参考。