支付宝手机网页支付 Demo 中 quit_url 和 product_code 如何配置?
结论
支付宝手机网页支付 Demo 通常调用 alipay.trade.wap.pay 接口:
product_code是销售产品码。手机网站支付应使用固定值QUICK_WAP_WAY。quit_url是用户在支付宝收银台中途取消或退出支付时返回的商户页面地址,需要填写完整且可访问的 URL。- 配置正确并发起请求后,商户服务端会生成用于跳转到支付宝收银台的表单。服务端需要将该表单返回给手机浏览器并自动提交,才能进入支付流程。
- 能否直接唤起支付宝 App,取决于浏览器环境、手机系统、支付宝客户端是否安装以及支付宝收银台的处理策略。支付宝不能保证每次都直接打开 App,有时会继续使用 H5 收银台完成支付。
两个参数分别有什么作用
product_code
product_code 用于标识当前交易使用的支付宝产品。手机网站支付一般配置为:
QUICK_WAP_WAY
这个值不是商品编号,也不是商户自行定义的产品 ID。调用 alipay.trade.wap.pay 时,不应填入商品 SKU、订单号或应用名称。
示例:
{
"product_code": "QUICK_WAP_WAY"
}
quit_url
quit_url 是用户在支付过程中主动退出时返回的地址,可以填写订单确认页或订单详情页,例如:
https://www.example.com/order/12345
quit_url 只处理退出收银台后的页面跳转,不代表支付成功,也不能作为修改订单状态的依据。
它与另外两个常见 URL 参数的用途不同:
| 参数 | 作用 |
|---|---|
quit_url | 用户中途退出支付时返回的页面 |
return_url | 支付完成后,浏览器前台跳回商户页面的地址 |
notify_url | 支付宝服务端异步通知商户的地址 |
判断订单是否支付成功,应以 notify_url 收到的异步通知为准,必要时还要主动查询交易结果,不能只看浏览器是否跳转到了 return_url。
Demo 的基本使用步骤
1. 准备应用和签名配置
至少要正确配置以下信息:
- 支付宝应用
app_id - 商户应用私钥
- 支付宝公钥,或证书模式对应的证书
- 签名算法,常见为
RSA2 - 支付宝网关地址
- 字符集,通常为
UTF-8 return_urlnotify_url
沙箱环境和正式环境的应用、网关、密钥及账号配置不能混用。正式发起交易前,还需要确认应用已经具备手机网站支付能力。具体开通条件以对应支付宝开放平台应用的实际配置为准。
2. 组装支付业务参数
下面是 Java SDK 的常见写法:
AlipayClient alipayClient = new DefaultAlipayClient(
"https://openapi.alipay.com/gateway.do",
APP_ID,
APP_PRIVATE_KEY,
"json",
"UTF-8",
ALIPAY_PUBLIC_KEY,
"RSA2"
);
AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
request.setReturnUrl("https://www.example.com/pay/return");
request.setNotifyUrl("https://www.example.com/api/alipay/notify");
request.setBizContent("""
{
"out_trade_no": "ORDER_202609090001",
"total_amount": "99.00",
"subject": "测试商品",
"product_code": "QUICK_WAP_WAY",
"quit_url": "https://www.example.com/order/ORDER_202609090001"
}
""");
AlipayTradeWapPayResponse response = alipayClient.pageExecute(request);
if (response.isSuccess()) {
String form = response.getBody();
// 将 form 原样写入 HTTP 响应,使手机浏览器自动提交并进入支付宝收银台
} else {
// 记录 response.getCode()、response.getSubCode() 等错误信息
}
实际项目中,不要直接拼接含有用户输入的 JSON。可以使用 SDK 提供的业务模型,也可以通过可靠的 JSON 库序列化参数。
3. 将 SDK 返回内容写给浏览器
pageExecute 通常会返回一个可以自动提交的 HTML 表单。服务端必须将它作为页面响应输出给浏览器。例如,在 Servlet 中可以这样处理:
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write(alipayResponse.getBody());
response.getWriter().flush();
如果只在服务端调用接口、打印返回内容,或者把 HTML 当作普通字符串传给前端,支付宝收银台不会自动打开。用户当前使用的手机浏览器必须加载并提交这个表单。
会不会直接跳转到支付宝
正常配置后的典型流程如下:
用户点击支付
→ 商户服务端创建支付请求
→ 浏览器提交支付宝表单
→ 进入支付宝收银台
→ 根据终端环境使用支付宝 App 或 H5 页面支付
正常情况下,用户会进入支付宝支付流程,但不一定会直接唤起支付宝 App。实际情况可能是:
- 手机已安装支付宝,且当前浏览器允许唤起 App,可能会打开支付宝客户端。
- 手机未安装支付宝,通常会进入适用的网页支付流程或显示相应提示。
- 浏览器限制跳转到外部应用时,页面可能停留在 H5 收银台,需要用户继续操作。
- 微信等内置浏览器可能限制跳转到支付宝,并提示用户改用系统浏览器打开。
- 参数、签名或产品权限存在异常时,用户无法进入正常收银台,页面或接口会返回错误。
不要自行使用支付宝私有 URL Scheme 强制拉起客户端。跳转应由 alipay.trade.wap.pay 返回的官方收银台页面完成。
常见错误和注意事项
不要把 quit_url 当成支付结果地址
用户可以在没有完成支付的情况下返回 quit_url。这个页面只能用于恢复订单页面或提示用户重新支付,不能据此把订单状态改为 “已支付”。
不要依赖 return_url 更新订单
前台跳转可能被关闭、拦截或重复访问。订单状态应在服务端对 notify_url 通知验签通过后更新,并至少校验以下内容:
- 通知签名是否有效
app_id是否属于当前应用out_trade_no是否存在total_amount是否与订单金额一致seller_id是否符合预期- 交易状态是否为业务允许处理的状态
回调处理还需要保证幂等,防止重复通知造成重复发货或重复记账。
URL 应使用完整地址
建议使用完整的 HTTPS 地址:
https://www.example.com/pay/quit
不要填写相对路径:
/pay/quit
联调时,需要确认相关地址在对应访问方的网络环境中可以访问。尤其是 notify_url,支付宝服务器必须能够通过公网访问它,因此不能使用 localhost、127.0.0.1 或只能从内网访问的地址。
订单号必须唯一
out_trade_no 是商户订单号。如果重复使用已经创建过交易的订单号,同时又修改金额或商品信息,可能会造成交易冲突。订单号应由服务端生成并持久化。
金额必须由服务端确定
不要直接采用前端提交的 total_amount。服务端应根据商品、优惠和订单记录重新计算应付金额,再生成支付宝请求,防止用户篡改支付金额。
不要手工修改签名后的参数
请求生成后,如果再修改 biz_content、回调地址或其他参与签名的字段,会导致验签失败。所有参数都应先设置完成,再交给支付宝 SDK 生成签名和表单。
备注:内容仅供参考。
