PAYATHON 2026

支付宝电脑版扫码支付成功但未收到异步通知

支付老李

结论

最常见的原因是:支付请求没有传入 notify_url,或该地址无法由支付宝服务器通过公网访问。

商家后台配置的某些“回调地址”可能用于授权、应用网关等场景,并不会自动成为支付接口的异步通知地址。以电脑网站支付 alipay.trade.page.pay 为例,发起支付时需要明确设置 notify_url。

浏览器能正常跳转支付,或用户可以手动打开通知地址,都不能证明支付宝服务器能够访问该地址。

优先检查支付请求

发起电脑网站支付时,需要同时设置:

  • return_url:支付完成后,浏览器同步跳转的地址。
  • notify_url:支付宝服务器主动调用的异步通知地址。

Java SDK 示例:

AlipayClient alipayClient = new DefaultAlipayClient(
    gatewayUrl,
    appId,
    merchantPrivateKey,
    "json",
    "UTF-8",
    alipayPublicKey,
    "RSA2"
);

AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();

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

request.setBizContent("""
{
  "out_trade_no": "ORDER_202609090001",
  "total_amount": "99.00",
  "subject": "订单支付",
  "product_code": "FAST_INSTANT_TRADE_PAY"
}
""");

AlipayTradePagePayResponse response = alipayClient.pageExecute(request);
String paymentForm = response.getBody();

如果使用其他语言或自行组装请求,也要确认最终提交给支付宝的公共请求参数中确实包含:

notify_url=https://www.example.com/alipay/notify

除了检查项目配置文件,还要记录实际发出的请求参数,确认代码分支、环境变量或 SDK 封装没有覆盖 notify_url。

检查通知地址是否真正可用

异步通知由支付宝服务器发起,通常使用 POST 表单提交。通知地址需要满足以下条件:

  1. 必须是可通过公网访问的完整 URL,不能使用:
localhost
127.0.0.1
192.168.x.x
10.x.x.x
  1. 域名解析正确,服务器可以通过公网访问。
  2. HTTPS 证书有效,证书链完整且没有过期。
  3. 接口不依赖浏览器登录状态、Cookie 或验证码。
  4. 请求不会被防火墙、WAF、CDN、反向代理或 IP 白名单拦截。
  5. 地址不会跳转到登录页,也不会发生 HTTP 到 HTTPS 或其他地址的重定向。
  6. 接口允许支付宝发送 POST 请求,而非只接受浏览器的 GET 请求。

“手动访问没有问题”通常只能说明浏览器的 GET 请求正常。可以从公网环境模拟一次表单请求:

curl -i -X POST \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  --data 'out_trade_no=test&trade_status=TRADE_SUCCESS' \
  https://www.example.com/alipay/notify

该请求只能用于检查网络、路由和请求处理,不能代替支付宝签名验证。

正确处理异步通知

通知接口需要读取支付宝提交的全部表单参数,然后完成验签和业务校验。处理成功后,响应体必须是以下纯文本:

success

Java Servlet 风格示例:

@PostMapping("/alipay/notify")
@ResponseBody
public String notify(HttpServletRequest request) {
    Map<String, String> params = new HashMap<>();

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

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

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

        String appIdFromNotify = 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");
        String sellerId = params.get("seller_id");

        // 必须校验 app_id、seller_id、订单金额和订单号。
        // 更新订单时要保证幂等,防止重复通知造成重复记账。
        if ("TRADE_SUCCESS".equals(tradeStatus)
                || "TRADE_FINISHED".equals(tradeStatus)) {
            // 查询本地订单并核对金额、商户身份
            // 原子地更新订单状态
        }

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

不要先读取请求体,再用不兼容的方式解析参数,否则参与验签的参数可能不完整。验签时使用支付宝公钥,不要使用应用公钥或商户私钥。

排查服务器是否收到请求

先在通知接口的最外层记录访问日志,包括:

  • 请求时间
  • HTTP 方法
  • 请求路径
  • 请求参数名称
  • HTTP 状态码
  • 异常信息
  • 请求处理耗时

不要把敏感字段和完整签名直接写入公开日志。

可以根据日志快速判断问题所在:

  • 完全没有访问记录:检查实际支付请求中的 notify_url,以及公网连通性、DNS、证书、防火墙和网关路由。
  • 有访问记录,但业务没有更新:检查验签、参数解析、订单号、金额校验和事务处理。
  • 收到多次通知:接口可能没有及时、准确地返回纯文本 success,也可能在处理过程中超时或发生异常。
  • 返回 301、302、401、403、404、405、500:根据状态码检查重定向、鉴权、路由、请求方法或服务器异常。

通知接口的响应应尽量简单:

HTTP/1.1 200 OK
Content-Type: text/plain; charset=UTF-8

success

不要返回:

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

也不要返回 HTML 页面、额外空格、调试信息或统一响应对象。

确认交易是否真实成功

浏览器显示“支付成功”或跳转到 return_url,不能作为最终入账依据。应使用商户订单号调用订单查询接口,例如:

alipay.trade.query

需要核对:

  • out_trade_no 是否与本地订单一致;
  • 交易状态是否已经成功;
  • total_amount 是否一致;
  • app_id 和收款方身份是否属于当前商户;
  • 发起支付与接收通知是否使用同一套应用和环境配置。

如果订单查询结果显示未支付、交易已关闭,或订单号不是预期值,就不会产生预期的成功通知。

容易忽略的配置问题

还需要检查以下情况:

  • 沙箱环境与正式环境的配置混用;
  • 实际运行节点仍在使用旧配置;
  • 多台服务器中只有部分节点配置了通知路由;
  • notify_url 中的查询参数没有正确编码;
  • 网关只放行 GET,没有放行 POST;
  • CSRF 中间件拦截了支付宝请求;
  • 通知接口要求 Bearer Token、Session 或登录状态;
  • Web 应用部署路径发生变化,导致通知地址返回 404;
  • 接口处理时间过长,尚未返回 success 就已超时;
  • 验签字符集或签名类型与请求不一致。

推荐的处理顺序

  1. 打印并核对发起支付时实际使用的 notify_url。
  2. 确认该地址属于当前应用和当前运行环境。
  3. 从外部网络发送 POST 请求,检查状态码和响应内容。
  4. 查看 Web 服务器、反向代理、WAF 和应用日志。
  5. 使用 alipay.trade.query 核实交易的真实状态。
  6. 收到通知后完成验签、商户身份校验、金额校验和幂等更新。
  7. 业务处理成功后,只返回纯文本 success。

异步通知可能重复发送,也可能延迟到达,因此订单系统不能只依赖单次通知。更稳妥的做法是以异步通知为主,并提供主动查询补偿机制,同时保证订单更新具有幂等性。

备注:内容仅供参考。