total_payments 设为 3 后是否会自动解约?
结论
不能把 total_payments=3 理解为成功扣款 3 次后协议一定会自动解约。
该参数表示商户最多可以依据这份协议成功扣款 3 次。达到上限后,商户不能再继续成功扣款,但这不等于协议状态会自动变为已解约。仅从 total_payments 的参数说明,无法判断支付宝是否会自动执行解约。
如果业务规定协议必须在第三次扣款成功后终止,商户应主动查询协议状态,并按照当前开放平台文档调用解约接口,不能根据扣款次数推断协议已经解约。
原因
total_payments 限制的是成功扣款次数。例如:
total_payments = 3
其含义通常是:
- 第 1 次成功扣款后,累计成功 1 次;
- 第 2 次成功扣款后,累计成功 2 次;
- 第 3 次成功扣款后,达到次数上限;
- 此后不能再依据该协议成功扣款。
参数说明只限定了成功扣款次数,没有明确说明达到上限后会同步修改协议状态,也没有说明系统会自动发送解约通知。因此,业务系统需要分别记录以下两个状态:
扣款额度是否已经用完
协议是否已经解约
协议仍然存在但不能继续扣款,与协议已经正式解约,是两种不同的状态。
建议的处理方式
1. 签约时保存协议标识
通过 alipay.user.agreement.page.sign 完成签约后,保存支付宝返回的协议号和签约状态。后续查询、扣款及解约都应使用真实的协议标识,不能只根据本地扣款次数关联协议。
签约参数示意:
{
"product_code": "实际产品码",
"personal_product_code": "实际个人产品码",
"sign_scene": "实际签约场景",
"total_payments": 3
}
具体必填字段以商户当前所用产品的开放平台文档为准。
2. 只统计最终成功的扣款
商户应结合支付宝返回结果和异步通知确认扣款是否成功,不能在请求发出后就增加成功次数。
伪代码示例:
PaymentResult result = executePayment(agreementNo);
if (result.isSuccess()) {
int successCount = paymentRepository.countSuccessfulPayments(agreementNo);
if (successCount >= 3) {
agreementRepository.markPaymentLimitReached(agreementNo);
stopCreatingNewPaymentRequests(agreementNo);
}
}
实际系统还应根据支付宝交易号或商户订单号进行幂等处理,防止重复通知造成重复计数。
3. 查询真实协议状态
成功扣款达到 3 次后,通过支付宝提供的协议查询能力核实协议状态。如果当前产品支持 alipay.user.agreement.query,可以使用协议号查询。具体请求字段和状态枚举以当前接口文档为准。
逻辑示意:
AgreementStatus status = queryAgreementStatus(agreementNo);
if (status.isEffective()) {
// 协议可能仍有效,但扣款次数已经达到上限
stopCreatingNewPaymentRequests(agreementNo);
} else if (status.isTerminated()) {
agreementRepository.markTerminated(agreementNo);
}
不要因为本地记录的 successCount == 3,就直接将支付宝侧的协议状态标记为已解约。
4. 业务需要明确终止时主动解约
如果业务规则要求第三次成功扣款后立即终止协议,应在确认该笔扣款成功后,调用适用于当前产品的解约接口。部分签约产品使用 alipay.user.agreement.unsign,但该接口是否适用以及需要传入哪些参数,仍应以对应产品和当前版本的接口文档为准。
处理流程可以设计为:
收到扣款成功通知
↓
进行订单幂等校验
↓
统计该协议的成功扣款次数
↓
次数达到 3
↓
停止发起后续扣款
↓
查询支付宝侧协议状态
↓
如协议仍有效且业务要求终止,则调用解约接口
↓
根据解约结果或通知更新本地状态
注意事项
total_payments限制的是成功扣款次数,不是扣款请求次数。失败、处理中或关闭的交易不能直接计入成功次数。- 第三次扣款成功后是否会自动改变协议状态,应以该签约产品的最新接口文档和实际返回状态为准,不能仅根据参数名称判断。
- 如果参数说明没有明确退款后是否恢复可扣款次数,不要自行假设。可以向支付宝技术支持确认,或在沙箱及测试商户环境中验证。
- 扣款通知可能重复送达,本地计数必须进行幂等处理。
- 即使支付宝侧会阻止超过上限的扣款,商户也应在本地停止生成新的扣款请求,以免产生无效请求和异常告警。
- 解约是独立的业务动作。如果必须确保协议终止,应检查解约接口的响应及后续协议状态,不能只记录已发起解约。
备注:内容仅供参考。
