如何将 alipay.trade.page.pay 改为 alipay.trade.wap.pay?
结论
不能在表单生成后直接把 alipay.trade.page.pay 替换为 alipay.trade.wap.pay,也不能在不调整参数的情况下安全切换。
这两个接口分别用于电脑网站支付和手机网站支付。订单号、金额、标题等核心业务参数可以复用,但至少要做以下调整:
- 将接口方法改为
alipay.trade.wap.pay - 将
product_code改为QUICK_WAP_WAY - 按手机网站支付的要求提供
quit_url - 根据修改后的完整请求重新计算签名
- 确认支付宝应用已经开通手机网站支付能力
如果只修改返回表单中的 method 字段,原签名会立即失效,支付宝通常会返回验签失败或参数错误。
为什么不能直接替换方法名
支付宝请求中的 method、biz_content 等字段都会参与签名。例如,将:
method=alipay.trade.page.pay
改为:
method=alipay.trade.wap.pay
待签名字符串就已经发生变化,原来的 sign 无法继续匹配。因此,不能直接对平台返回的 HTML 表单做字符串替换。
两个接口使用的产品参数也不同:
| 项目 | 电脑网站支付 | 手机网站支付 |
|---|---|---|
| API | alipay.trade.page.pay | alipay.trade.wap.pay |
product_code | FAST_INSTANT_TRADE_PAY | QUICK_WAP_WAY |
| 典型使用环境 | PC 浏览器 | 手机浏览器、H5 页面 |
| 退出地址 | 通常不使用 quit_url | 通常需要 quit_url |
out_trade_no、total_amount、subject 等订单数据可以保持不变,但整个参数集合不能原样照搬。
正确的改造方式
不要修改已经生成的表单。应当在调用支付宝 SDK 之前,根据客户端环境选择相应的请求类和 API。
基本流程如下:
- 保留原有的订单号、金额和商品标题等业务数据。
- 手机端改用
AlipayTradeWapPayRequest。 - 将
product_code设置为QUICK_WAP_WAY。 - 配置
return_url、notify_url和quit_url。 - 通过支付宝 SDK 重新生成支付表单。
- 将生成的表单原样输出到浏览器。
服务端异步通知的处理逻辑通常可以继续复用,但仍要验证支付宝签名,并核对订单号、金额、商户身份和订单状态。
Java 示例
下面是支付宝 Java SDK 的常见调用方式。不同 SDK 版本的类名和字段设置方法可能略有差异,应以项目当前使用的依赖为准。
AlipayClient alipayClient = new DefaultAlipayClient(
gatewayUrl,
appId,
merchantPrivateKey,
"json",
"UTF-8",
alipayPublicKey,
"RSA2"
);
AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
request.setNotifyUrl(notifyUrl);
request.setReturnUrl(returnUrl);
AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
model.setOutTradeNo(outTradeNo);
model.setTotalAmount(totalAmount);
model.setSubject(subject);
model.setProductCode("QUICK_WAP_WAY");
model.setQuitUrl(quitUrl);
request.setBizModel(model);
// pageExecute 会生成用于浏览器跳转的 HTML 表单
String form = alipayClient.pageExecute(request).getBody();
输出表单时,不要转义其中的 HTML:
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write(form);
response.getWriter().flush();
原来的电脑网站支付代码可能类似:
AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
AlipayTradePagePayModel model = new AlipayTradePagePayModel();
model.setOutTradeNo(outTradeNo);
model.setTotalAmount(totalAmount);
model.setSubject(subject);
model.setProductCode("FAST_INSTANT_TRADE_PAY");
改造时需要把 AlipayTradePagePayRequest 换成 AlipayTradeWapPayRequest,再重新构造对应的业务参数,而不是替换表单里的字符串。
PHP 示例
如果平台允许修改支付宝 SDK 的调用层,可以把请求对象切换为手机网站支付请求:
$aop = new AopClient();
$aop->gatewayUrl = 'https://openapi.alipay.com/gateway.do';
$aop->appId = $appId;
$aop->rsaPrivateKey = $merchantPrivateKey;
$aop->alipayrsaPublicKey = $alipayPublicKey;
$aop->signType = 'RSA2';
$request = new AlipayTradeWapPayRequest();
$bizContent = [
'out_trade_no' => $outTradeNo,
'total_amount' => $totalAmount,
'subject' => $subject,
'product_code' => 'QUICK_WAP_WAY',
'quit_url' => $quitUrl,
];
$request->setBizContent(
json_encode($bizContent, JSON_UNESCAPED_UNICODE)
);
$request->setNotifyUrl($notifyUrl);
$request->setReturnUrl($returnUrl);
$result = $aop->pageExecute($request, 'POST');
echo $result;
不要采用下面这种处理方式:
// 错误做法:修改后签名将不再匹配
$form = str_replace(
'alipay.trade.page.pay',
'alipay.trade.wap.pay',
$form
);
平台接口无法修改时怎么办
如果第三方平台只提供已经签名的 alipay.trade.page.pay 表单,又不开放支付方法和业务参数配置,就无法在平台外部将它可靠地转换为 alipay.trade.wap.pay。
可以采用以下方式处理:
- 请平台增加手机网站支付通道。
- 使用平台提供的自定义支付接口或支付宝参数配置功能。
- 在自己的服务端直接接入
alipay.trade.wap.pay。 - 如果平台支持回调式下单,可以让平台只负责生成订单,再由自己的服务端发起支付请求。
不要把商户私钥交给前端,也不建议通过解析并重新签署第三方表单来绕过平台限制。这样容易造成参数不一致,还可能影响平台的订单状态、回调校验和对账流程。
注意事项
不能仅凭速度选择接口
alipay.trade.page.pay 和 alipay.trade.wap.pay 的主要区别在于使用场景,并不是简单的性能等级之分。实际跳转速度还会受到网络、浏览器、设备、支付宝客户端的唤起方式和服务端响应时间影响。
PC 页面应优先使用电脑网站支付,手机 H5 页面更适合手机网站支付。如果需要按终端自动选择接口,可以在创建支付请求前判断业务入口,但关键业务逻辑不能只依赖容易伪造的 User-Agent。
订单号不能重复发起不同金额的交易
切换支付接口后,out_trade_no 仍要符合商户订单号的唯一性要求。对于已经创建或支付成功的订单,不应修改金额后使用同一个订单号再次提交。
return_url 不能代替异步通知
浏览器跳转到 return_url 只能用于展示支付结果,不能作为判断订单支付成功的唯一依据。订单状态应以服务端收到并验证通过的 notify_url 异步通知为准,必要时还要主动查询交易状态。
必须重新签名
以下任一内容发生变化,都要由服务端重新生成请求和签名:
method
biz_content
return_url
notify_url
timestamp
不要在前端修改支付宝表单中的隐藏字段,也不要继续使用电脑网站支付请求生成的 sign。
先确认产品权限
应用能够调用 alipay.trade.page.pay,不代表它一定有权调用 alipay.trade.wap.pay。切换前,应在对应的支付宝应用和商户账号中确认手机网站支付产品已经开通,并检查网关环境、应用 ID、密钥和支付宝公钥的配置是否一致。
备注:内容仅供参考。
