PAYATHON 2026

App支付成功后如何配置支付宝异步回调地址?

支付阿杰

明确结论

支付宝 App 支付的异步回调地址由 notify_url 指定。商家后端调用 alipay.trade.app.pay 创建支付订单时,需要把这个地址传给支付宝。它不需要在 App 中配置,也不需要单独提供支付完成后的网页。

使用支付宝 Java SDK 时,可以通过 AlipayTradeAppPayRequest#setNotifyUrl() 设置:

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

支付完成后,支付宝服务器会向这个地址发送异步通知。

配置步骤

1. 准备公网回调接口

后端需要提供一个支付宝服务器可以访问的 HTTP 或 HTTPS 地址,例如:

https://api.example.com/alipay/notify

该接口不能使用 localhost、127.0.0.1 或局域网 IP。测试环境同样需要支持公网访问。

2. 创建 App 支付订单时设置 notify_url

下面以支付宝 Java SDK 为例:

AlipayClient alipayClient = new DefaultAlipayClient(
        "https://openapi.alipay.com/gateway.do",
        appId,
        merchantPrivateKey,
        "json",
        "UTF-8",
        alipayPublicKey,
        "RSA2"
);

AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();

AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
model.setOutTradeNo("ORDER_202609090001");
model.setSubject("商品订单");
model.setTotalAmount("99.00");
model.setProductCode("QUICK_MSECURITY_PAY");

request.setBizModel(model);
request.setNotifyUrl("https://api.example.com/alipay/notify");

AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);

if (response.isSuccess()) {
    // 将 orderString 返回给 App,由 App 调起支付宝客户端
    String orderString = response.getBody();
} else {
    // 根据实际日志和错误码处理下单失败
    throw new IllegalStateException(
            response.getCode() + ": " + response.getSubMsg()
    );
}

notify_url 是请求级参数,不应放入 biz_content。后端生成的 orderString 已包含调用支付宝所需的签名信息,App 只需使用该字符串调起支付。

3. 接收并验证异步通知

支付宝会以表单参数的形式向 notify_url 发起请求。后端收到通知后,必须先验签,再处理订单:

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

    request.getParameterMap().forEach((key, values) -> {
        if (values != null && values.length > 0) {
            params.put(key, String.join(",", values));
        }
    });

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

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

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

    // 1. 根据 outTradeNo 查询本地订单
    // 2. 核对 app_id、seller_id、订单金额等信息
    // 3. 判断 trade_status
    // 4. 以幂等方式更新订单状态
    // 5. 保存支付宝交易号 tradeNo

    if ("TRADE_SUCCESS".equals(tradeStatus)
            || "TRADE_FINISHED".equals(tradeStatus)) {
        // 只有业务处理成功后才返回 success
        return "success";
    }

    return "failure";
}

不同版本的支付宝 SDK 可能使用不同的类名和异常类型,但处理流程相同:获取原始通知参数,使用支付宝公钥验签,核对订单信息,再以幂等方式更新业务状态。

为什么不需要回调页面

App 支付有两类结果:

  • App 端支付结果:用于提示用户支付操作是否结束,不能作为后端确认到账的唯一依据。
  • 支付宝异步通知:支付宝服务器会直接请求商家的 notify_url,后端据此确认支付结果并更新订单状态。

所以,“不需要回调页面”不代表”不需要回调地址”。App 支付通常不依赖浏览器跳转使用的 return_url,但仍应配置服务器异步通知地址 notify_url。

注意事项

  • notify_url 必须能从公网访问,不能要求用户登录,也不能依赖浏览器 Cookie 或 Session。
  • 回调接口应尽快处理请求并返回纯文本 success。只有验签、订单校验和业务更新全部成功后,才能返回 success。
  • 支付宝可能重复发送通知,因此订单更新必须具备幂等性,避免重复发货或重复充值。
  • 不能只根据 trade_status 更新订单,还要核对 out_trade_no、app_id、seller_id 和 total_amount 等字段。
  • 验签需要使用支付宝公钥,不能使用应用公钥或商家私钥。
  • 不要信任 App 客户端上传的”支付成功”状态。客户端结果可以用于界面展示,最终状态应以验签通过的异步通知或服务端主动查询结果为准。
  • 如果没有收到通知,可以调用支付宝交易查询接口主动查询订单状态,作为补偿机制。
  • 沙箱环境和生产环境应分别使用各自对应的网关、应用配置、密钥及回调地址。

备注:内容仅供参考。