alipay.trade.wap.pay 是否支持周期扣款?
结论
alipay.trade.wap.pay(手机网站支付接口 2.0)不能直接用于周期扣款。
这个接口用于手机浏览器中的单次收银台支付。每笔交易都需要用户进入支付宝收银台并确认付款。周期扣款采用另一套流程:用户先签署扣款协议,商户再按照协议主动发起后续扣款。
如果支付宝当前的周期扣款文档只列出了 alipay.trade.app.pay,就应按照文档要求,通过 App 支付流程完成签约,不能直接将接口名替换为 alipay.trade.wap.pay。
为什么不能直接使用手机网站支付
周期扣款通常分为两个阶段:
- 用户签署周期扣款协议。
- 商户按照协议约定的周期、金额和条件发起后续扣款。
alipay.trade.wap.pay 只能创建一次手机网站支付,并返回支付宝收银台页面。商户重复调用这个接口,并不会因此获得后续免确认扣款的权限。
下面这种做法无法实现真正的周期扣款:
定时任务
-> 调用 alipay.trade.wap.pay
-> 生成新的支付页面
-> 等待用户再次确认付款
它只是定期创建普通订单,每次仍要由用户确认付款,不属于协议扣款。
推荐处理方式
1. 确认商户是否已开通周期扣款产品
周期扣款通常不是普通支付接口默认包含的能力。接入前,需要在支付宝开放平台或商户后台确认:
- 商户所属行业是否允许接入;
- 应用是否已签约相应产品;
- 当前应用类型是否支持周期扣款;
- 签约、解约、协议查询和扣款分别使用哪些接口;
- 扣款周期、金额和通知方式有哪些限制。
接口和参数应以应用后台当前显示的官方文档为准。产品方案、所属行业和签约权限不同,具体要求也可能不同。
2. 按周期扣款文档完成用户签约
如果官方接入文档要求使用 alipay.trade.app.pay 完成签约,就需要在原生 App 中调起支付宝客户端,不能继续使用 WAP 收银台。
服务端调用结构可以写成:
AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
// bizContent 中除了普通订单信息,还需要加入周期扣款签约所需参数。
// 参数名称、嵌套结构和可选值必须以当前周期扣款产品文档为准。
request.setBizContent(bizContent);
AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
if (!response.isSuccess()) {
throw new IllegalStateException(
response.getCode() + ": " + response.getSubMsg()
);
}
// 将 response.getBody() 返回给 App,由 App 调用支付宝 SDK。
String orderString = response.getBody();
不要照着普通 App 支付示例猜测周期、签约场景或协议参数。缺少必要的产品权限时,即使请求格式正确,也可能无法完成签约。
3. 保存并核验签约结果
签约完成后,服务端应根据支付宝返回的结果或异步通知保存协议标识,并建立协议与业务用户之间的对应关系。
建议至少记录:
业务用户编号
商户侧协议编号
支付宝协议标识
协议状态
签约时间
解约时间
最近一次状态核验时间
不能只看到客户端返回“支付成功”,就认定签约已经成功。客户端结果可能被中断或伪造,最终状态应通过服务端通知或官方查询接口核验。
4. 使用周期扣款产品指定的扣款接口
后续扣款需要使用周期扣款文档指定的接口,并携带有效的协议信息。不要在定时任务中再次调用 alipay.trade.wap.pay。
伪代码示例:
Agreement agreement = agreementRepository.findByUserId(userId);
if (agreement == null || !agreement.isEffective()) {
throw new IllegalStateException("用户尚未签约或协议已失效");
}
String outTradeNo = orderService.createUniqueTradeNo();
DeductResult result = cyclePayService.deduct(
agreement.getAgreementNo(),
outTradeNo,
amount
);
if (result.isAccepted()) {
orderService.markProcessing(outTradeNo);
} else {
orderService.markFailed(outTradeNo, result.getErrorCode());
}
这里的 cyclePayService.deduct 只是业务层示意,并不是支付宝接口名称。实际使用的扣款 API、协议字段和金额限制,应以已开通产品的官方文档为准。
只有 H5 网站时怎么办
如果业务只有 H5 页面,没有原生 App,而周期扣款文档明确要求通过 alipay.trade.app.pay 完成签约,那么现有接入形态通常不能直接使用这套方案。
可考虑以下处理方式:
- 继续使用
alipay.trade.wap.pay,每期生成账单,由用户主动付款; - 增加原生 App,通过
alipay.trade.app.pay完成签约; - 向支付宝技术支持确认,当前商户是否可以使用面向 H5 的独立签约产品或页面签约方案。
在取得对应产品权限和官方接入说明之前,不应把普通 WAP 支付包装成“自动续费”或“免密周期扣款”。
注意事项
- 用户签约前,应清楚展示扣款金额、周期、扣款条件和解约方式。
- 协议签约成功不代表每次扣款都会成功,还要处理余额不足、协议失效和风控拦截等情况。
- 异步通知必须验签,同时校验应用、商户、订单号、金额和协议信息。
- 每期扣款订单号必须唯一,并做好接口重试和业务幂等。
- 用户解约后,应立即停止创建新的扣款任务。
- 不要通过定时重复调用
alipay.trade.wap.pay模拟自动扣款,这个接口仍要求用户逐笔确认。
备注:内容仅供参考。
