是否有 alipay.trade.page.pay 前置模式 Demo 或文档?
结论
alipay.trade.page.pay 通常采用前置页面跳转。商户服务端调用接口生成支付宝收银台表单,把表单 HTML 返回给浏览器后自动提交。一般不需要,也不建议把支付宝收银台嵌入商户自己的 iframe。
官方 Demo 通常使用 pageExecute 生成表单并完成跳转,没有单独提供所谓的“iframe 前置模式”接口。如果合同、开放平台控制台或当前产品文档明确支持 iframe 模式,应按对应产品文档接入。否则,不要假定 alipay.trade.page.pay 能够在 iframe 中稳定运行。
推荐接入流程
完整流程如下:
- 用户在商户网站确认订单。
- 浏览器请求商户服务端的支付接口。
- 商户服务端创建
AlipayTradePagePayRequest。 - 服务端调用
pageExecute,获取自动提交的 HTML 表单。 - 浏览器提交表单,顶层页面跳转到支付宝收银台。
- 用户完成支付后,支付宝向
notify_url发送异步通知。 - 商户验签并核对订单信息,再更新订单状态。
return_url只负责同步跳转和结果展示,不能作为确认支付成功的最终依据。
流程可以简化为:
商户页面
↓ 创建支付
商户服务端
↓ 返回自动提交表单
支付宝收银台
↓ 用户完成支付
notify_url → 商户服务端确认支付结果
return_url → 浏览器展示支付结果
Java 示例
下面是 Java SDK 的典型调用方式。该示例只用于说明调用结构。SDK 依赖版本、网关地址和证书配置,应以商户当前的开放平台配置为准。
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
public class AlipayPagePayDemo {
public static String createPayForm() throws AlipayApiException {
AlipayClient alipayClient = new DefaultAlipayClient(
"https://openapi.alipay.com/gateway.do",
"YOUR_APP_ID",
"YOUR_APP_PRIVATE_KEY",
"json",
"UTF-8",
"ALIPAY_PUBLIC_KEY",
"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"
}
""");
return alipayClient.pageExecute(request).getBody();
}
}
Web 接口需要把生成的表单直接返回给浏览器:
@GetMapping(
value = "/pay",
produces = "text/html;charset=UTF-8"
)
@ResponseBody
public String pay() throws AlipayApiException {
return AlipayPagePayDemo.createPayForm();
}
浏览器收到的通常是一段包含 <form> 和自动提交脚本的 HTML。不要按 JSON 解析,也不要对内容进行 HTML 转义,否则表单可能无法正常提交。
如果业务页面必须保留
可以通过新窗口或顶层页面打开支付入口:
<form action="/pay" method="get" target="_blank">
<button type="submit">支付宝支付</button>
</form>
也可以直接从当前页面跳转:
window.location.href = "/pay";
如果当前页面处于 iframe 中,需要跳出 iframe,可以使用:
window.top.location.href = "/pay";
这种方式要求父页面没有通过沙箱限制阻止顶层跳转。如果 iframe 设置了 sandbox,还要确认其配置是否允许顶层导航。
为什么不建议直接使用 iframe
支付宝收银台涉及登录、风控、扫码、短信验证和跨域跳转。使用 iframe 时可能出现以下问题:
- 收银台页面不允许嵌入第三方页面;
- 浏览器限制第三方 Cookie;
- 扫码或登录后的跨域跳转失败;
- iframe 的
sandbox或安全策略阻止表单提交; - 移动端和桌面端的行为不一致;
- 用户难以判断当前页面是否为真实的支付宝收银台。
即使 iframe 在某些环境中暂时能够显示,也不能说明这种方式稳定或受到官方支持。
异步通知处理要点
确认支付结果应以 notify_url 为主要入口。收到通知后,至少需要完成以下处理:
- 使用支付宝公钥验签;
- 核对
app_id; - 核对
out_trade_no; - 核对
total_amount; - 检查
trade_status; - 确保订单更新具有幂等性;
- 处理成功后,按协议返回成功响应。
不能因为浏览器跳转到了 return_url,就直接把订单改为已支付。用户可能关闭页面,网络也可能中断,而且同步参数不能代替服务端验签。
如果异步通知尚未到达,可以由服务端调用交易查询接口核实状态。不要让前端持有应用私钥,也不要让前端直接调用需要签名的开放接口。
注意事项
out_trade_no必须在商户系统中保持唯一。- 金额应由服务端根据订单计算,不能直接采用前端传入的值。
- 私钥只能保存在服务端,不能写入 JavaScript 或 HTML。
- 正式环境和沙箱环境的网关、应用配置及密钥不能混用。
notify_url必须能够被支付宝服务器通过公网访问。- 回调地址不能依赖登录状态、浏览器 Cookie 或前端页面。
- 证书模式和公钥模式的初始化代码不同,需要与应用实际使用的签名配置一致。
- 如果必须使用 iframe,应先查阅当前商户产品文档,或向支付宝技术支持确认该能力是否已对相关应用开放,再按官方提供的专用流程接入。
备注:内容仅供参考。
