芝麻GO与免押开通页合并签约代扣应如何选择?
明确结论
每期扣款成功通知并不由“芝麻GO”或“免押开通页合并签约代扣”的开通页面统一回调,而是由实际执行扣款的支付接口发出。
如果使用 alipay.trade.pay 扣款,需要在每次请求的公共参数中传入 notify_url。支付宝会将该笔交易的异步通知发送到这个地址。收到通知后,应完成验签,检查 trade_status,并核对订单金额等信息。
选择方案时,可以按以下原则判断:
- 如果业务只有免押授权、代扣签约和后续按期扣款,通常选择“免押开通页合并签约代扣”更直接。
- 如果业务需要芝麻GO完整的先享、履约、结算或营销体系,而且符合芝麻GO的准入要求,再选择芝麻GO。
- 不要根据“哪个方案提供扣款回调”来选择。无论使用哪种方案,最终都要根据实际扣款接口的异步通知和主动查询结果确认支付状态。
具体能够使用哪些产品和扣款接口,取决于商户的签约权限、行业准入条件,以及支付宝为应用开通的能力。请以商户后台和相应接口文档为准。
为什么开通文档里没有每期扣款回调
“免押开通页合并签约代扣”主要完成两项操作:
- 用户进行免押授权。
- 用户签署代扣协议。
这一步得到的是授权和签约结果,并不会同时创建以后每一期的支付订单。后续扣款通常由商户系统根据账单周期主动发起,例如:
用户完成签约
↓
商户保存 agreement_no 等签约信息
↓
账单到期
↓
商户创建唯一 out_trade_no
↓
调用实际扣款接口
↓
支付宝向该次请求的 notify_url 发送交易通知
所以,在“如何接入开通页”章节中找不到每期扣款地址是正常的。要确认扣款回调的配置方式,应查看实际使用的支付接口,而不是签约页面接口。
以下几个地址也需要区分:
return_url:用户完成页面操作后,浏览器跳转回商户页面的地址。- 签约结果通知:用于确认协议是否签署成功。
notify_url:支付交易结果的服务端异步通知地址。
不能根据页面跳转结果判断扣款是否成功。
每期扣款通知如何配置
假设后续通过 alipay.trade.pay 发起协议扣款,可以在每次请求中设置 notify_url。Java SDK 的典型结构如下,具体字段应以商户当前开通产品所对应的接口文档为准:
AlipayTradePayRequest request = new AlipayTradePayRequest();
// 每笔扣款的异步通知地址
request.setNotifyUrl("https://api.example.com/alipay/payment/notify");
AlipayTradePayModel model = new AlipayTradePayModel();
model.setOutTradeNo("BILL_202609_000001");
model.setSubject("2026年9月服务费");
model.setTotalAmount("99.00");
model.setProductCode("CYCLE_PAY_AUTH");
AgreementParams agreementParams = new AgreementParams();
agreementParams.setAgreementNo("用户签约后取得的协议号");
model.setAgreementParams(agreementParams);
request.setBizModel(model);
AlipayTradePayResponse response = alipayClient.execute(request);
示例中的 product_code、协议参数,以及商户能否使用 alipay.trade.pay,都要根据实际开通的代扣产品确定,不能直接照搬。
如果实际使用的扣款接口不提供 notify_url,应按照该接口文档规定的通知机制处理,并通过订单查询接口补偿确认交易结果。
回调处理示例
支付宝的异步通知通常使用表单参数。服务端收到通知后,应先验签,再核对订单,最后进行幂等处理:
@PostMapping("/alipay/payment/notify")
public String handleNotify(HttpServletRequest request) throws Exception {
Map<String, String> params = new HashMap<>();
request.getParameterMap().forEach((key, values) -> {
if (values != null && values.length > 0) {
params.put(key, String.join(",", values));
}
});
boolean verified = AlipaySignature.rsaCheckV1(
params,
alipayPublicKey,
"UTF-8",
"RSA2"
);
if (!verified) {
return "failure";
}
String outTradeNo = params.get("out_trade_no");
String tradeNo = params.get("trade_no");
String tradeStatus = params.get("trade_status");
String totalAmount = params.get("total_amount");
String appId = params.get("app_id");
String sellerId = params.get("seller_id");
// 必须从数据库读取订单,并核对:
// 1. out_trade_no 是否存在
// 2. total_amount 是否与订单金额一致
// 3. app_id 和 seller_id 是否属于当前商户
// 4. 订单是否已经处理,防止重复入账
if ("TRADE_SUCCESS".equals(tradeStatus)
|| "TRADE_FINISHED".equals(tradeStatus)) {
// 使用事务或唯一约束进行幂等更新
markBillPaid(outTradeNo, tradeNo, totalAmount);
}
// 只有验签、核对和业务落库全部成功后才能返回 success
return "success";
}
回调地址需要满足以下条件:
- 使用公网可访问的 HTTPS 地址。
- 不依赖用户登录状态或浏览器 Cookie。
- 不执行页面跳转。
- 业务处理成功后返回纯文本
success。 - 业务处理失败时返回
failure或其他非成功响应,让支付宝按照相应机制重试。
推荐的完整处理方式
1. 保存签约结果
用户完成签约后,保存协议号、签约状态、用户标识和产品相关参数。签约成功仅表示用户已经授权代扣,不代表任何一期账单已经支付。
2. 为每一期生成独立订单
每期账单都要使用唯一的 out_trade_no,例如:
BILL_{userId}_{billingPeriod}
同一笔账单重试时应继续使用原订单号,以免发生重复扣款。
3. 发起协议扣款
使用签约后取得的协议标识,调用商户实际获准使用的扣款接口,并为该次请求配置 notify_url。
4. 同时处理同步结果和异步通知
同步响应只能用于判断请求是否已被受理,不能直接当作最终扣款结果。确认最终状态时,需要综合以下信息:
- 支付宝异步通知;
- 交易查询接口;
- 商户本地订单状态。
5. 增加主动查询补偿
网络故障可能导致回调未能及时到达。订单长时间停留在“处理中”状态时,应调用相应的交易查询接口主动确认结果。
如果扣款接口是 alipay.trade.pay,通常可以通过 alipay.trade.query,按 out_trade_no 查询:
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
AlipayTradeQueryModel model = new AlipayTradeQueryModel();
model.setOutTradeNo("BILL_202609_000001");
request.setBizModel(model);
AlipayTradeQueryResponse response = alipayClient.execute(request);
查询接口的使用方式同样以实际产品文档和商户权限为准。
两种方案如何选择
适合免押开通页合并签约代扣的情况
如果业务流程如下:
用户获得免押资格
→ 同时签署代扣协议
→ 商户按月、按次或按账单主动扣款
通常可以优先选择免押开通页合并签约代扣。这种方式能减少用户分别完成免押授权和代扣签约的操作,但账单管理、扣款时机、失败重试和对账仍由商户系统负责。
适合芝麻GO的情况
如果业务需要芝麻GO提供的完整“先享后付”产品闭环,包括特定履约规则、芝麻GO订单体系、营销入口或平台侧结算能力,则应选择芝麻GO。
芝麻GO并不是专门用于提供代扣回调地址的产品。能否接入还取决于行业、业务模式和商户准入条件。
注意事项
- 签约成功和扣款成功是两个不同的状态,必须分别保存。
- 不要将
return_url用作支付结果通知地址。 - 回调可能重复发送,处理逻辑必须保证幂等。
- 即使验签成功,也要核对
app_id、seller_id、out_trade_no和total_amount。 - 不要只依赖异步通知,还应建立主动查询和对账补偿机制。
- 扣款失败后不能无限重试,需要设置重试次数、间隔和终止条件。
- 协议解约、失效或用户授权状态发生变化后,应停止创建新的扣款请求。
- 如果商户后台没有相应的代扣产品权限,即使接口参数正确也无法正常扣款,需要先确认产品签约和应用授权状态。
备注:内容仅供参考。
