支付宝H5支付中签约及扫码签约应使用哪个接口?
结论
alipay.trade.wap.pay 不支持”支付中签约”,追加自定义参数也无法实现这一能力。
H5 场景需要把支付和签约分成两个流程:
- H5 支付仍使用
alipay.trade.wap.pay。 - 代扣或周期扣款签约使用
alipay.user.agreement.page.sign。 - 用户扫码后可以直接进入签约页,但这仍是独立的签约流程,并非通过 WAP 支付接口完成支付中签约。
如果业务要求一次完成付款和签约,只能使用支付宝明确支持该能力的产品和支付接口。具体是否可用,取决于商户已经签约的支付宝产品,不能通过增加接口参数自行开启。
为什么 WAP 支付不能直接实现
支付和协议签约属于两类不同的能力:
alipay.trade.wap.pay用于创建手机网站支付交易。alipay.user.agreement.page.sign用于创建用户协议签约页面。- 后续代扣通常还需要开通相应的协议支付产品并取得接口权限。
有些客户端支付产品可能支持支付和签约的组合流程,但这不表示 WAP 支付支持相同参数。接口文档未声明的参数,即使提交,也不会让接口获得支付中签约能力。
爱奇艺等业务还可能使用需要单独准入或定制的产品能力,不能只根据页面表现判断其调用了哪个公开接口。
推荐实现流程
方案一:先签约,再支付
这种方案适合必须先取得代扣授权的业务:
- 服务端生成唯一的
external_agreement_no。 - 调用
alipay.user.agreement.page.sign。 - 把返回的签约页面输出到浏览器,由用户在支付宝侧确认。
- 服务端接收异步通知,并主动查询签约结果。
- 确认协议生效后,再调用
alipay.trade.wap.pay发起首笔支付。
方案二:先支付,再引导签约
如果首笔支付不依赖代扣协议,可以采用这种流程:
- 使用
alipay.trade.wap.pay完成首笔付款。 - 在支付成功页提示用户开通自动续费。
- 调用
alipay.user.agreement.page.sign,进入独立签约流程。 - 服务端确认签约成功后,再开通自动续费权益。
这种方式通常更容易接入现有的 H5 支付流程,但页面必须清楚展示扣款规则,不能把签约授权隐藏在普通支付按钮之后。
服务端调用示例
下面的代码只展示调用结构。personal_product_code、sign_scene、周期规则等参数必须填写商户已签约产品对应的实际值,不能直接使用示例中的占位符。
AlipayClient alipayClient = new DefaultAlipayClient(
gatewayUrl,
appId,
merchantPrivateKey,
"json",
"UTF-8",
alipayPublicKey,
"RSA2"
);
AlipayUserAgreementPageSignRequest request =
new AlipayUserAgreementPageSignRequest();
request.setBizContent("""
{
"external_agreement_no": "AGREEMENT_202609090001",
"personal_product_code": "<以已签约产品为准>",
"sign_scene": "<以产品配置为准>",
"sign_notify_url": "https://merchant.example.com/alipay/agreement/notify",
"return_url": "https://merchant.example.com/alipay/agreement/result",
"access_params": {
"channel": "<以当前产品支持的访问方式为准>"
},
"period_rule_params": {
"<按所签约产品的规则填写>": "<value>"
}
}
""");
AlipayUserAgreementPageSignResponse response =
alipayClient.pageExecute(request);
if (response.isSuccess()) {
// pageExecute 返回的 body 通常用于输出签约页面或跳转表单。
String pageBody = response.getBody();
} else {
throw new IllegalStateException(
response.getCode() + ": " + response.getSubMsg()
);
}
H5 页面不能直接使用商户私钥调用支付宝接口。服务端应先生成签约页面,再把页面内容返回给浏览器:
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write(pageBody);
扫码签约如何处理
扫码签约也应基于 alipay.user.agreement.page.sign 设计,具体接入方式则取决于已经开通的产品是否支持二维码访问渠道。
一般流程如下:
- 服务端创建签约请求。
- 通过产品支持的二维码访问方式生成签约入口。
- 把签约入口转换成二维码并展示。
- 用户使用支付宝扫码并确认协议。
- 服务端结合异步通知和签约查询,确认最终状态。
不要直接把 SDK 返回的自动提交 HTML 表单全文编码成二维码。二维码应包含可访问的签约地址,也可以指向商户自己的中转页,再由中转页通过服务端重新生成并输出签约表单。
如果当前产品文档没有列出二维码渠道参数,就不能自行猜测 access_params.channel 的枚举值。接入前需要确认商户签约的产品是否支持扫码签约,以及支付宝为该产品提供了哪种接入方式。
签约结果必须由服务端确认
用户跳回 return_url,只能说明浏览器完成了跳转,不能证明协议已经生效。业务系统需要:
- 验证异步通知签名。
- 检查应用、商户和协议编号是否匹配。
- 使用
external_agreement_no保证请求幂等。 - 必要时调用协议查询接口核实状态。
- 确认协议有效后,才能开启自动续费或代扣权益。
前端显示”签约成功”,不能作为后续扣款的唯一依据。
注意事项
- 能调用签约接口,不等于商户已经取得代扣权限。相关产品需要单独签约和准入。
personal_product_code、sign_scene和周期规则都与具体产品绑定,应以商户后台和当前官方接口文档为准。- H5 页面不能传递商户私钥,也不能由前端自行拼接支付宝签名。
- 签约编号应由服务端生成并持久化,避免重复签约。
- 页面应明确展示扣款金额或计算方式、扣款周期、服务内容和取消方式等信息。
- 如果业务要求真正的一步式”支付并签约”,应先确认目标支付接口是否明确支持组合签约参数。
alipay.trade.wap.pay不支持时,需要采用独立签约流程,不能通过尝试未声明的参数来实现。
备注:内容仅供参考。
