PAYATHON 2026

支付宝沙箱这两天是否正在维护,支付成功后为何未回调?

支付小周

结论

仅凭“支付链接昨天不可用,今天支付成功但没有回调”,还不能判断支付宝沙箱正在维护。沙箱偶尔会出现不稳定或通知延迟,但没有官方公告时,不宜直接归因于平台维护。

既然支付已经成功,更应先检查异步通知地址 notify_url、公网网络、签名验证、接口响应和沙箱配置。建议先调用 alipay.trade.query 查询订单状态,再逐项检查回调链路。

为什么支付成功却没有回调

支付宝支付涉及两个容易混淆的地址:

  • return_url:支付完成后,用户浏览器跳转到这个地址,通常用于展示支付结果。
  • notify_url:支付宝服务器向这个地址发起 POST 请求,用于异步通知支付结果。

用户看到支付成功页面,只能说明浏览器完成了跳转,不能证明 notify_url 已经调用成功。常见原因有:

  1. 支付请求中没有正确传入 notify_url。
  2. 回调地址使用了 localhost、127.0.0.1 或局域网 IP,支付宝服务器无法访问。
  3. 域名、HTTPS 证书、端口、防火墙或反向代理配置有误。
  4. 回调接口发生重定向、处理超时或返回 HTTP 错误。
  5. 接口收到了通知,但验签失败,或者业务代码抛出了异常。
  6. 回调处理成功后,没有返回纯文本 success。
  7. 沙箱应用的 app_id、支付宝公钥、应用私钥或网关环境混用了。
  8. 订单号重复,或者业务系统已经处理过这笔订单。
  9. 沙箱通知出现延迟或临时异常。

排查步骤

1. 查询支付宝侧的订单状态

使用创建支付时的 out_trade_no 调用 alipay.trade.query。

重点检查这些字段:

  • trade_status
  • trade_no
  • out_trade_no
  • total_amount

如果查询结果是 TRADE_SUCCESS 或 TRADE_FINISHED,说明支付宝侧已经支付成功,接下来应检查异步通知链路。如果查询不到订单,需要确认应用、网关和订单号是否属于同一个沙箱环境。

订单查询也可以作为主动补偿手段,但不能完全代替异步通知。

2. 确认支付请求设置了 notify_url

以 Java SDK 为例:

AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();

request.setReturnUrl("https://example.com/pay/return");
request.setNotifyUrl("https://example.com/api/alipay/notify");

request.setBizContent("""
{
  "out_trade_no": "ORDER_202609090001",
  "total_amount": "0.01",
  "subject": "测试订单",
  "product_code": "FAST_INSTANT_TRADE_PAY"
}
""");

AlipayTradePagePayResponse response = alipayClient.pageExecute(request);

notify_url 必须是支付宝服务器可以直接访问的公网地址。该接口不能依赖浏览器登录状态,也不应要求额外的自定义请求头。

3. 从公网验证回调地址

至少需要确认:

  • 域名可以正常解析。
  • HTTPS 证书有效,证书链完整。
  • 回调路径允许 POST 请求。
  • 网关、防火墙和 WAF 没有拦截支付宝请求。
  • 接口不会自动跳转到登录页。
  • 服务可以在合理时间内完成处理。
  • Nginx、应用服务器和业务日志中是否出现过相关请求。

本地开发时,可以通过合规的内网穿透服务提供临时公网 HTTPS 地址。测试地址发生变化后,支付请求中的 notify_url 也要同步更新。

4. 正确读取参数并验签

支付宝异步通知通常通过表单参数提交,不能只按 JSON 请求体解析。

Spring Boot 示例:

@PostMapping(
    value = "/api/alipay/notify",
    produces = "text/plain;charset=UTF-8"
)
public String handleNotify(HttpServletRequest request) {
    Map<String, String> params = new HashMap<>();

    request.getParameterMap().forEach((key, values) -> {
        params.put(key, String.join(",", values));
    });

    try {
        boolean verified = AlipaySignature.rsaCheckV1(
            params,
            alipayPublicKey,
            "UTF-8",
            "RSA2"
        );

        if (!verified) {
            return "failure";
        }

        String appId = params.get("app_id");
        String outTradeNo = params.get("out_trade_no");
        String tradeNo = params.get("trade_no");
        String tradeStatus = params.get("trade_status");
        String totalAmount = params.get("total_amount");

        if (!expectedAppId.equals(appId)) {
            return "failure";
        }

        Order order = orderService.findByOrderNo(outTradeNo);
        if (order == null) {
            return "failure";
        }

        if (order.getAmount().compareTo(new BigDecimal(totalAmount)) != 0) {
            return "failure";
        }

        if ("TRADE_SUCCESS".equals(tradeStatus)
                || "TRADE_FINISHED".equals(tradeStatus)) {
            orderService.markPaidIdempotently(outTradeNo, tradeNo);
        }

        return "success";
    } catch (Exception e) {
        return "failure";
    }
}

验签使用的是支付宝公钥,不是应用公钥或应用私钥。沙箱和正式环境的密钥也要分别配置,不能混用。

5. 返回纯文本 success

业务处理成功后,响应体应直接返回:

success

不要返回:

{"code":200,"message":"success"}

也不要返回 HTML 页面、统一响应对象或包含其他说明的字符串。只有识别到符合要求的成功响应后,支付宝才会认为通知已经处理完成,否则可能按照平台机制重试。

建议增加的日志

可以在回调入口记录必要的诊断信息:

log.info(
    "Alipay notify received: outTradeNo={}, tradeNo={}, tradeStatus={}",
    params.get("out_trade_no"),
    params.get("trade_no"),
    params.get("trade_status")
);

生产日志中不要完整输出私钥、签名配置或其他敏感信息。建议分别记录:

  • 是否进入回调接口
  • 请求方法和 Content-Type
  • out_trade_no
  • trade_no
  • trade_status
  • 验签结果
  • 金额和应用 ID 的校验结果
  • 最终响应内容
  • 异常堆栈

如果 Web 服务器的访问日志中完全没有请求,问题更可能出在通知地址、公网网络或支付宝沙箱侧。如果有请求但业务状态没有更新,则应重点检查参数解析、验签和异常处理。

注意事项

回调处理必须具备幂等性。同一笔订单可能收到多次通知,系统不能因此重复发货、充值或记账。可以根据订单状态、out_trade_no 唯一约束或支付流水表实现幂等控制。

支付结果不能只依赖 return_url。浏览器跳转可能被关闭、拦截或伪造,最终状态应以验签通过的异步通知为主,同时结合 alipay.trade.query 主动核对。

如果公网地址、密钥和回调代码都已确认正常,订单查询也显示支付成功,但长时间没有收到任何通知请求,可以再检查支付宝开放平台公告和沙箱状态,或者向支付宝技术支持提交订单号、请求时间及 trade_no。得到官方确认前,应表述为“疑似沙箱通知异常”,不要直接认定支付宝正在维护。

备注:内容仅供参考。