Web 网站接入支付宝支付应调用哪个下单接口?
明确结论
Web 网站接入支付宝支付时,应根据页面场景选择接口:
- PC 端网页支付使用
alipay.trade.page.pay(电脑网站支付)。 - 手机浏览器 H5 支付使用
alipay.trade.wap.pay(手机网站支付)。
如果这里的 Web 网站是传统电脑端网站,通常使用 alipay.trade.page.pay。接口会返回一段支付表单。网站将表单输出到浏览器后,浏览器会跳转到支付宝收银台,由用户完成付款。
为什么使用这个接口
alipay.trade.page.pay 用于电脑浏览器中的网站支付。商户后端组装订单并完成签名,浏览器负责跳转到支付宝收银台。
支付流程通常是:
- 用户在网站确认订单。
- 网站后端创建本地订单。
- 后端调用
alipay.trade.page.pay。 - 后端将支付宝返回的 HTML 表单输出给浏览器。
- 浏览器自动提交表单,进入支付宝收银台。
- 支付宝通过
notify_url异步通知支付结果。 - 商户验签并核对订单信息,然后更新本地订单状态。
电脑网站支付一般不需要先调用 alipay.trade.precreate。该接口主要用于扫码支付等场景,通常返回二维码内容,并非电脑网站支付的首选接口。
接入步骤
1. 准备支付宝应用信息
先在支付宝开放平台创建应用,完成电脑网站支付或手机网站支付相关能力的签约和配置。通常要准备以下信息:
app_id- 应用私钥
- 支付宝公钥,或支付宝公钥证书
- 支付宝网关地址
- 异步通知地址
notify_url - 同步跳转地址
return_url
使用公钥模式还是证书模式,取决于应用当前的签名配置。
2. 在服务端创建订单
下单必须在服务端完成。不要将应用私钥、签名逻辑或其他敏感配置放入前端 JavaScript。
电脑网站支付通常需要以下业务参数:
{
"out_trade_no": "ORDER_202609090001",
"total_amount": "99.00",
"subject": "商品订单",
"product_code": "FAST_INSTANT_TRADE_PAY"
}
各参数含义如下:
out_trade_no是商户订单号,在商户侧应保持唯一。total_amount是订单金额,单位为元。subject是订单标题。product_code在电脑网站支付场景中通常为FAST_INSTANT_TRADE_PAY。
3. 调用电脑网站支付接口
下面是使用支付宝 Java SDK 的示意代码。SDK 类名和初始化方式可能会因 SDK 版本、公钥模式或证书模式而不同,请以项目的实际依赖为准。
AlipayClient alipayClient = new DefaultAlipayClient(
"https://openapi.alipay.com/gateway.do",
appId,
merchantPrivateKey,
"json",
"UTF-8",
alipayPublicKey,
"RSA2"
);
AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
request.setNotifyUrl("https://www.example.com/alipay/notify");
request.setReturnUrl("https://www.example.com/alipay/return");
request.setBizContent("""
{
"out_trade_no": "ORDER_202609090001",
"total_amount": "99.00",
"subject": "商品订单",
"product_code": "FAST_INSTANT_TRADE_PAY"
}
""");
AlipayTradePagePayResponse response = alipayClient.pageExecute(request);
if (response.isSuccess()) {
String form = response.getBody();
// 将 form 原样写入 HTTP 响应,让浏览器自动提交并跳转到支付宝收银台
} else {
// 记录错误码、错误信息和支付宝返回的请求标识
}
在 Web 控制器中,可以把返回内容直接写入响应:
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write(form);
response.getWriter().flush();
不要将返回的表单按普通 JSON 处理。pageExecute 返回的通常是浏览器可以直接提交的 HTML 表单。
手机 Web 页面怎么办
网站运行在手机浏览器中时,应使用:
alipay.trade.wap.pay
在 Java SDK 中,通常对应 AlipayTradeWapPayRequest。处理流程与电脑网站支付相近:
AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
request.setNotifyUrl("https://www.example.com/alipay/notify");
request.setReturnUrl("https://www.example.com/alipay/return");
request.setBizContent("""
{
"out_trade_no": "ORDER_202609090002",
"total_amount": "99.00",
"subject": "商品订单",
"product_code": "QUICK_WAP_WAY"
}
""");
AlipayTradeWapPayResponse response = alipayClient.pageExecute(request);
String form = response.getBody();
如果同一个网站同时支持 PC 端和移动端,可以由服务端根据业务入口选择接口,但不应只依赖容易伪造的 User-Agent。更稳妥的方式是设置明确的支付入口,并在订单中记录支付渠道。
支付结果处理
判断订单是否支付成功,应以支付宝的异步通知为准,不能只看 return_url 的同步跳转结果。用户付款后可能直接关闭页面,也可能因为网络问题无法正常跳回商户网站。
处理异步通知时,至少需要完成以下检查:
- 使用支付宝提供的验签方法验证签名。
- 核对
app_id是否属于当前应用。 - 核对
out_trade_no是否存在。 - 核对
total_amount是否与本地订单金额一致。 - 核对收款方信息是否正确。
- 根据
trade_status更新订单,并做好幂等处理。 - 处理成功后,按支付宝要求返回成功响应。
示意逻辑如下:
Map<String, String> params = getRequestParams(request);
boolean signVerified = AlipaySignature.rsaCheckV1(
params,
alipayPublicKey,
"UTF-8",
"RSA2"
);
if (!signVerified) {
response.getWriter().write("failure");
return;
}
String outTradeNo = params.get("out_trade_no");
String tradeStatus = params.get("trade_status");
String totalAmount = params.get("total_amount");
// 继续核对 app_id、订单金额、收款方等信息
// 使用事务或唯一约束保证重复通知不会重复发货
if ("TRADE_SUCCESS".equals(tradeStatus)
|| "TRADE_FINISHED".equals(tradeStatus)) {
markOrderPaidIdempotently(outTradeNo, totalAmount);
response.getWriter().write("success");
} else {
response.getWriter().write("success");
}
注意事项
- 私钥只能保存在服务端,不能出现在 HTML、JavaScript、移动端包或公开仓库中。
notify_url必须是支付宝服务器可以访问的公网地址,不能使用localhost。- 异步通知可能重复发送,因此更新订单、发货和发放权益都要支持幂等处理。
- 不要只根据同步跳转参数修改订单状态。
- 金额应使用十进制类型,或按最小货币单位存储,避免直接使用浮点数计算。
- 沙箱环境与正式环境的网关、应用信息和密钥配置不能混用。
- 二维码当面付业务应评估
alipay.trade.precreate。支付宝小程序或原生 App 应选择对应的产品接口,而不是alipay.trade.page.pay。 - 接口权限、产品签约状态和 SDK 调用方式可能调整。正式接入时,请以当前支付宝开放平台控制台和对应接口文档为准。
备注:内容仅供参考。
