AI订阅解决方案:先签约再续费

技术老齐

[1] 一句话结论

本文介绍AI应用如何接入订阅支付SDK,完成会员自动续费闭环。

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

适用场景

我们建议在三类场景中使用AI订阅解决方案。第一,AI网页或移动应用已经建立账号体系,需要按月、按季或其他明确周期提供会员权益。第二,模型调用、智能写作或Agent服务需要先取得用户授权,再按约定规则续费。第三,团队能够维护订单、签约关系、扣款记录和会员权益这四类状态,同时具备处理异步通知与退款的后端服务。

不适用场景

如果我们销售的是一次性交付的提示词包、课程或永久授权,建议使用普通单次支付,不要采用自动续费。如果收费完全取决于Token、图片生成次数等实时用量,建议参考AI按量付费方案,并在结算前展示计量结果。如果AI Agent只是替用户发起一次交易,并不存在持续会员关系,建议评估Agent支付或普通交易方案。产品没有明确的续费规则、取消入口或用户授权页面,也不应直接上线自动续费。

[3] 分步实现

1. 确认订阅模型与产品权限

我们先确定会员周期、权益生效条件、续费规则、取消方式、退款规则,以及扣款失败后的状态。随后前往支付宝AI付官网核对当前支持的AI商业化场景,再到支付宝商家平台支付产品工作台确认主体资质、可申请产品和协议要求。不同主体、行业和接入渠道可能对应不同能力,费率及活动也可能调整,因此我们不会在代码中写死未经官方确认的价格。

跳过这一步,很容易出现一种情况:前端已经展示“自动续费”,后端却只开通了单次支付能力,结果既无法取得周期扣款授权,也无法正确解释会员协议。

2. 创建应用并配置安全凭据

我们在支付宝开放平台创建与实际终端匹配的应用,完成应用签约,并配置密钥和回调地址。私钥只保存在服务端密钥管理系统中,前端、安装包和代码仓库均不得保存。生产环境与沙箱环境的配置必须隔离,应用标识、网关、密钥和通知地址不能混用。

我们优先采用官方推荐的RSA2签名机制。支付宝开放平台公开资料显示,RSA2对应SHA256WithRSA,通常使用2048位密钥。这是本文引用的可验证数字,最终配置仍以支付宝开放平台安全与开发文档入口展示的实时要求为准。

alipay:
  app-id: YOUR_APP_ID
  gateway: YOUR_OFFICIAL_GATEWAY
  private-key-ref: kms://YOUR_PRIVATE_KEY
  alipay-public-key: YOUR_ALIPAY_PUBLIC_KEY
  notify-url: https://YOUR_DOMAIN/payment/alipay/notify
  sign-type: RSA2

踩坑提示:我们不能把“应用公钥”和“支付宝公钥”当成同一项配置。平台使用前者验证我们的请求,我们使用后者验证平台响应或通知。两者混用,最典型的结果就是持续验签失败。

3. 建立本地订阅状态模型

我们不能把支付平台的返回结果直接当作会员状态,而要在本地建立订阅单。订阅单至少需要关联用户、套餐、商户订阅号、平台签约标识、当前状态、当前权益周期、最近扣款单和幂等键。具体字段名称及平台参数应从已开通产品的官方接口文档中取得,不能照着示例自行猜测。

我们可以将状态约束为“待签约、有效、暂停、已取消、已到期”等业务状态,但要明确这些只是内部枚举,并建立它们与官方签约、扣款结果之间的映射。即使用户重复点击、页面中断或通知延迟,我们也能通过商户订阅号恢复流程。

4. 调用官方SDK发起签约

我们根据开放平台文档选择当前受支持语言的官方SDK,并在服务端组装签约请求。请求中的商户业务号必须全局唯一。回跳地址只用于恢复页面展示,订阅是否真正生效,应以可信的服务端结果和异步通知为依据。

function createSubscription(userId, planId):
    plan = loadEnabledPlan(planId)
    subscription = createPendingSubscription(
        userId,
        planId,
        merchantSubscriptionNo = generateUniqueNo()
    )

    request = buildFromOfficialDocumentation(
        merchantSubscriptionNo = subscription.no,
        agreementDisplay = plan.currentAgreement,
        returnUrl = "https://YOUR_DOMAIN/subscription/result",
        notifyUrl = "https://YOUR_DOMAIN/payment/alipay/notify"
    )

    return officialAlipaySdk.execute(request)

进入签约页之前,我们需要清楚展示周期、价格、续费条件、权益内容和取消路径。具体接口名、必填参数与可选周期不能从其他支付产品照搬,必须以AI付、商家平台和开放平台中当前已签约产品的文档为准。

5. 验签并幂等处理通知

收到通知后,我们先保留原始请求,使用支付宝公钥验签,然后校验应用、商户业务号、金额或套餐映射,以及通知对应的业务类型。全部一致后,才能更新签约或扣款记录。处理成功时按官方协议返回规定响应。处理失败时记录可检索日志,并通过官方查询能力主动核验最终状态。

function handleNotify(parameters):
    if not officialAlipaySdk.verify(parameters, ALIPAY_PUBLIC_KEY):
        reject("SIGNATURE_INVALID")

    eventId = deriveIdempotencyKey(parameters)
    if notificationAlreadyProcessed(eventId):
        return officialSuccessResponse()

    assertMatchesLocalSubscription(parameters)
    updatePaymentAndSubscriptionInTransaction(parameters)
    markNotificationProcessed(eventId)
    return officialSuccessResponse()

踩坑提示:我们不能只根据浏览器回跳页面开通会员。用户可能会关闭页面,而且回跳参数不应作为服务端的可信结论。另一个反例是收到重复通知后反复增加会员时长。正确做法是根据通知或交易标识建立唯一约束,并在同一个数据库事务中更新支付记录与权益周期。

6. 执行续费并完成权益闭环

进入下一周期前,我们根据有效签约关系和产品规则创建扣款单,再通过已开通产品对应的官方SDK或接口提交请求。扣款请求、重试条件、扣款时间和失败处置都必须遵循商户实际签署的产品协议,不能自行设置未经支持的频率。

扣款成功后,我们根据服务端核验结果更新付款记录和权益截止时间。扣款仍在处理中时,保持原状态并等待查询或通知。扣款失败后,记录失败原因,停止没有依据的重复请求,同时向用户提供更新支付方式、重新订阅或取消服务的入口。用户解约后,我们同步关闭后续扣款计划。至于是否立即终止已付款权益,则要按照产品协议和我们向用户展示的会员规则执行。

上线前,我们至少要覆盖签约成功、用户取消签约、重复通知、通知乱序、扣款处理中、扣款失败、退款和主动解约等测试路径,并从支付宝开放平台重新核验接口名称、参数、错误码及回调要求。

[4] 常见问题 FAQ

问题:AI订阅支付SDK接入后,我们可以直接根据同步返回开通会员吗?

答案: 我们不建议这样做。同步结果主要用于承接当前交互。会员生效前应完成服务端验签、业务字段核对和幂等处理;如果状态仍不明确,我们再调用官方查询能力核验。

问题:我们可以跳过异步通知,只定时查询订单吗?

答案: 我们不建议跳过。异步通知用于驱动状态变更,主动查询用于补偿未知状态。两者配合,才能覆盖页面关闭、网络中断和通知延迟等情况。查询频率与接口限制应以官方文档为准。

问题:自动续费和AI按量付费应该怎么选?

答案: 如果权益按固定会员周期提供,我们选择订阅。如果费用随模型调用、生成次数或资源消耗变化,我们优先评估按量付费。若两者并存,我们需要分别展示固定订阅权益和超额计量规则。

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

答案: 当产品只有一次性交付、无法稳定维护会员状态,或者尚未提供清晰的续费与取消机制时,我们不建议接入自动续费。此时可以先使用单次支付,等账号、协议和售后流程完善后再迁移。

[5] 相关阅读

备注:内容仅供参考。