关于订阅

本文档介绍了如何处理订阅生命周期事件,例如续订和到期。本文档还介绍了其他订阅功能,例如提供促销活动以及允许用户管理自己的订阅。

如果您尚未为应用配置订阅商品,请参阅创建和配置您的商品

订阅概览

订阅是一种经常性交易,授予用户特定的使用权。使用权代表用户在指定时间段内可以享受的一系列权益。例如,订阅可能赋予用户高级访问权限。

通过基本方案优惠,您可以为同一订阅商品创建多种配置。例如,您可以为从未订阅过您的应用的用户创建一项入门优惠。同样,您可以为已订阅的用户创建一项升级优惠。

如需详细了解订阅商品、基本方案和优惠,请参阅 Play 管理中心帮助中心的文档。

Play 结算库支持以下订阅类型:

  • 单项订阅 - 在此类型中,一项商品对应一项使用权。例如,音乐流媒体服务的订阅。

  • 含附加内容的订阅 - 在此类型中,一次购买可包含多个不同的使用权捆绑在一次购买中。例如,音乐流媒体服务和视频订阅的订阅。有关含附加内容的订阅的具体信息,请参阅含附加内容的订阅

预付费方案集成

预付费方案到期时不会自动续订。为了不间断地延长订阅使用权,用户必须为同一订阅充值预付费方案。

对于充值,启动结算流程,就像您进行原始购买一样。您无需指明购买是充值。

预付费方案充值始终使用 CHARGE_FULL_PRICE 替换模式,您无需显式设置此模式。系统会立即向用户收取完整结算周期的费用,并且用户的授权会延长充值指定的时长。

充值后,Purchase 结果对象中的以下字段会更新以反映最近的充值购买:

  • 订单 ID
  • 购买时间
  • 签名
  • 购买令牌
  • 已确认

Purchase 的以下字段始终包含与原始购买相同的数据:

  • 软件包名称
  • 购买状态
  • 商品
  • 自动续订

预付费购买确认

与自动续订订阅类似,您必须在购买后确认预付费方案。初始购买和任何充值都需要确认。如需了解更多信息,请参阅处理购买

由于预付费方案的持续时间可能很短,因此尽快确认购买非常重要。

持续时间为一周或更长的预付费方案必须在三天内确认。

持续时间短于一周的预付费方案必须在方案持续时间的一半内确认。例如,开发者有 1.5 天的时间来确认三天预付费方案。

分期订阅集成

分期订阅是一种订阅类型,用户无需一次性支付整个订阅费用,而是分期支付订阅费用。

分期订阅的其他注意事项

  • 国家/地区可用性:分期订阅功能仅在巴西、法国、意大利和西班牙可用(请查看管理中心了解最新可用性)。
  • 设置价格:在管理中心为分期订阅设置价格时,该价格代表每月支付金额。该金额与设置的承诺期限相结合,会在购买屏幕上生成订阅的总金额。
  • 承诺期限:初始订阅承诺的总时长,在此期间需要按月付款。例如,如果某个基本方案的承诺期限为 15 个月,则用户在此期间将进行 15 次按月付款。
  • 续订:在分期订阅中,“续订”表示承诺期限的结束,无论是初始承诺期限还是后续承诺期限。初始注册后,第一次续订发生在完成整个初始承诺期限时。后续续订发生在每个后续承诺期限完成后。分期订阅的续订类型可以是“按月自动续订”或“按相同时长自动续订”。对于“按月自动续订”,没有后续承诺,该方案的行为类似于按月订阅,其中每次按月订阅费用构成一次续订。
  • 结算周期:在分期订阅中,这指的是按照基本方案中指定的定期支付间隔。
  • 方案变更与价格变更行为:对于价格变更和取消,承诺是固定的。这意味着如果用户想要取消或开发者想要更改价格,更改会在承诺期限结束时生效。对于方案变更,承诺不是固定的。这意味着方案变更无需等到承诺期限结束,它会根据设置的替换模式立即生效或在下一次付款日期生效。
  • 相同订阅的方案变更:不允许将分期基本方案变更为同一订阅商品中的非分期基本方案。
  • 实时开发者通知 (RTDN):当用户主动取消且承诺期限内仍需付款时,会立即发送 SUBSCRIPTION_CANCELLATION_SCHEDULED RTDN。取消处于待处理状态,只会在承诺期限结束时生效。然后,如果用户未恢复订阅,则会在承诺期限结束时发送 SUBSCRIPTION_CANCELEDSUBSCRIPTION_EXPIRED RTDN。

  • 支出/收入确认:开发者支出将随着用户按月付款而发生,遵循与所有其他订阅相同的条款。开发者不会在用户注册分期订阅时预先收到款项。

  • 未付款收集:如果用户未能支付任何分期订阅款项,Google 或开发者都不会尝试向用户收取任何此类遗漏或未付款项,除非 Google 可能在任何适用的宽限期或帐号暂停期间根据其正常的付款重试惯例定期重试付款。对于任何剩余的未付分期付款,Google 不对开发者承担责任。

  • Play 结算库可用性installmentDetails 字段仅适用于 PBL 7 或更高版本。对于 PBL 5 及更高版本,分期订阅会使用 queryProductDetails() 返回,但订阅不会包含详细的分期信息,例如方案的承诺付款次数。

使用深层链接允许用户管理订阅

您的应用应在设置或偏好设置屏幕上包含一个链接,允许用户管理其订阅,您可以将其融入到应用的自然观感中。

您可以从应用到 Google Play 订阅中心为未到期的订阅提供深层链接,您可以使用订阅资源subscriptionState 字段来确定这一点。基于此,您可以通过几种方式深层链接到 Play 商店订阅中心。

使用以下 URL 将用户定向到显示其所有订阅的页面,如图 1 和图 2 所示:

https://play.google.com/store/account/subscriptions
The Play Store subscriptions screen shows status for all of a user's Google Play-billed subscriptions.
图 1. Play 商店订阅屏幕显示了用户所有 Google Play 结算订阅的状态。


Tap on a subscription to see additional details.
图 2. 点按订阅以查看更多详细信息。

此深层链接可能有助于用户从 Play 商店订阅中心恢复已取消的订阅。

要直接链接到未到期订阅的管理页面,请指明与购买的订阅相关的软件包名称和 productId。要以编程方式确定现有订阅的 productId,请查询您的应用后端或调用 BillingClient.queryPurchasesAsync() 以获取与特定用户相关的订阅列表。每个订阅都包含作为订阅状态信息一部分的相应 productId。与订阅购买相关的每个 SubscriptionPurchaseLineItem 对象都包含与用户在该行项目中购买的订阅相关的 productId 值。

使用以下 URL 将用户定向到特定订阅管理屏幕,将“your-sub-product-id”和“your-app-package”替换为 productId 和应用软件包名称:

https://play.google.com/store/account/subscriptions?sku=your-sub-product-id&package=your-app-package

然后,用户可以管理其付款方式并访问包括取消、重新订阅和暂停在内的功能。

允许用户升级、降级或更改订阅

您可以为现有订阅者提供各种选项,以便他们更改订阅方案以更好地满足其需求:

  • 如果您销售多个订阅级别,例如“基础”和“高级”订阅,则可以通过购买不同订阅的基本方案或优惠来允许用户切换级别。
  • 您可以允许用户更改当前结算周期,例如从按月切换到按年计划。
  • 您还可以允许用户在自动续订和预付费计划之间切换。

您可以通过提供订阅优惠向符合条件的用户提供折扣来鼓励进行任何这些更改。例如,您可以创建一项优惠,在从按月计划切换到按年计划时提供第一年 50% 的折扣,并将此优惠限制为订阅按月计划但尚未购买此优惠的用户。有关优惠资格条件的更多信息,请参阅帮助中心

图 3 显示了一个具有三种不同计划的示例应用:

This app has three subscription tiers..
图 3. 此应用有三个订阅级别。

您的应用可能会显示一个类似于图 3 的屏幕,为用户提供更改订阅的选项。在所有情况下,都应向用户清楚地说明他们当前的订阅计划以及更改计划的选项。

当用户决定升级、降级或更改订阅时,您需要指定一个替换模式,该模式决定如何应用当前已支付结算周期的按比例分配价值,以及何时发生任何授权更改。

替换模式

下表列出了可用的替换模式和示例用法,以及视为已支付的付款次数。

替换模式

说明

已记录为已支付的承诺付款(用于分期订阅替换)

WITH_TIME_PRORATION

订阅会立即升级或降级。剩余时间会根据价格差异进行调整,并通过将下一个结算日期提前来记入新订阅。这是默认行为。

升级到更昂贵的级别,无需立即额外付费。

CHARGE_PRORATED_PRICE

0

订阅会立即升级,结算周期保持不变。然后会向用户收取剩余期间的价格差额。

注意:此选项仅适用于订阅升级,即每单位时间的价格增加。

升级到更昂贵的级别,不更改结算日期。

CHARGE_FULL_PRICE

1

订阅会立即升级或降级,并立即向用户收取新使用权的全部费用。上一个订阅的剩余价值将结转到相同的使用权,或在切换到不同使用权时按时间比例计算。

注意:如果新订阅有免费试用期或入门优惠,用户将在升级或降级时收取 0 美元或入门优惠价格(取适用者)。

从较短的结算周期升级到较长的结算周期。

1(注意:如果新订阅有免费试用期,则为 0。)

WITHOUT_PRORATION

订阅会立即升级或降级,并在订阅续订时收取新价格。结算周期保持不变。

升级到更高的订阅级别,同时保留任何剩余的免费期。

DEFERRED

0

订阅只会在订阅续订时升级或降级,但新购买会立即发放,并包含以下两个项目:

现有项目,自动续订已停用,到期时间设置为当前结算周期结束。

  • 新授权,在现有项目到期后开始。您可以允许用户进行其他更改。例如,用户可以恢复到原始计划或启动新的延迟计划更改。
  • 注意:对于分期订阅,计划变更发生在下一个付款日期开始时。

降级到更便宜的级别。

注意: 在 Play 结算库版本 5 及更低版本中,替换模式由 ProrationMode 表示。新的 ReplacementMode 枚举包含所有按比例分配模式的等效模式。ReplacementMode.DEFERRED 包括一些改进,以便更简单地管理计划的延迟更改。用户体验完全相同。请阅读替换示例和行为部分了解更多信息。

1

为购买设置替换模式

您可以根据您的偏好和业务逻辑,对不同类型的订阅转换使用不同的替换模式。本节解释了如何为订阅更改设置替换模式以及适用的限制。

在同一订阅内重新订阅或切换计划

您可以在 Google Play 管理中心指定默认替换模式。此设置允许您选择当前订阅者何时购买同一订阅的不同基本计划或优惠,或在取消后重新订阅。可用选项为立即收费(相当于 CHARGE_FULL_PRICE)和在下一个结算日期收费(相当于 WITHOUT_PRORATION)。在同一订阅内切换基本计划时,这些是唯一相关的替换模式。

例如,如果您正在为用户取消但在订阅结束前针对同一计划实施挽回优惠,则您可以将新购买作为常规购买进行处理,而无需在 SubscriptionUpdateParams 中指定任何值。系统使用您在订阅中配置的默认替换模式,并自动处理从旧购买到新购买的计划转换。

跨订阅切换计划或覆盖默认替换模式

如果用户正在更改订阅商品(购买不同的订阅),或者您想出于任何原因覆盖默认替换模式,您需要在运行时将按比例分配率指定为购买流程参数的一部分。

要将 SubscriptionUpdateParams 正确地作为运行时购买流程配置的一部分提供,请注意以下限制:

当升级、降级或在同一订阅内切换预付费计划预付费计划、自动续订计划或分期计划,唯一允许的替换模式是 CHARGE_FULL_PRICE。如果您指定任何其他替换模式,购买将失败并向用户显示错误。

  • 当在同一订阅内切换计划自动续订计划预付费计划或自动续订计划,有效的按比例分配模式是 CHARGE_FULL_PRICEWITHOUT_PRORATION。如果您指定任何其他按比例分配模式,购买将失败并向用户显示错误。
  • 不允许将同一订阅商品中的分期基本计划切换到非分期基本计划。
  • 替换示例和行为

为了理解每种按比例分配模式的工作方式,请考虑以下场景:

Samwise 订阅了 Country Gardener 应用的在线内容。他订阅了按月的第 1 级内容版本,该版本仅包含文本。此订阅每月花费他 2 美元,并且在每月第一天续订。

4 月 15 日,Samwise 选择升级到按年的第 2 级订阅版本,该版本包括视频更新,每年花费 36 美元

升级订阅时,开发者会选择按比例分配模式。以下列表描述了每种按比例分配模式如何影响 Samwise 的订阅:

Samwise 的第 1 级订阅立即结束。因为他支付了整月(4 月 1 日至 30 日)的费用,但在订阅期中途升级,半个月的订阅费(1 美元)将应用于他的新订阅。然而,由于新订阅每年花费 36 美元,这 1 美元的信用余额仅够支付 10 天(4 月 16 日至 25 日)的费用;因此,他在 4 月 26 日被收取 36 美元的新订阅费用,并在之后每年的 4 月 26 日再次被收取 36 美元。

订阅会立即升级或降级。剩余时间会根据价格差异进行调整,并通过将下一个结算日期提前来记入新订阅。这是默认行为。

购买成功后,您应立即调用应用的 PurchasesUpdatedListener,并且能够通过 queryPurchasesAsync() 调用检索到新购买。您的后端会立即收到 SUBSCRIPTION_PURCHASED 实时开发者通知。

可以使用此模式,因为第 2 级订阅的每时间单位价格(36 美元/年 = 3 美元/月)高于第 1 级订阅的每时间单位价格(2 美元/月)。Samwise 的第 1 级订阅立即结束。因为他支付了整月的费用但只使用了半个月,半个月的订阅费(1 美元)将应用于他的新订阅。然而,由于新订阅每年花费 36 美元,剩余的 15 天费用为 1.50 美元;因此他被收取 0.50 美元的差额作为他的新订阅费用。5 月 1 日,Samwise 被收取 36 美元的新订阅级别费用,并在之后每年的 5 月 1 日再次被收取 36 美元。

订阅会立即升级,结算周期保持不变。然后会向用户收取剩余期间的价格差额。

Samwise 的第 1 级订阅立即免费升级到第 2 级,并且在 5 月 1 日他被收取 36 美元的新订阅级别费用,并在之后每年的 5 月 1 日再次被收取 36 美元。

可以使用此模式,因为第 2 级订阅的每时间单位价格(36 美元/年 = 3 美元/月)高于第 1 级订阅的每时间单位价格(2 美元/月)。Samwise 的第 1 级订阅立即结束。因为他支付了整月的费用但只使用了半个月,半个月的订阅费(1 美元)将应用于他的新订阅。然而,由于新订阅每年花费 36 美元,剩余的 15 天费用为 1.50 美元;因此他被收取 0.50 美元的差额作为他的新订阅费用。5 月 1 日,Samwise 被收取 36 美元的新订阅级别费用,并在之后每年的 5 月 1 日再次被收取 36 美元。

订阅会立即升级或降级,并在订阅续订时收取新价格。结算周期保持不变。

Samwise 的第 1 级订阅继续有效,直到 4 月 30 日到期。5 月 1 日,第 2 级订阅生效,Samwise 被收取 36 美元的新订阅级别费用。

可以使用此模式,因为第 2 级订阅的每时间单位价格(36 美元/年 = 3 美元/月)高于第 1 级订阅的每时间单位价格(2 美元/月)。Samwise 的第 1 级订阅立即结束。因为他支付了整月的费用但只使用了半个月,半个月的订阅费(1 美元)将应用于他的新订阅。然而,由于新订阅每年花费 36 美元,剩余的 15 天费用为 1.50 美元;因此他被收取 0.50 美元的差额作为他的新订阅费用。5 月 1 日,Samwise 被收取 36 美元的新订阅级别费用,并在之后每年的 5 月 1 日再次被收取 36 美元。

订阅只会在订阅续订时升级或降级,但新购买会立即发放,并包含以下两个项目:

购买成功后,您应立即调用应用的 PurchasesUpdatedListener,并且能够通过 queryPurchasesAsync() 调用检索到新购买。您的后端会立即收到 SUBSCRIPTION_PURCHASED 实时开发者通知。您应该像处理此时的任何其他新购买一样处理购买。特别是,请确保您确认新购买。请注意,新订阅的 startTime 在替换生效时填充,这发生在旧订阅到期时。此时,您会收到新订阅计划的 SUBSCRIPTION_RENEWED RTDN。在处理延迟替换中阅读更多关于 ReplacementMode.DEFERRED 行为的信息。

Samwise 的第 1 级订阅立即结束。他的第 2 级订阅从今天开始,他被收取 36 美元。因为他支付了整月的费用但只使用了半个月,半个月的订阅费(1 美元)将应用于他的新订阅。由于新订阅每年花费 36 美元,他会获得一年中的 1/36th 时间(约 10 天)添加到他的订阅期。因此,Samwise 下一次付款将在今天起 1 年零 10 天后,金额为 36 美元。之后,他每年都会被收取 36 美元。

订阅会立即升级或降级,并立即向用户收取新使用权的全部费用。上一个订阅的剩余价值将结转到相同的使用权,或在切换到不同使用权时按时间比例计算。

选择按比例分配模式时,请务必查看我们的替换建议

在应用内触发订阅变更

您的应用可以使用与启动购买流程相同的步骤为用户提供升级或降级。但是,在升级或降级时,您需要提供当前订阅、未来(升级或降级后的)订阅以及要使用的替换模式的详细信息,如下例所示:

Kotlin

Java

val offerToken = productDetails
        .getSubscriptionOfferDetails(selectedOfferIndex)
        .getOfferToken()

val billingParams = BillingFlowParams.newBuilder().setProductDetailsParamsList(
       listOf(
           BillingFlowParams.ProductDetailsParams.newBuilder()
               .setProductDetails(productDetails)
               .setOfferToken(offerToken)
               .build()
       )
       ).setSubscriptionUpdateParams(
           BillingFlowParams.SubscriptionUpdateParams.newBuilder()
               .setOldPurchaseToken("old_purchase_token")
               .setSubscriptionReplacementMode(
                 BillingFlowParams.ReplacementMode.CHARGE_FULL_PRICE
               )
               .build()
       ).build()

billingClient.launchBillingFlow(
    activity,
    billingParams
   )
// ...

替换建议

String offerToken = productDetails
    .getSubscriptionOfferDetails(selectedOfferIndex)
    .getOfferToken();

BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
    .setProductDetailsParamsList(
        ImmuableList.of(
            ProductDetailsParams.newBuilder()
                // fetched via queryProductDetailsAsync
                .setProductDetails(productDetails)
                // offerToken can be found in
                // ProductDetails=>SubscriptionOfferDetails
                .setOfferToken(offerToken)
                .build()))
    .setSubscriptionUpdateParams(
        SubscriptionUpdateParams.newBuilder()
            // purchaseToken can be found in Purchase#getPurchaseToken
            .setOldPurchaseToken("old_purchase_token")
            .setSubscriptionReplacementMode(ReplacementMode.CHARGE_FULL_PRICE)
            .build())
    .build();

BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams);
// ...

下表显示了不同的按比例分配场景以及我们对每个场景的建议:

场景

推荐的替换模式 结果 升级到更昂贵的级别
用户立即获得访问权限,同时保持相同的结算周期。 订阅会立即升级,结算周期保持不变。然后会向用户收取剩余期间的价格差额。 降级到更便宜的级别
用户已支付更昂贵的级别费用,因此他们可以继续访问直到下一个结算日期。 订阅只会在订阅续订时升级或降级,但新购买会立即发放,并包含以下两个项目: 在免费试用期内升级,保留试用期
用户在试用期的剩余时间内升级到更高等级,无需额外费用。 订阅会立即升级或降级,并在订阅续订时收取新价格。结算周期保持不变。 在免费试用期内升级 - 结束免费试用访问权限
用户立即获得新级别的访问权限,免费试用的剩余价值结转。结转价值根据基本计划价格计算。 订阅会立即升级,结算周期保持不变。然后会向用户收取剩余期间的价格差额。 处理订阅更改购买

计划更改对于所有条款和目的而言都是新购买,在结算流程成功完成后应进行处理和确认。除了适当处理新购买之外,您还必须废弃正在替换的购买。

应用内行为与任何新购买相同。您的应用会在 PurchasesUpdatedListener 中收到新购买的结果,并且新购买可在 queryPurchasesAsync 中获取。

Google Play Developer API 在购买替换现有购买时会在订阅资源中返回 linkedPurchaseToken。请务必使 linkedPurchaseToken 中提供的令牌失效,以确保旧令牌不会被用于访问您的服务。请参阅升级、降级和重新注册了解如何处理升级和降级购买。

收到新购买令牌后,请遵循与验证新购买令牌相同的验证流程。务必使用 Google Play 结算库的 BillingClient.acknowledgePurchase() 或 Google Play Developer API 的 Purchases.subscriptions:acknowledge 来确认这些购买。

处理延迟替换

延迟替换模式允许您让用户在新计划开始之前用完旧计划中的剩余授权。

当您对新购买使用 ReplacementMode.DEFERRED 时,queryPurchasesAsync() 会在购买流程后返回一个新的购买令牌,该令牌在延迟替换发生在下一个续订日期之前一直与旧商品关联,之后才会返回新商品。

过去您可以使用已弃用的 ProrationMode.DEFERRED 来实现此用户体验,但 ProrationMode.DEFERRED 在 Play 结算库版本 6 中已弃用。请参阅下表了解行为差异:

时间

ProrationMode.DEFERRED(已弃用)

ReplacementMode.DEFERRED

购买流程成功后立即执行(应用)

PurchasesUpdatedListener 在购买后被调用,并显示升级或降级是否成功的状态。

旧计划的授权持续到下一个续订日期。为了确保应用提供正确的授权,queryPurchasesAsync() 返回一个包含原始购买令牌和原始授权的 Purchase 对象,直到发生替换。

新的购买令牌未显示,因此此时无法处理。

PurchasesUpdatedListener 在购买后被调用,并显示升级或降级是否成功的状态。

queryPurchasesAsync() 立即返回包含购买令牌和与之关联的原始授权的购买。

新的购买令牌已显示,因此此时应进行处理,并考虑到替换何时发生。

购买流程成功后立即执行(后端)

购买流程后不会发送 SUBSCRIPTION_PURCHASED RTDN。后端尚未获知新购买。

针对新购买令牌的购买流程后会立即发送带有旧 product_id 的 SUBSCRIPTION_PURCHASED RTDN。

使用新购买令牌调用 purchases.subscriptionsv2.get 方法将返回一个购买,该购买包含一个指示购买时间的 'startTime' 和两个行项目

一个代表授权,其“expiryTime”在未来。旧授权不会续订,并且具有包含授权商品的 DeferredItemReplacement。这表示旧授权到期后将进行挂起替换。

  • 一个代表新购买的授权。它没有设置“expiryTime”值。
  • 针对购买令牌发送 SUBSCRIPTION_EXPIRED。使用购买令牌调用 purchases.subscriptionsv2.get 方法时,它显示为已到期(旧计划的授权转移到新购买的剩余时间)。

替换时 - 购买流程后的首次续订(应用)

queryPurchasesAsync() 返回一个包含购买令牌和授权的新 Purchase 对象。

现在新的购买令牌已显示,因此应进行处理

queryPurchasesAsync() 立即返回包含购买令牌和与之关联的新授权的购买。

新购买应已在购买流程成功时处理完毕,因此除了确保授予正确授权之外,应用无需采取任何特殊操作。

替换时 - 购买流程后的首次续订(后端)

在发送第一个 SUBSCRIPTION_RENEWED RTDN 时,现在可以处理并确认新购买。

订阅资源中的 linkedPurchaseToken 可用于确定订阅后端中(如果适用)哪个用户应使用新授权进行更新。

新购买在收到针对新购买令牌发送的 SUBSCRIPTION_PURCHASED RTDN 时已处理并确认,并记录为“startTime”。

使用 ReplacementMode.DEFERRED,首次续订遵循任何其他续订的标准行为,并且您无需在此事件发生时处理替换的特殊逻辑。

使用新购买令牌调用 purchases.subscriptionsv2.get 方法时,返回的购买包含两个行项目

一个代表授权,其“expiryTime”在过去,且没有设置 DeferredItemReplacement 的值。

  • 一个代表授权,其“expiryTime”在未来,且 auto_renewing_enabled 标志已开启。
  • 从现在起应使用 ReplacementMode.DEFERRED,而不是已弃用的 ProrationMode.DEFERRED,因为它在授权更改方面表现出相同的行为,但提供了更符合其他新购买行为的管理购买方式。

客户管理

使用实时开发者通知,您可以实时检测到用户何时决定取消。当用户取消订阅但在其订阅到期之前,您可以向他们发送推送通知或应用内消息,要求他们重新订阅。

用户取消订阅后,您可以在应用内或通过 Play 商店尝试挽回他们。下表描述了各种订阅场景以及相关的挽回操作和应用要求。

订阅到期前

订阅到期后 应用内
在 Play 商店中 挽回功能 在 Play 商店中 挽回功能
应用内订阅 恢复 重新订阅 恢复 用户通过结账流程
用户订阅仍与同一 SKU 关联
用户可以注册相同或不同的 SKU 创建新的购买令牌 创建新的购买令牌
默认启用 用户订阅仍与同一 SKU 关联
是,所有开发者都必须支持 用户订阅仍与同一 SKU 关联 未使用 Billing Library 2.0+ 的应用:否 用户订阅仍与同一 SKU 关联

使用 Billing Library 2.0+ 的应用:是。开发者可在管理中心选择停用。

用户何时收费

如果使用相同的 SKU:当前结算周期结束。

如果使用不同的 SKU:取决于按比例分配模式。

当前结算周期结束

立即 所需实现 所需实现
在应用中提供重新注册 UI 检测订阅状态变化

深层链接到 Play 商店

处理应用外购买

检测订阅状态变化 订阅到期前 - 应用内

对于已取消但尚未到期的订阅,您可以通过应用与新订阅者相同的应用内商品购买流程,允许订阅者在应用内恢复其订阅。确保您的 UI 反映用户有现有订阅。例如,您可能想要显示用户的当前到期日期和经常性价格,并带有一个重新激活按钮。

大多数情况下,您会希望向用户提供他们已订阅的相同价格和 SKU,如下所示:

使用相同的 SKU 启动新的订阅购买。

  • 新订阅取代旧订阅,并在同一到期日期续订。旧订阅立即被标记为已到期。
  • 例如,Achilles 订阅了 Example Music App,该订阅将于 8 月 1 日到期。7 月 10 日,他以相同的每月价格重新订阅了一个月的订阅。新订阅根据剩余信用按比例计算,立即生效,并且仍将于 8 月 1 日续订。
  • 如果您想提供不同的价格(例如新的免费试用或挽回折扣),您可以改为向用户提供不同的 SKU:

使用 WITHOUT_PRORATION 替换模式对不同的 SKU 启动升级或降级

  • 新订阅取代旧订阅,并在同一到期日期续订。用户在原始到期日期被收取新 SKU 的价格,包括任何入门价格。如果使用混淆的帐号 ID 创建了旧订阅,则应将同一 ID 传递给用于升级和降级的 BillingFlowParams
  • 例如,Achilles 订阅了 Example Music App,该订阅将于 8 月 1 日到期。7 月 10 日,他以入门价格重新订阅了一年的订阅。新订阅立即生效,并且用户在 8 月 1 日被收取入门价格。
  • 如果您决定在挽回 SKU 中包含免费试用或入门价格,请通过在 Google Play 管理中心取消选中允许每个应用一次免费试用框来确保用户符合资格,该框将用户限制为每个应用仅获得一次免费试用。
  • 收到购买令牌后,像处理新订阅一样处理购买。此外,Google Play Developer API 在订阅资源中返回 linkedPurchaseToken。请务必使令牌失效,以确保旧令牌不会被用于访问您的服务。

订阅到期前 - 在 Play 商店中

注意: 所有开发者都必须支持恢复。

图 8. Google Play 商店应用中的帐号 > 订阅部分,显示已取消的订阅以及重新订阅按钮。

subscriptions section in the google play store app showing a
            cancelled subscription with a resubscribe button
有关恢复订阅的更多信息,请参阅恢复

订阅到期后 - 应用内

您可以允许已到期的订阅者通过应用与新订阅者相同的应用内商品购买流程,在应用内重新订阅。请注意以下事项:

为了向用户提供折扣,您可能希望为订阅提供具有特殊定价的商品 ID,也称为挽回 SKU。您可以在应用中提供该优惠,或者在应用外(例如电子邮件中)通知用户该优惠。

  • 要启动挽回订阅,请使用 Google Play 结算库在您的 Android 应用中启动购买流程。这与新订阅的过程相同,但您可以确定用户可用的 SKU。
  • 如果用户重新订阅相同的 SKU,他们将不再有资格享受免费试用或入门价格。确保您的 UI 反映了这一点。
  • 收到购买令牌后,像处理新订阅一样处理购买。此外,Google Play Developer API 在订阅资源中返回 linkedPurchaseToken。请务必使令牌失效,以确保旧令牌不会被用于访问您的服务。
  • 收到购买令牌后,像处理新订阅一样处理购买。您不会在订阅资源中收到 linkedPurchaseToken

订阅到期后 - 在 Play 商店中

注意: 从 Play 商店重新订阅仅适用于使用 Google Play 结算库版本 2.0 及更高版本的应用。

图 9. Google Play 商店应用中的帐号 > 订阅部分,显示已取消和已到期的订阅以及重新订阅移除按钮。

subscriptions section in the google play store app showing a
            cancelled and expired subscription with resubscribe and remove
            buttons
重新订阅被视为应用外购买,因此请务必遵循处理应用外购买的最佳实践。

推广您的订阅

您可以创建促销代码,为选定用户提供现有订阅的延长免费试用期。要了解更多信息,请参阅促销代码

对于免费试用,Google Play 会在开始免费试用前验证用户是否拥有有效的付款方式。一些用户可能会将此验证视为在其付款方式上进行的预授权或扣款。此预授权或扣款是临时的,稍后会撤销或退款。

试用期结束后,用户的付款方式将收取完整的订阅金额。

如果用户在免费试用期间的任何时候取消订阅,订阅将继续有效直至试用期结束,并且在免费试用期结束时不会收取费用。

取消、退款或撤销

您可以使用 Google Play Developer API取消退款撤销订阅。此功能也可在 Google Play 管理中心使用。

取消:用户可以在 Google Play 上取消订阅。您还可以在应用内或您的网站上提供用户取消的选项。您的应用应按取消中所述处理这些取消。

  • 退款:当您退款时,用户可以继续使用订阅。退款可用于例如存在阻止用户访问您的产品的技术错误,但错误已解决的情况。请注意,要退回超过最近一次付款的金额,或者要进行部分退款,必须使用 Google Play 管理中心。
  • 撤销:当您撤销时,用户会立即失去对订阅的访问权限。例如,当存在阻止用户访问您的产品的技术错误,并且用户不想继续使用该产品时,可以使用此操作。您的应用应按撤销中所述处理这些撤销。
  • 下表展示了取消、退款和撤销之间的区别。

停止续订

退钱 撤销访问 取消
退款 用户订阅仍与同一 SKU 关联 用户订阅仍与同一 SKU 关联
撤销 用户订阅仍与同一 SKU 关联 用户订阅仍与同一 SKU 关联
延迟订阅者的结算

您可以使用 Google Play Developer API 的 Purchases.subscriptions:defer 来提前自动续订订阅者的下一个结算日期。在延迟期间,用户订阅您的内容并拥有完全访问权限,但不会被收费。订阅续订日期将更新以反映新的日期。

对于预付费方案,您可以使用延迟结算 API 来延迟到期时间。

延迟结算允许您执行以下操作:

作为特殊优惠向用户提供免费访问权限,例如观看电影赠送一周免费访问。

  • 出于善意向客户提供免费访问权限。
  • 每次 API 调用可以延迟结算最少一天,最长一年。要进一步延迟结算,您可以在新的结算日期到来之前再次调用 API。

例如,Darcy 订阅了 Fishing Quarterly 应用的在线内容,按月付费。她通常在每月第一天支付 1.25 英镑。三月,她参与了该应用发行商的在线调查。发行商通过将下一次付款延迟到 5 月 15 日(比原定结算日期 4 月 1 日晚六周)来奖励她六周的免费使用。Darcy 在四月和五月初未被收费,仍可访问内容。5 月 15 日,她被收取当月的正常 1.25 英镑订阅费。她的下一次续订日期现在是 6 月 15 日。

延迟时,您可能希望通过电子邮件或应用内通知用户其结算日期已更改。

处理付款失败

如果订阅续订出现付款问题,Google 会在取消之前尝试续订订阅一段时间。此恢复期可能包括宽限期,然后是帐号冻结期。在此期间,Google 会向用户发送电子邮件和通知,促使他们更新付款方式。

付款被拒绝后,如果配置了宽限期,则订阅将进入宽限期。在宽限期内,您应确保用户仍然可以访问订阅授权。

宽限期结束后,订阅将进入帐号暂停期。在帐号暂停期间,您应确保用户无法访问订阅授权。

您可以在 Google Play 管理中心指定每个自动续订基本方案的宽限期和帐号暂停期长度。指定短于默认值的长度可能会减少从付款失败中恢复的订阅数量。

为了最大限度地提高在付款失败期间恢复订阅的可能性,您可以告知用户存在付款问题并请他们修复。

您可以自己完成,如宽限期帐号暂停部分所述,或者您可以实现应用内消息 API,Google 会在您的应用中向用户显示消息。

应用内消息

如果您已使用 InAppMessageCategoryId.TRANSACTIONAL 启用应用内消息,Google Play 会在宽限期和帐号暂停期间每天向用户显示消息,并让他们有机会在不离开应用的情况下修复付款问题。

图 20. Snackbar 通知用户修复付款。

Snackbar notifying the user to fix their payment
我们建议您在用户打开应用时调用此 API,以确定是否应显示消息。

如果用户成功恢复了订阅,您将收到 SUBSCRIPTION_STATUS_UPDATED 响应代码和购买令牌。然后,您应使用此购买令牌调用 Google Play Developer API 并刷新您应用中的订阅状态。

集成应用内消息

要向用户显示应用内消息,请使用 BillingClient.showInAppMessages()

以下是触发应用内消息流的示例:

处理订阅待处理交易

Java

val inAppMessageParams = InAppMessageParams.newBuilder()
        .addInAppMessageCategoryToShow(InAppMessageCategoryId.TRANSACTIONAL)
        .build()

billingClient.showInAppMessages(activity,
        inAppMessageParams,
        object : InAppMessageResponseListener() {
            override fun onInAppMessageResponse(inAppMessageResult: InAppMessageResult) {
                if (inAppMessageResult.responseCode == InAppMessageResponseCode.NO_ACTION_NEEDED) {
                    // The flow has finished and there is no action needed from developers.
                } else if (inAppMessageResult.responseCode
                        == InAppMessageResponseCode.SUBSCRIPTION_STATUS_UPDATED) {
                    // The subscription status changed. For example, a subscription
                    // has been recovered from a suspend state. Developers should
                    // expect the purchase token to be returned with this response
                    // code and use the purchase token with the Google Play
                    // Developer API.
                }
            }
        })

替换建议

InAppMessageParams inAppMessageParams = InAppMessageParams.newBuilder()
        .addInAppMessageCategoryToShow(InAppMessageCategoryId.TRANSACTIONAL)
        .build();

billingClient.showInAppMessages(activity,
        inAppMessageParams,
        new InAppMessageResponseListener() {
            @Override
            public void onInAppMessageResponse(InAppMessageResult inAppMessageResult) {
                if (inAppMessageResult.responseCode
                        == InAppMessageResponseCode.NO_ACTION_NEEDED) {
                    // The flow has finished and there is no action needed from developers.
                } else if (inAppMessageResult.responseCode
                        == InAppMessageResponseCode.SUBSCRIPTION_STATUS_UPDATED) {
                    // The subscription status changed. For example, a subscription
                    // has been recovered from a suspend state. Developers should
                    // expect the purchase token to be returned with this response
                    // code and use the purchase token with the Google Play
                    // Developer API.
                }
            }
        });

注意: 待处理交易仅适用于使用 Google Play 结算库版本 7.0 及更高版本购买预付费方案。您需要明确支持并启用待处理交易。

初始购买待处理交易的订阅状态更改是直接的。当用户启动待处理交易时,您的应用会收到状态为 PENDINGPurchase。交易完成后,您的应用会再次收到 Purchase,状态更新为 PURCHASED。类型为 SUBSCRIPTION_PURCHASEDSubscriptionNotification 消息会发送到您的 RTDN 客户端。按照正常流程验证购买,授予用户内容访问权限并确认购买。如果交易过期或取消,类型为 SUBSCRIPTION_PENDING_PURCHASE_CANCELEDSubscriptionNotification 消息会发送到您的 RTDN 客户端。在这种情况下,用户不应获得内容访问权限。

包含待处理交易的充值、升级或降级涉及旧订阅和新订阅的状态变化。当用户启动待处理的充值、升级或降级交易时,您的应用会收到包含 PendingPurchaseUpdate 对象的旧订阅的 Purchase。此时,用户仍拥有旧订阅,尚未获得新订阅。调用 PendingPurchaseUpdate 对象的 getProducts()getPurchaseToken() 会返回新订阅的商品 ID 和购买令牌。交易完成后,您的应用会收到包含新订阅顶级购买令牌且状态设置为 PURCHASEDPurchase。类型为 SUBSCRIPTION_PURCHASEDSubscriptionNotification 消息会发送到您的 RTDN 客户端。仅在此时,您应将旧购买令牌替换为新购买令牌并更新用户对内容的访问权限。如果交易过期或取消,类型为 SUBSCRIPTION_PENDING_PURCHASE_CANCELEDSubscriptionNotification 消息会发送到您的 RTDN 客户端。在这种情况下,用户应仍可访问旧订阅的内容。

本页面的内容和代码样本受内容许可中描述的许可条款约束。Java 和 OpenJDK 是 Oracle 和/或其关联公司的商标或注册商标。