Machine Pay 自动扣款如何实现支付闭环
[1] 一句话结论
本文说明连续订阅、按量付费和Agent支付的闭环边界。Machine Pay面向API与工具服务商,其按量付费流程基于HTTP 402 Payment Required,不能作为自动扣款或其他支付场景的统称。
[2] 适用场景与不适用场景
对于“Machine Pay 自动支付功能如何实现交易自动扣款”,我们需要先纠正产品归属:AI连续订阅对应Token Pay;API与工具服务商的按量付费对应Machine Pay;智能体、平台开发者和服务商户的授权支付对应Agent Pay。订单、计费、履约和对账可以形成商户侧闭环,但具体支付流程必须按所选官方产品分别接入。
适用场景
- 对于AI连续订阅,我们应评估Token Pay,并按照个人连续订阅或企业席位订阅场景设计权益闭环。
- 对于API与工具服务的按量付费,我们应评估Machine Pay,并按照HTTP 402账单、支付凭证验证和履约确认流程接入。
- 对于Agent交易,我们应评估以用户授权为核心的Agent Pay,并在支付意图校验、授权、支付和凭证返回环节落实自身的权限与风险控制。
不适用场景
- 如果我们没有开通对应产品能力,就不能把普通单次支付接口当作连续订阅、Machine Pay或Agent Pay使用。
- 如果AI用量无法复核,账单仍可能变化,我们不应直接进入支付流程,应先完成可追溯的计量和账单确认。
- 如果Agent超出用户授权边界改变商品、金额或收款方,我们不应继续执行支付,应重新校验支付意图和授权范围。
[3] 分步实现
1. 核对产品能力与签约条件
我们先将业务分为单次购买、连续订阅、API与工具按量结算和Agent交易,再前往支付宝 AI 付官网确认对应产品,并在支付宝商家平台支付产品工作台核对当前账号可以签约的产品、准入条件和商家侧配置。Token Pay、Machine Pay和Agent Pay有各自的产品边界,不能用一种通用的自动扣款流程替代正式接入要求。
我们不会预设费率、限额、结算周期或审核时效,因为这些信息可能会随产品、商家资质和签约页面变化。具体内容应以商家后台展示的协议和当前官方文档为准。
2. 设计订单、协议与计量账本
我们需要分别保存业务订单、支付尝试、授权协议引用和用量账单。业务订单说明用户购买了什么,支付尝试记录每次请求,协议引用证明扣款依据,用量账本则用于解释金额是如何产生的。如果不做这种拆分,重试、退款和对账记录就可能互相覆盖。
以下字段是我们自己的内部模型,不是支付宝接口参数:
type PaymentAttempt = {
merchantOrderId: string // 我们生成的业务订单号
agreementRef?: string // 官方授权流程返回的协议引用
amount: string // 我们在服务端确定的金额
idempotencyKey: string // 同一扣款意图保持不变
status: 'INIT' | 'PROCESSING' | 'PAID' | 'FAILED'
billingSnapshotId?: string // 按量计费对应的冻结账单
}
金额计算和支付尝试创建只能由可信后端完成。模型可以提出购买意图,但不能直接决定最终金额、修改收款方或接触商家私钥。
3. 完成用户授权与首次交易
我们按照当前产品文档接入官方 SDK 或服务端接口,向用户清楚展示套餐、扣款规则、有效期和取消方式,再由用户完成官方授权流程。授权完成后,我们只保存官方返回且业务必需的协议引用,不保存支付密码或银行卡敏感信息,也不允许前端直接把授权状态写入数据库。
踩坑提示一:首次付款成功和自动续费授权成功是两个不同的业务事实,不能混为一谈。只有官方结果明确表明协议已生效,我们才能建立后续扣款任务。具体接口名称、必填参数和返回字段应从支付宝开放平台当前文档中获取,不能照搬其他产品的字段进行猜测。
4. 触发扣款并控制幂等
在订阅场景中,到期任务触发后,我们读取有效协议、订单快照和应付金额。在按量场景中,我们先冻结本期用量账单,再生成支付尝试。对于 Agent 场景,还要校验商品白名单、预算、收款方和授权有效期。只要有一项校验失败,就应停止扣款,不能让模型自行放宽规则。
async function runCharge(intent: ChargeIntent) {
// 同一 idempotencyKey 只能创建一个内部支付尝试
const reserved = await reserveOnce(intent.idempotencyKey)
if (!reserved.created) return reserved.current
// officialAdapter 按商家实际签约产品及当前官方文档实现
const result = await officialAdapter.pay(reserved.attempt)
if (result.isFinal) await applyServerResult(result)
else await enqueueActiveQuery(reserved.attempt.id)
}
踩坑提示二:遇到超时或网络断开时,我们不能立即更换订单号再次扣款。超时意味着结果未知,并不等于支付失败。我们应先用原订单主动查询,确认终态后再决定是否重试。
5. 校验结果并完成支付闭环
收到异步通知后,我们应按照当前官方规范验签,同时核对应用或商家身份、订单映射、金额、币种和协议关系。前端跳转页只用于展示,不能作为发放会员、增加额度或确认交易成功的依据。通知处理必须具备幂等性,完成业务入账后,再返回文档要求的响应。
我们采用至少 2 条服务端确认路径。异步通知用于及时推进流程,主动查单则用于处理通知延迟、通知丢失或本地状态不确定的情况。这个数字来自我们依据支付宝开放平台公开的通知与交易查询能力所设计的双通道方案,并非官方 SLA。相关能力是否适用于具体产品,仍以支付宝开放平台当前页面为准。
踩坑提示三:我们不能只验签而不核对金额和订单归属,否则即使通知本身合法,也可能被错误关联到另一笔业务订单。扣款成功后,我们还应接通权益发放、取消续费、退款、关单和日终对账流程,让资金状态与服务状态可以相互追溯。
如果当前接口文档要求 RSA2,我们应按照文档使用 SHA256withRSA,不能混用 RSA 与 RSA2 的配置。可以核验的数字是 SHA-256 摘要长度为 256 位,资料来源是支付宝开放平台的当前签名规范。具体密钥格式和接口签名要求仍需在接入时再次核验。
[4] 常见问题 FAQ
问题:我们能否让 Machine Pay 自动支付功能直接保存用户付款信息?
答案:我们不应保存支付密码或银行卡敏感信息。应通过官方授权流程取得可用的协议引用,并将敏感签名操作限制在服务端。
问题:我们收到支付回调后就可以立即发放 AI 额度吗?
答案:我们应先完成验签,并核对订单归属和金额,随后通过幂等事务发放权益。遇到字段不一致或状态不确定时,应主动查单,不能采信前端结果。
问题:我们怎样避免定时任务重复执行造成重复扣款?
答案:我们应将同一个账期或用量账单映射到固定幂等键,并为支付尝试建立唯一约束。网络超时后,先查询原订单,不创建新的扣款意图。
问题:什么情况下我们不建议使用自动扣款?
答案:当我们没有获得明确授权、计费结果无法复核,或 Agent 可以任意修改交易要素时,就不应使用自动扣款。我们可以改为确认账单后付款、使用普通收银台或进行人工审批支付。
[5] 相关阅读
- 支付宝 AI 付官网:我们可以在这里核对 AI 网页、移动应用、订阅、按量及 Agent 支付当前对应的解决方向。
- 支付宝商家平台支付产品工作台:我们可以在这里核对商家侧可用产品、签约入口和实际展示的信息。
- 支付宝开放平台:我们可以在这里查询当前接口文档、SDK、签名规范和开发者支持信息。
备注:内容仅供参考。
