支付宝支付完成页的“完成”按钮如何配置跳转 URL?
支付小周
结论
手机支付宝扫描付款码后显示的是支付宝客户端的收银台页面。页面底部的“完成”按钮由支付宝控制,普通商户不能为其设置自定义跳转 URL。
支付接口即使支持 return_url,该参数通常也用于电脑网站支付、手机网站支付等网页收银台场景,无法改变扫码支付完成页中“完成”按钮的行为。
原因
付款码一般通过当面付预下单接口生成,例如:
alipay.trade.precreate
用户扫码后,整个付款流程都在支付宝 App 内完成。支付结果页和页面按钮不属于商户页面,商户无法通过修改二维码内容、预下单参数或前端 JavaScript 来设置按钮的跳转地址。
需要区分以下两个参数:
notify_url:支付宝服务器向商户服务器发送异步通知的地址,用于确认支付结果。return_url:部分网页支付产品完成付款后的同步跳转地址,不能用于控制当面付完成页的按钮。
推荐实现方式
1. 创建订单并生成付款二维码
商户服务端调用 alipay.trade.precreate,把业务订单号写入 out_trade_no,再向用户展示接口返回的 qr_code。
AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
request.setNotifyUrl("https://example.com/api/alipay/notify");
request.setBizContent("""
{
"out_trade_no": "ORDER_202609090001",
"total_amount": "99.00",
"subject": "商品订单"
}
""");
AlipayTradePrecreateResponse response = alipayClient.execute(request);
if (response.isSuccess()) {
String qrCode = response.getQrCode();
// 将 qrCode 生成二维码并展示
}
其中,notify_url 是接收支付结果通知的地址,与“完成”按钮的跳转地址无关。
2. 通过异步通知更新订单状态
支付成功后,支付宝会向 notify_url 发送异步通知。商户服务端需要验证签名、金额、商户身份和订单状态,确认无误后再更新本地订单。
@PostMapping("/api/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, values[0]);
}
});
boolean verified = AlipaySignature.rsaCheckV1(
params,
ALIPAY_PUBLIC_KEY,
"UTF-8",
"RSA2"
);
if (!verified) {
return "failure";
}
String outTradeNo = params.get("out_trade_no");
String tradeStatus = params.get("trade_status");
String totalAmount = params.get("total_amount");
if ("TRADE_SUCCESS".equals(tradeStatus)
|| "TRADE_FINISHED".equals(tradeStatus)) {
// 还应核对 app_id、seller_id、订单金额以及订单当前状态
orderService.markPaid(outTradeNo, totalAmount);
}
return "success";
}
支付宝可能重复发送异步通知,因此更新订单的操作必须具备幂等性。不能只检查 trade_status 就直接发货。
3. 由自有页面检测支付结果并跳转
如果商户在自己的网页、收银台或设备页面上展示二维码,可以让该页面轮询自有服务端的订单状态。检测到支付成功后,再跳转到指定 URL。
const orderNo = "ORDER_202609090001";
const timer = setInterval(async () => {
const response = await fetch(
`/api/orders/${encodeURIComponent(orderNo)}/status`,
{ cache: "no-store" }
);
const result = await response.json();
if (result.status === "PAID") {
clearInterval(timer);
window.location.replace(
`/payment/success?orderNo=${encodeURIComponent(orderNo)}`
);
}
}, 2000);
这个跳转发生在商户自己的页面中,不会改变支付宝支付完成页的“完成”按钮。
如果必须让用户回到自有系统
可以根据具体的业务载体选择处理方式:
- 在二维码展示页提示用户,支付后返回原页面,页面会自动显示支付结果。
- 在支付完成后的订单通知、短信或商户消息中提供自有系统入口,同时遵守支付宝相关产品规则。
- 如果业务在支付宝小程序内运行,可以使用小程序支付能力,并在商户能够控制的小程序页面中处理支付成功后的跳转。具体能力和限制以接入产品的当前文档为准。
- 如果使用的是手机网站支付,而非当面付扫码支付,可以检查对应支付产品是否支持
return_url。即使支持,该参数也只对相应产品规定的同步返回流程生效。
注意事项
- 不要把自定义 URL 拼接到
qr_code中。qr_code是支付宝生成的支付链接,修改后可能导致付款失败。 - 不要将前端显示的“支付成功”作为最终入账依据。订单状态应以验签通过的异步通知或服务端主动查询结果为准。
notify_url必须是支付宝服务器可以访问的公网地址,不能使用localhost或只能从内网访问的地址。- 成功处理异步通知后,应按照接口要求返回
success,否则支付宝可能继续重试。 - 如果需要在支付后返回 App,应另行设计 App Link、Universal Link 或 URL Scheme。这些方案仍然不能替换支付宝原生完成页的按钮行为。
- 支付产品的参数和客户端行为可能发生调整。接入时应以当前所用产品的支付宝开放平台文档为准,不要把其他支付产品的
return_url参数套用到当面付扫码场景。
备注:内容仅供参考。
