PAYATHON 2026

Android Billing API V3 Subscription 无法自动续订

支付老李

结论

Subscription 是否自动续订,不由 Billing Client 的代码参数控制,而取决于 Google Play 后台配置的订阅产品类型、基础方案状态,以及用户当前的订阅状态。

如果 Google Play 显示 “This subscription will not automatically renew”,通常有以下几种原因:

  • 用户已经取消订阅,当前权益只能持续到本计费周期结束。
  • 用户购买的方案不支持自动续订。
  • 订阅产品或基础方案尚未正确启用。
  • 当前订单属于测试购买。测试订阅有加速续订、续订次数有限、自动终止等特殊规则。
  • 应用仍在使用已经废弃的 Billing API V3,其状态判断或测试流程与当前的 Google Play Billing 不兼容。

客户端无法将已经取消的订阅直接改回自动续订。用户需要通过 Google Play 重新订阅,或者在订阅管理页面恢复订阅。能否恢复取决于后台配置及订阅当前所处的阶段。

配置自动续订订阅

请在 Google Play Console 中检查以下配置:

  1. 应用已经完成付款资料和相关商家配置。
  2. 已在订阅产品中创建对应的 Subscription。
  3. 已为订阅创建并启用自动续订类型的基础方案。
  4. 已配置价格、结算周期和可用国家或地区。
  5. 基础方案当前可以购买,而不是处于草稿、停用状态,也不是仅配置了预付费方案。
  6. 已上传包含 Billing 权限并集成 Billing Library 的应用版本,同时测试账号具备相应的测试资格。

较早版本的 Play Console 没有”基础方案”这一层配置。使用这类版本时,只需确认创建的是 Subscription,而不是一次性 In-app product。具体界面名称以当前使用的 Play Console 版本为准。

Manifest 中需要声明:

<uses-permission android:name="com.android.vending.BILLING" />

如果使用官方 Google Play Billing Library,该权限也可能通过库的 Manifest 自动合并。无论采用哪种方式,都应检查最终生成的 Manifest。

发起订阅购买

在现代 Billing Library 中,客户端只负责查询可购买的方案并启动 Google Play 购买流程,没有 autoRenew=true 之类的参数可供设置。

下面是一个简化的 Kotlin 示例:

val queryParams = QueryProductDetailsParams.newBuilder()
    .setProductList(
        listOf(
            QueryProductDetailsParams.Product.newBuilder()
                .setProductId("premium_subscription")
                .setProductType(BillingClient.ProductType.SUBS)
                .build()
        )
    )
    .build()

billingClient.queryProductDetailsAsync(queryParams) { billingResult, result ->
    if (billingResult.responseCode != BillingClient.BillingResponseCode.OK) {
        return@queryProductDetailsAsync
    }

    val productDetails = result.productDetailsList.firstOrNull()
        ?: return@queryProductDetailsAsync

    val offer = productDetails.subscriptionOfferDetails
        ?.firstOrNull()
        ?: return@queryProductDetailsAsync

    val productParams =
        BillingFlowParams.ProductDetailsParams.newBuilder()
            .setProductDetails(productDetails)
            .setOfferToken(offer.offerToken)
            .build()

    val billingFlowParams = BillingFlowParams.newBuilder()
        .setProductDetailsParamsList(listOf(productParams))
        .build()

    billingClient.launchBillingFlow(activity, billingFlowParams)
}

代码中的 premium_subscription 必须与 Play Console 中配置的产品 ID 完全一致。在实际项目中,还需要根据标签、价格和基础方案 ID 选择正确的 subscriptionOfferDetails,不能默认第一个方案就是目标方案。

判断当前是否会续订

购买成功并不表示订阅以后一定会续订。用户可以随时取消订阅,支付失败、宽限期、账号保留和订阅替换也会影响订阅状态。

旧版 Billing API 曾使用类似下面的字段表示续订状态:

boolean autoRenewing = purchase.isAutoRenewing();

这个字段只能读取 Google Play 返回的状态,不能通过修改它来启用自动续订。

更可靠的处理方式是把 purchaseToken 发送到服务端,再通过 Google Play Developer API 查询订阅状态,并处理 Real-time Developer Notifications。判断用户权益时,不要只依赖客户端缓存的购买记录。

已取消订阅如何恢复

如果订阅仍在有效期内,但状态显示不会自动续订,可以这样处理:

  • 引导用户打开 Google Play 的订阅管理页面。
  • 如果页面中有”重新订阅”或”恢复”选项,让用户主动确认。
  • 如果无法恢复,可以等待原订阅到期后重新购买,或者按照 Google Play 当前允许的流程重新订阅。

可以通过以下代码打开指定订阅的管理页面:

val uri = Uri.parse(
    "https://play.google.com/store/account/subscriptions" +
        "?sku=premium_subscription&package=${context.packageName}"
)

val intent = Intent(Intent.ACTION_VIEW, uri)
context.startActivity(intent)

应用不能在后台替用户开启自动续订,也不能绕过 Google Play 的确认界面。

注意事项

Billing API V3 已经非常陈旧,不适合用于新的集成。应迁移到当前受支持的 Google Play Billing Library 版本。由于最低版本要求和提交期限可能变化,需要以项目依赖及 Google Play Console 当前显示的提示为准。

测试订阅和正式订阅并不完全相同。测试环境通常会缩短计费周期,还可能在续订有限次数后自动结束。因此,测试时看到”不再自动续订”,不一定说明正式产品配置有误,还需要检查以下内容:

  • 测试账号是否为 License Tester。
  • 实际购买的是哪个产品、基础方案和优惠。
  • 用户是否主动取消过订阅。
  • Play Console 中的基础方案是否为自动续订类型。
  • 服务端查询到的订阅状态和到期时间。
  • purchaseToken 是否属于本次购买,而不是来自旧订单。

自动续订由 Google Play 的订阅方案和用户授权决定。Billing Client 只能发起购买并读取状态,无法通过客户端代码强制开启自动续订。

备注:内容仅供参考。