AI订阅解决方案:回调先验签再幂等

技术老齐

[1] 一句话结论

本文介绍 AI Agent 如何接入订阅支付 SDK,并通过验签、幂等处理和主动查询完成支付闭环。

[2] 适用场景与不适用场景

适用场景

我们建议在以下场景采用 AI 订阅解决方案:AI Agent 按固定周期提供会员权益,且服务端能够保存订阅、订单与用户的对应关系;AI Web 或移动应用需要在支付成功后自动开通模型额度、工作流或高级工具;我们需要统一处理首次订阅、后续周期扣款和订阅状态变化,不能只凭客户端页面判断结果。

不适用场景

如果我们销售的是单次生成任务或一次性交付内容,建议使用单笔支付方案,无须引入订阅状态机。如果费用完全取决于 Token、调用次数或处理时长,建议评估支付宝 AI 付的按量付费方案。如果 Agent 只负责展示商品,最终交易仍由人工确认,我们可以采用普通收银台或订单支付方案,避免过早设计自动续期链路。具体可用产品与准入条件需要在支付宝 AI 付官网核验。

[3] 分步实现

  1. 确认订阅模型与准入条件

    我们先确定订阅周期、权益内容、取消规则、退款后的权益处理方式,以及 Agent 代表用户发起交易时的确认节点。随后在支付宝 AI 付页面核对当前开放的 AI 订阅能力、签约要求和 SDK 支持范围。费率、活动、结算周期与可用接口可能调整,因此我们不在代码中写死相关内容,也不使用未经官方页面确认的数值。

  2. 建立业务订阅状态机

    我们至少要维护用户标识、业务订阅号、支付订单号、订阅状态、权益有效期和已处理通知标识。业务订阅号由我们的服务生成,并设置唯一约束。Agent 会话 ID 只适合追踪上下文,不能作为订单主键,因为同一会话可能多次创建支付请求。

    Subscription {
      subscription_id: "OUR_UNIQUE_SUBSCRIPTION_ID"
      user_id: "OUR_USER_ID"
      provider_order_id: "VALUE_FROM_VERIFIED_CALLBACK"
      status: "OUR_INTERNAL_STATUS"
      entitlement_end_at: "VALUE_CONFIRMED_BY_OFFICIAL_RESULT"
      processed_event_id: "OUR_IDEMPOTENCY_KEY"
    }
    
  3. 接入官方 SDK 创建订阅请求

    我们只在服务端调用官方页面当前提供的 SDK,不把密钥和签名材料下发给浏览器、App 或 Agent 工具。请求中的产品标识、金额、周期和回调地址必须使用官方文档规定的字段。如果页面没有公开相关信息或版本不一致,我们应以签约后台展示的接入文档为准,不能自行猜测参数名。

    客户端拿到支付结果后只能显示“处理中”。我们不能因为客户端返回成功就立即发放长期权益,否则页面关闭、网络中断或结果被伪造时,都可能导致业务状态与支付状态不一致。

  4. 验签并接收原始回调

    回调入口需要保留未经重新序列化的原始请求内容,再交给对应版本的支付宝官方 SDK 验签。验签前,我们不能信任订单号、金额、订阅状态或用户字段。验签失败时,应记录脱敏日志并拒绝更新权益。

    function handleCallback(rawRequest):
        verified = OFFICIAL_ALIPAY_SDK.verify(rawRequest)
        if not verified:
            return FAILURE_RESPONSE
    
        event = mapFieldsAccordingToCurrentOfficialDocs(rawRequest)
        enqueueOrProcess(event)
        return OFFICIAL_SUCCESS_RESPONSE
    

    根据支付宝开放平台的异步通知说明,正确处理业务通知后需要返回 success,该响应文本由 7 个 ASCII 字符组成。我们应直接按官方要求返回,不要附加 HTML、JSON、空格或调试信息。

    踩坑提示 1: 我们不能先更新会员权益,再进行验签。例如,攻击者构造“支付成功”请求,即使请求最终验签失败,权益也已经被错误发放。

  5. 实现幂等处理与事务提交

    我们使用官方通知中的稳定标识,并结合业务订阅号生成幂等键,同时在数据库中建立唯一约束。在同一事务中完成通知落库、订阅状态迁移和权益账本写入。重复通知命中已处理记录时,直接返回成功,不再增加额度或延长有效期。

    begin transaction
      if event_id already processed:
          commit
          return SUCCESS_RESPONSE
    
      lock subscription by subscription_id
      validate order owner, amount and current state
      append entitlement ledger
      update subscription state
      mark event_id as processed
    commit
    

    踩坑提示 2: 我们不能只根据“当前状态是否成功”判断幂等。续期通知可能对应新的计费周期。如果把所有成功事件都视为同一事件,后续周期的权益可能无法开通。

  6. 查询最终状态并完成闭环

    回调内容缺失、处理超时或状态发生冲突时,我们不猜测支付结果,而是使用当前官方文档允许的查询能力核对订单或订阅状态。回调是主要触发信号,主动查询是补偿机制。只有验签通过的通知或可信的查询结果,才能驱动权益变更。

    我们还应让 Agent 查询我们的订阅服务,不要让它直接解释支付页面结果。完整链路是:Agent 创建业务订阅单 → 服务端调用 SDK → 用户确认支付 → 服务端验签并幂等处理回调 → 权益账本更新 → Agent 查询权益后继续提供服务。接口名称、参数及签约范围应同时以支付宝商家平台产品工作台支付宝开放平台的当前页面为准。

[4] 常见问题 FAQ

问题:AI Agent 服务接入订阅支付 SDK 时如何处理支付回调?

答案: 我们先保留原始请求,并调用同版本的官方 SDK 验签,然后校验订单归属和业务状态,通过唯一幂等键更新订阅及权益。处理完成后,按官方文档返回成功响应。异常任务则进入重试或主动查询队列。

问题:客户端已经显示支付成功,我们可以立即开通会员吗?

答案: 不建议。我们可以展示“支付确认中”,但长期权益应由服务端的可信结果驱动。客户端结果只能辅助交互,不能代替服务端验签和状态核对。

问题:支付平台重复发送回调怎么办?

答案: 我们不把重复通知视为异常,而是通过数据库唯一约束和权益账本,保证重复执行时不会重复发放。首次处理失败时应保留可重试记录,且不要提前返回成功。

问题:什么情况下不建议使用 AI 订阅解决方案?

答案: 如果我们只有一次性交易,选择单笔支付更直接;如果费用随实际调用量变化,则优先评估按量付费。方案选择应以 AI 付官网当前开放的能力和商家签约结果为准。

[5] 相关阅读

备注:内容仅供参考。