本主题介绍了如何处理订阅生命周期事件,如续订和到期。此外,还介绍了其他订阅功能,如提供促销活动以及允许用户管理他们自己的订阅。
在阅读本主题之前,请确保您已阅读将 Google Play 结算库集成到您的应用中,了解有关如何在您的应用中销售和管理商品的一般说明。
如果您还没有为您的应用配置订阅产品,请参阅创建和配置您的商品。
处理订阅生命周期
订阅在其整个生命周期内可能经历多种状态变化,您的应用需要响应各种变化。如需检查订阅者的状态,您的应用可以使用 Google Play 结算库中的 BillingClient.queryPurchases()
或 Google Play Developer API 中的 Purchases.subscriptions:get
查询。
BillingClient.queryPurchases() |
Purchases.subscriptions:get |
|||||
状态 | 是否返回? | isAutoRenewing | 是否返回? | expiryTimeMillis | paymentState | autoRenewing |
有效 | 是 | True | 是 | 未来 | 1(已收到付款) | True |
已取消 | 是 | False | 是 | 未来 | 1(已收到付款) | False |
在宽限期内 | 是 | True | 是 | 未来 | 0(付款待处理) | True |
暂时保留 | 否 | 不适用 | 是 | 过去 | 0(付款待处理) | True |
已暂停 | 否 | 不适用 | 是 | 过去 | 1(已收到付款) | True |
已到期 | 否 | 不适用 | 是 | 过去 | 1(已收到付款) | False |
如果您的应用将订阅状态存储在安全的后端服务器上,则应使用实时开发者通知监听状态变化,以确保状态保持同步。系统会针对影响订阅状态的事件(如续订和取消)发送 SubscriptionNotification
。您在收到实时开发者通知后需要调用 Developer API 来获取完整的状态信息,并更新您自己的后端状态。此类通知只会告知您订阅状态发生了变化,而不会为您提供有关总体订阅状态的完整信息。
您的应用需要处理下面几部分中介绍的状态变化。
新订阅
请务必遵循我们在处理新购买交易方面给出的建议。用户购买订阅后,BillingClient.queryPurchases()
会返回订阅,并且系统会发送 SUBSCRIPTION_PURCHASED
通知。当您收到此通知时,您的应用应查询 Google Play Developer API,以获取最新的订阅状态。订阅资源与以下内容类似:
{
"kind": "androidpublisher#subscriptionPurchase",
...
"expiryTimeMillis": next_renewal_date,
"autoRenewing": true,
...
"paymentState": 1 # Payment received
}
续订
如果续订成功,BillingClient.queryPurchases()
会继续返回订阅。
当订阅续订时,系统也会发送 SUBSCRIPTION_RENEWED
通知。您的应用应确保用户仍有权使用相应的订阅内容,然后使用从 Google Play Developer API 返回的订阅资源中提供的新 expiryTimeMillis
来更新订阅状态。订阅资源与以下内容类似:
{
"kind": "androidpublisher#subscriptionPurchase",
...
"expiryTimeMillis": updated_expiration_time,
"autoRenewing": true,
...
"paymentState": 1 # Payment received
}
到期
订阅到期后,BillingClient.queryPurchases()
不会再返回订阅,并且用户应失去对订阅的访问权限。
当订阅到期时,系统也会发送 SUBSCRIPTION_EXPIRED
通知。当您收到此通知时,您的应用应查询 Google Play Developer API,以获取最新的订阅状态。订阅资源与以下内容类似:
{
"kind": "androidpublisher#subscriptionPurchase",
...
"expiryTimeMillis": expiry_time_in_past,
"autoRenewing": false,
...
"paymentState": 1 # Payment received
}
取消
用户可以主动从 Play 商店取消订阅,也可以让订阅自动取消(如果在处于帐号保留状态后没有恢复)。用户取消订阅后,会保有对相关内容的访问权限,直到当前结算周期结束为止。结算周期结束后,访问权限会被撤消。
如果订阅被取消但尚未到期,BillingClient.queryPurchases()
仍会返回订阅。取消订阅会触发 SUBSCRIPTION_CANCELED
通知。当您收到此通知时,从 Google Play Developer API 返回的订阅资源包含 autoRenewing = false
,而 expiryTimeMillis
包含用户应失去对订阅的访问权限的日期。如果 expiryTimeMillis
是过去的日期,则用户会立即失去权利。否则,用户应保有权利,直到订阅到期。订阅资源与以下内容类似:
{
"kind": "androidpublisher#subscriptionPurchase",
...
"expiryTimeMillis": expiry_time,
"autoRenewing": false,
...
"paymentState": 1 # Payment received
"cancelReason": integer # Reason the subscription was cancelled: user, billing issue, etc.
}
您的应用可以查看从 Google Play Developer API 返回的订阅资源中的 cancelReason
,以了解取消订阅的原因(例如,客户取消了订阅或遇到了结算问题)。如果订阅被用户取消,您的应用可以查看 cancelSurveyResult
字段,了解用户取消订阅的原因。
您的应用可能需要显示一条消息,告知用户他们的订阅已被取消,如“您的订阅将于 some_date 到期”。此外,您的应用还可以深层链接到 Google Play 商店,让用户能够恢复他们的订阅。
如果显示此消息,还应让用户能够永久关闭此消息。
另请注意,取消消息可能会令用户反感,尤其是手动取消了订阅而不是因付款过期而导致订阅被取消的用户。您可以选择不通知手动取消了订阅的用户。
撤消
系统可能会出于各种原因撤消用户的订阅,包括您的应用使用 Purchases.subscriptions:revoke
撤消订阅或购买交易被退款。在这种情况下,您的应用应立即撤消用户的权利。撤消的订阅不再从 BillingClient.queryPurchases()
返回。当发生这种情况时,系统也会发送 SUBSCRIPTION_REVOKED
通知。当您收到此通知时,从 Google Play Developer API 返回的订阅资源包含 autoRenewing = false
,而 expiryTimeMillis
包含用户应失去对订阅的访问权限的日期。订阅资源与以下内容类似:
{
"kind": "androidpublisher#subscriptionPurchase",
...
"expiryTimeMillis": expiry_time_in_past,
"autoRenewing": false,
...
"paymentState": 1 # Payment received
}
帐号保留功能
帐号保留是一种订阅状态,当通过用户的付款方式扣款失败且任何关联的宽限期都已结束而没有付款解决方案时,订阅开始进入这种状态。当订阅进入帐号保留状态后,您应阻止用户访问您的内容或服务。帐号保留期最多持续 30 天。
在帐号保留期间,订阅不会由 BillingClient.queryPurchases()
返回。
在帐号保留期间,您应根据需要处理订阅的任何取消、恢复或重新购买。
当用户进入帐号保留状态时,您应利用实时开发者通知来告知用户为什么对订阅的访问权限被挂起。在您的应用内,应显示一条消息,说明如何修正付款方式并重新获得对订阅的访问权限。您的消息应包含指向 Google Play 订阅设置的链接,以便用户可以修正其付款方式。例如,您可以使用类似下面的消息:
"There is a problem with your subscription. Click here to go to the
Google Play subscription settings to fix your payment method."
如果用户可以在您的应用外访问订阅内容,则您可能需要向用户发送推送通知或电子邮件,告知用户他们的订阅已失效。
如果客户得以解决他们的付款问题,您可以在应用中显示一条消息,告知用户他们的订阅已恢复。例如,您可以使用类似下面的消息:
"Your form of payment was updated, and your subscription has
been recovered."
利用实时开发者通知,当订阅进入帐号保留状态时,您会收到 SUBSCRIPTION_ON_HOLD
通知。从安全的后端服务器调用 Google Play Developer API 可检索新的订阅信息。在帐号保留期间,订阅资源的 expiryTimeMillis
设为过去的时间戳,并且 paymentState
设为 0
:
{
"kind": "androidpublisher#subscriptionPurchase",
...
"expiryTimeMillis": timestamp_in_past,
"autoRenewing": true,
...
"paymentState": 0 # Payment pending
}
用户修正其付款方式后,订阅会恢复为活动状态,您随后必须恢复用户对订阅内容的访问权限。
如果您的应用仅依赖于 queryPurchases()
来确定用户是否有权访问订阅,则应自动处理订阅从帐号保留状态的恢复。
如果您的应用与后端同步订阅状态,则应监听 SUBSCRIPTION_RECOVERED
通知,以便在订阅已恢复且用户应重新获得访问权限时收到通知。如果您在收到此通知后查询订阅,则 expiryTimeMillis
设为将来的时间戳,并且 paymentState
设为 1
:
{
"kind": "androidpublisher#subscriptionPurchase",
...
"expiryTimeMillis": timestamp_in_future,
"autoRenewing": true,
...
"paymentState": 1 # Payment received
}
如果用户在帐号保留期结束之前未修正付款方式,您会收到 SUBSCRIPTION_CANCELED
实时开发者通知。有关处理取消的说明,请参阅订阅取消。当您查询以这种方式取消的订阅时,返回的 expiryTimeMillis
设为过去的时间戳,并且 cancelReason
的值为 1
:
{
"kind": "androidpublisher#subscriptionPurchase",
...
"expiryTimeMillis": timestamp_in_past,
"autoRenewing": false,
...
"cancelReason": 1 # The system cancelled the subscription
}
宽限期
启用宽限期后,如果在结算周期结束时存在付款问题,订阅就会进入宽限期。在此期间,用户应仍有权访问订阅,同时 Google Play 会尝试续订订阅。您可以从 Google Play 管理中心的应用内商品设置中指定宽限期的长度。
如果您的应用仅依赖于 queryPurchases()
来检查用户是否有权访问订阅,则应自动处理宽限期,因为 queryPurchases()
会在购买交易的到期日期之前继续返回已取消的购买交易。
如果您的应用与后端同步订阅状态,则应监听 SUBSCRIPTION_IN_GRACE_PERIOD
实时开发者通知,以便在用户进入宽限期时收到通知。当用户处于宽限期时,订阅资源包含 autoRenewing = true
和 paymentState = 0
(即,待处理)。
{
"kind": "androidpublisher#subscriptionPurchase",
...
"expiryTimeMillis": timestamp_in_future,
"autoRenewing": true,
...
"paymentState": 0 # Payment pending
}
当用户进入宽限期时,应在您的应用中显示一条消息,告诉用户如何修正付款方式。否则,当宽限期结束时,用户会失去对订阅的访问权限。此消息可以深层链接到 Google Play 商店,以帮助用户管理订阅。
一旦用户修正了付款方式,订阅就会续订,而您的应用可以按照续订中的说明处理续订。
如果用户在宽限期内未修正其付款方式,那么订阅会进入帐号保留状态。
已暂停的订阅
您可以通过让用户能够暂停订阅来防止主动取消订阅的用户流失。在您启用暂停功能后,用户可以选择暂停订阅一段时间(介于一周到三个月之间),具体取决于循环周期。启用暂停选项后,它将同时显示在订阅中心和取消流程中。请注意,按年订阅无法暂停,并且一周和三个月的暂停限制随时可能更改。
为了让用户能够暂停订阅,请执行以下操作:
- 登录 Google Play 管理中心。
- 选择您的应用,然后依次转到商店发布 > 应用内商品 > 订阅。
- 展开订阅设置部分。
- 选中启用暂停功能。
只有在当前结算周期结束后,订阅暂停才会生效。订阅暂停后,用户将无法访问订阅。在暂停期结束时,订阅将恢复,并且 Google 会尝试续订订阅。如果恢复成功,订阅将再次变为活动状态。如果由于付款问题导致恢复失败,用户将进入帐号保留状态,如图 1 所示:

用户也可以选择在暂停期内随时手动恢复订阅,如图 2 所示。当用户手动恢复订阅时,结算日期将更改为手动恢复日期。

用户的订阅暂停后,订阅不会由 queryPurchases()
返回。如果恢复了订阅,订阅随后会由 queryPurchases()
返回。
如果您的应用与安全的后端服务器同步订阅状态,则应监听实时开发者通知来维护状态。利用这些通知,还可以在您的应用中通知用户他们已暂停订阅,因而无法访问订阅。您还应使用 Google Play 深层链接来为用户提供一种手动恢复订阅的方法。
当用户发起订阅的暂停时,系统会发送 SUBSCRIPTION_PAUSE_SCHEDULE_CHANGED
实时开发者通知。此时,用户应保持对订阅的访问权限,并且订阅资源包含 autoRenewing = true
、paymentState = 1
(付款已接收),以及 expiryTimeMillis
和 autoResumeTimeMillis
的将来日期值。
当暂停生效时,系统会发送 SUBSCRIPTION_PAUSED
实时开发者通知。此时,用户应失去对订阅的访问权限,并且订阅资源包含 autoRenewing = true
和 paymentState = 0
(待处理),以及 autoResumeTimeMillis
的将来日期值和 expiryTimeMillis
的过去日期值。
如果在暂停期结束时自动恢复了订阅或用户选择了手动恢复订阅,系统会发送 SUBSCRIPTION_RENEWED
实时开发者通知。应按照续订中的说明来处理此事件。
如果尝试恢复订阅时付款失败,系统会发送 SUBSCRIPTION_ON_HOLD
实时开发者通知。应按照帐号保留部分中的说明来处理此事件。
恢复
已取消的订阅会在到期日期之前继续显示在 Play 商店应用中。用户可以通过在 Google Play 商店应用的订阅部分中点击重新订阅(以前称为恢复),在已取消的订阅到期之前恢复订阅。

如果您的应用仅依赖于 queryPurchases()
来确定用户是否有权访问订阅,则应自动处理恢复,因为 queryPurchases()
会在购买交易的到期日期之前继续返回已取消的购买交易。已恢复的订阅会继续续订,就像未取消过一样。
如果您的应用与后端同步订阅状态,则应监听 SUBSCRIPTION_RESTARTED
实时开发者通知。收到该通知后,您的应用可以对其做出响应,记录订阅现已设为续订,并停止在您的应用中显示恢复消息。订阅资源与下面的内容类似:
{
"kind": "androidpublisher#subscriptionPurchase",
...
"expiryTimeMillis": expiry_time_in_future,
"autoRenewing": true,
...
"paymentState": 1 # Payment received
}
升级、降级和重新注册
当用户升级、降级或重新订阅时,旧订阅会变为无效,并且系统会使用一个新的购买令牌创建新订阅。
此外,从 Google Play Developer API 返回的订阅资源将包含一个 linkedPurchaseToken
,用来指示用户升级、降级或重新订阅时所基于的旧购买交易。您可以使用 linkedPurchaseToken
查询旧订阅并识别现有用户帐号,以便将新购买交易与同一帐号关联。此外,我们还建议您使用 Google Play Developer API 确认购买交易,让用户省去一些麻烦。订阅资源与下面的内容类似:
{
"kind": "androidpublisher#subscriptionPurchase",
...
"expiryTimeMillis": next_renewal_date,
"autoRenewing": true,
"linkedPurchaseToken": old_purchase_token
...
"paymentState": 1 # Payment received
}
使用深层链接让用户能够管理订阅
作为开发者,您必须让客户能够轻松地管理订阅。您的应用应在设置或偏好设置屏幕上添加一个链接,让用户能够管理订阅。此链接的示例如图 4 所示。

在此链接的点击处理程序中,添加逻辑以确定用户在您的应用中是否有任何未到期的订阅,其中 expiryTimeMillis
是将来的日期,或者 autoRenewing
设为 true
。
每个订阅的 SKU 都与您在 Play 管理中心创建它时为其分配的商品 ID 相匹配。如需以编程方式确定现有订阅的 SKU,请在应用的后端查询与特定用户关联的订阅列表。
如果用户有未到期的订阅,您可以将其转到与下面类似的网址,应将“your-sub-product-id”和“your-app-package”替换为订阅 ID 和应用软件包信息:
https://play.google.com/store/account/subscriptions?sku=your-sub-product-id&package=your-app-package
如果用户在您的应用中没有任何未到期的订阅,请使用以下网址将用户转到显示其所有其他订阅的页面,如图 5 和图 6 所示:
https://play.google.com/store/account/subscriptions


您可以在 Classy Taxi 示例应用中找到订阅链接逻辑的示例代码。
允许用户升级、降级或更改订阅
您可以为用户提供不同的订阅层级,如基本级和付费级。图 7 显示了一个提供两个订阅层级的屏幕:

用户应该能够访问与图 7 类似的屏幕来升级或降级订阅。升级或降级订阅时,您可以设置按比例计费模式,或者设置变更对订阅者有何影响。下表列出了可用的按比例计费模式:
按比例计费模式 | 说明 |
---|---|
IMMEDIATE_WITH_TIME_PRORATION |
订阅会立即升级或降级。任何剩余时间都会根据差价进行调整,并通过向前推下一个结算日期,将余额记入新订阅。这是默认行为。 |
IMMEDIATE_AND_CHARGE_PRORATED_PRICE |
订阅会立即升级,结算周期保持不变。用户随后需要补足剩余订阅期的差价。 |
IMMEDIATE_WITHOUT_PRORATION |
订阅会立即升级或降级,在订阅续订时将按新价格收取费用。结算周期保持不变。 |
DEFERRED |
只有在订阅续订时,订阅才会升级或降级。 |
按比例计费示例
为了理解各种按比例计费模式的工作原理,我们来考虑下面的场景:
Samwise 订阅了 Country Gardener 应用的在线内容。他当前按月订阅第 1 层级的内容,该内容只包含文字。此订阅的费用为每月 2 美元,并且在每月的第一天续订。
在 4 月 15 日,Samwise 选择升级到第 2 层级按年订阅,该内容包含视频更新,费用为每年 36 美元。
升级订阅时,开发者会选择一种按比例计费模式。以下列表说明了各种按比例计费模式对 Samwise 的订阅有何影响:
IMMEDIATE_WITH_TIME_PRORATION
- Samwise 的第 1 层级订阅会立即终止。由于他支付了整个月(4 月 1 日至 30 日)的费用,但在订阅期刚过一半时升级了订阅,因此剩余半个月的订阅费用(1 美元)会应用到新订阅。不过,由于新订阅的费用为每年 36 美元,1 美元的余额只够 10 天(4 月 16 日至 25 日)的费用,因此在 4 月 26 日,他需要为新订阅支付 36 美元的费用,并且此后每年的 4 月 26 日需要再支付 36 美元。
IMMEDIATE_AND_CHARGE_PRORATED_PRICE
- 可以使用此模式,因为第 2 层级的每时间单位的订阅价格(36 美元/年 = 3 美元/月)大于第 1 层级的每时间单位的订阅价格(2 美元/月)。Samwise 的第 1 层级订阅会立即终止。由于他支付了整个月的费用,但只用了一半,因此剩余半个月的订阅费用(1 美元)会应用到新订阅。不过,由于新订阅的费用为每年 36 美元,剩余 15 天的费用为 1.50 美元,因此他需要为新订阅支付 0.50 美元的差价,并且 5 月 1 日需要再支付 35.50 美元。此后,Samwise 每年都需要支付 36 美元。
IMMEDIATE_WITHOUT_PRORATION
- Samwise 的第 1 层级订阅会立即升级到第 2 层级,无需支付额外的费用,而在 5 月 1 日,他需要为新订阅层级支付 36 美元,并且此后每年的 5 月 1 日都需要再支付 36 美元。
DEFERRED
- Samwise 的第 1 层级订阅会一直持续到 4 月 30 日到期。在 5 月 1 日,第 2 层级订阅开始生效,Samwise 需要为新订阅层级支付 36 美元。
选择按比例计费模式时,请务必查看我们的按比例计费建议。
您的应用可以使用与启动购买流程相同的步骤来为用户提供升级或降级。不过,在升级或降级时,您需要提供当前订阅、将来(升级或降级的)订阅以及要使用的按比例计费模式的详细信息,如以下示例所示:
Kotlin
// Retrieve a value for "skuDetails" by calling querySkuDetailsAsync() val flowParams = BillingFlowParams.newBuilder() .setOldSku(previousSku, purchaseTokenOfOriginalSubscription) .setReplaceSkusProrationMode(desiredProrationMode) .setSkuDetails(upgradeOrDowngradeSkuDetails) .build(); val responseCode = billingClient.launchBillingFlow(activity, flowParams)
Java
// Retrieve a value for "skuDetails" by calling querySkuDetailsAsync() BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder() .setOldSku(previousSku, purchaseTokenOfOriginalSubscription) .setReplaceSkusProrationMode(desiredProrationMode) .setSkuDetails(upgradeOrDowngradeSkuDetails) .build(); int responseCode = billingClient.launchBillingFlow(billingFlowParams);
对于立即替换按比例计费模式,您的应用会在 PurchasesUpdatedListener
中收到新的购买交易。此外,BillingClient.queryPurchases()
中也会提供相应的购买交易。当您收到购买令牌时,请遵循与验证新购买令牌相同的验证流程。请务必使用 Google Play 结算库中的 BillingClient.acknowledgePurchase()
或 Google Play Developer API 中的 Purchases.subscriptions:acknowledge
确认这些购买交易。
Google Play Developer API 会在订阅资源中返回一个 linkedPurchaseToken
。请务必使在 linkedPurchaseToken
中提供的令牌无效,以确保旧令牌不会被用于获取对您的服务的访问权限。如需了解如何处理升级购买交易和降级购买交易,请参阅升级、降级和重新注册。
对于延迟替换模式,您的应用会收到对 PurchasesUpdatedListener
的调用,其中包含空的购买交易列表,以及表明升级或降级是否成功的状态。在替换生效之前,BillingClient.queryPurchases()
会继续返回原始订阅方案的购买交易。新方案生效后,queryPurchases()
会返回新订阅的购买交易数据,并且系统会向安全的后端服务器发送 SUBSCRIPTION_RENEWED
通知。对于延迟替换,强烈建议监听此通知,并使用 Purchases.subscriptions:acknowledge
确认购买交易。订阅资源中的 linkedPurchaseToken
可用于确定订阅后端的哪个用户(如果适用)应更新为拥有新的权利。您的应用不应依赖于用户打开应用并通过 BillingClient.acknowledgePurchase()
确认,因为用户在方案变更生效后的三天内可能不会打开应用。
在享受免费试订或初次体验价优惠期间升级
当用户升级或降级时,会应用免费试订资格设置。您可以在 Google Play 管理中心内调整免费试订资格设置。
请注意以下几点:
- 如果对于您的应用中提供的所有订阅,用户只能获得一次免费试订机会,则用户要改用的方案将没有免费试订或初次体验价。
- 如果您针对每种订阅产品提供一次免费试订机会,则用户要改用的方案可以有免费试订或初次体验价。
下表说明了当新方案和旧方案都有免费试订且用户在免费试订期间升级时各种按比例计费模式的行为:
在每个应用中免费试订一次 | 每种订阅产品免费试订一次 | |
IMMEDIATE_WITH_TIME_PRORATION | 用户会立即失去免费试订资格。剩余的免费试订期会根据差价转换为新层级的等效免费期。 | 用户会失去之前的免费试订资格,但会立即开始新的免费试订。此外,旧层级的剩余免费试订期会转换为新层级的等效免费期,并添加到新的免费试订。 |
IMMEDIATE_AND_CHARGE_PRORATED_PRICE |
用户会立即失去免费试订资格。用户随后需要补足剩余订阅期的差价。下一个结算日期保持不变。 注意:此选项仅适用于每时间单位的价格提高的订阅升级。 |
|
IMMEDIATE_WITHOUT_PRORATION | 用户会立即升级到新层级。用户可以一直免费试订新层级的内容,直到上一个结算周期结束。 | |
DEFERRED | 用户可以一直免费试订旧订阅内容,直到下一个结算日期。 |
为了理解在每个应用中免费试订一次的默认情况下免费试订过渡的工作原理,我们来考虑下面的场景:
Maria 订阅了 Country Gardener 应用的在线内容。她当前按月订阅第 1 层级的内容,该内容只包含文字。此订阅的费用为每月 10 美元,并且她是在 4 月 1 日订阅的。作为首次订阅者,她可以享受 30 天的免费试订服务,这意味着,她应于 5 月 1 日支付第一笔订阅费用。
在 4 月 15 日,Maria 选择升级到第 2 层级订阅,该内容包含视频更新,费用为 20 美元/月。这第二次订阅也有 30 天的试订服务。
以下列表说明了在各种按比例计费模式下如何进行免费试订过渡:
IMMEDIATE_WITH_TIME_PRORATION
- Maria 会立即升级到第 2 层级。由于 Maria 在订阅期刚过一半时升级了订阅,因此剩余半个月的订阅费用(15 天的金额,按 10 美元/月计算)会应用到新订阅。不过,由于新订阅的费用为 20 美元/月,因此 15 天的余额只够 7.5 天的费用。Maria 没有资格再享受一次第 2 层级的免费试订服务,所以自 4 月 22 日起,她每月需要支付 20 美元。IMMEDIATE_AND_CHARGE_PRORATED_PRICE
- 可以使用此模式,因为第 2 层级的每时间单位的订阅价格(20 美元/月)大于第 1 层级的每时间单位的订阅价格(10 美元/月)。Maria 的第 1 层级订阅会立即升级到第 2 层级,并且她会失去免费试订资格。由于 Maria 的下一个结算日期是在 5 月 1 日,因此她今天需要支付 10 美元,这是 4 月份下半月的费用,然后自 5 月 1 日起,她每月需要支付 20 美元。IMMEDIATE_WITHOUT_PRORATION
- Maria 的第 1 层级订阅会立即升级到第 2 层级。Maria 可以免费试订到 4 月 30 日,并且现在可以访问第 2 层级的内容。自 5 月 1 日起,她每月需要支付 20 美元。DEFERRED
- Maria 的第 1 层级订阅一直持续到下次付款日,即 5 月 1 日。在 5 月 1 日,第 2 层级订阅开始生效,Maria 需要在每月的第一天支付 20 美元。
以下列表说明了开发者允许每种订阅产品免费试订一次时的过渡行为:
IMMEDIATE_WITH_TIME_PRORATION
- Maria 会立即升级到第 2 层级。由于 Maria 在订阅期刚过一半时升级了订阅,因此剩余半个月的订阅费用(15 天的金额,按 10 美元/月计算)会应用到新订阅。不过,由于新订阅的费用为 20 美元/月,因此 15 天的余额只够 7.5 天的费用。Maria 有资格再享受一次第 2 层级的免费试订服务,所以她又有 37.5 天免费。自 5 月 22 日起,她每月需要支付 20 美元。IMMEDIATE_AND_CHARGE_PRORATED_PRICE
- 可以使用此模式,因为第 2 层级的每时间单位的订阅价格(20 美元/月)大于第 1 层级的每时间单位的订阅价格(10 美元/月)。Maria 的第 1 层级订阅会立即升级到第 2 层级,并且她会失去免费试订资格。由于 Maria 的下一个结算日期是在 5 月 1 日,因此她今天需要支付 10 美元,这是 4 月份下半月的费用,然后自 5 月 1 日起,她每月需要支付 20 美元。IMMEDIATE_WITHOUT_PRORATION
- Maria 的第 1 层级订阅会立即升级到第 2 层级。Maria 可以免费试订到 4 月 30 日,并且现在可以访问 *DEFERRED
- Maria 的第 1 层级订阅一直持续到下次付款日,即 5 月 1 日。在 5 月 1 日,第 2 层级订阅开始生效,Maria 需要在每月的第一天支付 20 美元。
按比例计费建议
下表显示了不同的按比例计费场景以及我们针对各种场景给出的建议:
场景 | 建议的按比例计费模式 | 结果 |
---|---|---|
升级到费用更高的层级 | IMMEDIATE_AND_CHARGE_PRORATED_PRICE |
用户会立即获得访问权限,而结算周期保持不变。 |
降级到费用更低的层级 | DEFERRED |
用户已经为费用更高的层级付款,因此他们将保有访问权限,直到下一个结算日期。 |
更改同一层级的循环周期(例如,从按月订阅更改为按年订阅) | DEFERRED |
用户将在下一个结算日期按新的周期性价格支付。 |
在免费试订期间升级 - 保留对免费试订的访问权限 | IMMEDIATE_WITHOUT_PRORATION |
用户会保有对免费试订的访问权限,但试订期的剩余时间会升级到更高的层级。 |
在免费试订期间升级 - 终止对免费试订的访问权限 | IMMEDIATE_AND_CHARGE_PRORATED_PRICE |
用户会立即获得对新层级的访问权限,但不能再免费试订。 |
流失后赢回
在用户取消订阅后,您可以尝试在应用内或通过 Play 商店赢回他们。下表介绍了各种订阅场景以及相关的赢回操作和应用要求。
订阅到期之前 | 订阅到期之后 | |||
应用内 | Play 商店内 | 应用内 | Play 商店内 | |
赢回功能 | 应用内订阅 | 恢复 | 应用内订阅 | 重新订阅 |
用户完成结帐流程 | 是 | 不可以 | 是 | 是 |
用户订阅仍与同一 SKU 关联 | 用户可以注册相同或不同的 SKU | 是 | 用户可以注册相同或不同的 SKU | 是 |
创建新的购买令牌 | 是 | 不可以 | 是 | 是 |
默认处于启用状态 | 否 | 是,所有开发者都需要支持 | 否 |
未采用结算库 2.0 及以上版本的应用:否 采用结算库 2.0 及以上版本的应用:是。开发者可以在管理中心中选择停用该功能。 |
何时向用户收取费用 |
如果使用相同的 SKU:当前结算周期结束时。 如果使用不同的 SKU:取决于按比例计费模式。 |
当前结算周期结束时 | 立即 | 立即 |
所需实现 | 在应用中提供重新注册界面 |
检测订阅状态的变化 指向 Play 商店的深层链接 |
在应用中提供重新注册界面 | 处理应用外购买 |
订阅到期之前 - 应用内
对于已被取消但尚未过期的订阅,您可以通过应用与新订阅者相同的应用内商品购买流程,允许订阅者在您的应用中恢复他们的订阅。请确保界面中会显示用户的现有订阅。例如,您不妨显示用户当前的到期日期、定期支付的费用以及重新激活按钮。
大多数情况下,建议您向用户提供与已订阅内容相同的价格和 SKU,如下所示:
- 使用同一个 SKU 发起新的订阅购买。
- 新订阅将替换旧订阅,并在同一到期日期续订。旧订阅会立即标记为“已过期”。
- 例如,小张订阅了一款示例音乐应用的内容且订阅的到期日期为 8 月 1 日。在 7 月 10 日,他以相同的每月价格重新订阅了一个月的订阅内容。系统会根据余额按比例计算新订阅的费用,新订阅会立即生效,并且仍在 8 月 1 日续订。
如果您想提供不同的价格(例如,新的免费试订或赢回折扣),则可以改为为用户提供不同的 SKU:
- 使用采用了按比例计费模式
IMMEDIATE_WITHOUT_PRORATION
的不同 SKU 发起升级或降级。 - 新订阅将替换旧订阅,并在同一到期日期续订。在原始到期日期那天,用户会按新 SKU 的价格付费(包括所有初次体验价)。
- 例如,小张订阅了一款示例音乐应用的内容且订阅的到期日期为 8 月 1 日。在 7 月 10 日,他以初次体验价重新订阅了按年订阅的内容。新订阅会立即生效,并且用户将在 8 月 1 日按初次体验价付费。
- 如果您决定在赢回 SKU 中添加免费试订或初次体验价,请确保用户有资格享受这些优惠,方法是在 Google Play 管理中心取消选中允许在每个应用中免费试订一次复选框,选中该复选框会限制用户在每个应用中只能免费试订一次。
当您收到购买令牌时,应该就像处理新订阅一样来处理购买交易。此外,Google Play Developer API 还会在订阅资源中返回一个 linkedPurchaseToken
。请务必让 linkedPurchaseToken
中提供的令牌失效,以确保旧令牌不会被用于获取对您服务的访问权限。
订阅到期之前 - Play 商店内
在订阅被取消但仍然处于有效状态时,用户可以通过点击重新订阅(以前称为恢复)在 Google Play 订阅中心恢复订阅。这样会让订阅和购买令牌保持不变。

如需详细了解如何恢复订阅,请参阅恢复。
订阅到期之后 - 应用内
您可以允许订阅已过期的订阅者在您的应用中重新订阅,方法是应用与新订阅者相同的应用内商品购买流程。不过,请注意以下几点:
- 为了给用户提供折扣,您可能需要为您的订阅提供一个具有特殊定价的商品 ID,也称为“赢回 SKU”。您可以在应用中提供优惠,也可以在应用外(如通过电子邮件)通知用户优惠活动。
- 为了开始赢回订阅,请使用 Google Play 结算库在您的 Android 应用中启动购买流程。这与新订阅的流程相同,但您可以确定提供给用户的 SKU。
- 如果您决定在赢回 SKU 中添加免费试订或初次体验价,请确保用户有资格享受这些优惠,方法是在 Google Play 管理中心取消选中允许在每个应用中免费试订一次复选框,选中该复选框会限制用户在每个应用中只能免费试订一次。
- 如果用户重新订阅同一 SKU,便没有资格再享受免费试订或初次体验价。请务必在界面中说明这一点。
当您收到购买令牌时,应该就像处理新订阅一样来处理购买交易。您将不会在订阅资源中收到 linkedPurchaseToken
。
订阅到期之后 - Play 商店内
如果您启用了重新订阅功能,用户便可通过在 Google Play 订阅中心点击重新订阅来重新订阅同一 SKU(最长一年)。这样会生成新的订阅和购买令牌。

重新订阅属于应用外购买,因此请务必遵循处理在您的应用外进行的购买交易中介绍的最佳做法。
客户管理
使用实时开发者通知,当用户决定取消订阅时,您可以实时检测到。如果用户在订阅到期之前取消了订阅,您可以向他们发送推送通知或应用内消息,让他们重新订阅。如需了解详情,请参阅流失后赢回。
免费试订和初次体验价
您的应用可以提供免费试订和初次体验价,以鼓励客户试用您的应用。
免费试订
您可以让用户先试订,然后再付款。免费试订的持续时间由您自行指定,免费试订期结束后,免费试订会自动转换为全价订阅。这些转换后的订阅使用的期长和价格与普通订阅相同。您可以针对任何类型的订阅设置免费试订。
为了开始免费试订,用户需完成在 Google Play 上购买订阅的标准流程。如果用户有资格免费试订,他们在免费试订期间无需支付费用,并且系统会通过电子邮件通知他们,订阅包含免费试订期。Google Play 会将交易金额记录为 0 美元,并且订阅在试订期内或被取消之前会被标记为“已购买”。
在开始免费试订之前,Google Play 会验证用户是否具有有效的付款方式。某些用户可能会看到此验证的结果显示为付款方式被暂停或产生扣款。这种暂停或扣款是暂时的,稍后会撤消或退还。
试订期结束后,系统会通过用户的付款方式,按照全价收取订阅费用。
如果用户在免费试订期间的任一时刻取消了订阅,订阅将保持活动状态,直到试订期结束,当免费试订期结束时,不会向用户收取费用。
默认情况下,对于您的应用中提供的所有订阅,用户只能获得一次免费试订机会。如果您希望针对每种订阅产品提供一次免费试订机会,可以在 Google Play 管理中心更改相应的设置。
如需向订阅添加免费试订,请参阅 Google Play 帮助中心的免费试订说明。
包含免费试订的订阅的订阅生命周期事件的工作方式与不含免费试订的订阅相同。唯一的区别在于,续订期可能不同于常规订阅续订间隔。
向用户展示可供销售的商品时,您可以使用 SkuDetails.getFreeTrialPeriod()
方法显示商品可免费试订。
如果购买的订阅提供免费试订,则从 Google Play Developer API 返回的订阅具有 paymentState = 2
属性(免费试订)。如果订阅成功续订,则 paymentState
会改为 1
(付款已接收)。
初次体验价
与免费试订类似,您的应用也可以提供初次体验价,以鼓励用户试用您的应用。如需详细了解初次体验价以及如何启用,请参阅创建订阅。
包含初次体验价的订阅的订阅生命周期事件的工作方式与不含初次体验价的订阅相同。唯一的区别在于,续订期可能不同于常规订阅续订间隔。
向用户展示可供销售的商品时,您可以使用 SkuDetails.getIntroductoryPrice()
以及相关的方法向用户显示订阅有初次体验价。
宣传您的订阅
您可以创建促销代码,让部分用户能够免费试订现有的订阅 SKU 更长时间。如需了解详情,请参阅促销代码。
取消、退款或撤消
您可以使用 Google Play Developer API 取消订阅、为订阅退款或撤消订阅。Google Play 管理中心也提供了此功能。
- 取消:用户可以在 Google Play 上取消订阅。您也可以为用户提供一个在您的应用中或您的网站上取消订阅的选项。您的应用应按照撤消中的说明来处理这些取消事件。
- 退款:当您退款时,用户可以继续使用订阅内容。例如,如果因技术错误而导致用户无法访问您的商品,但该错误已得到解决,则可以使用退款。请注意,如果要退还的不只是最近一次的付款,或者如果您要办理部分退款,必须使用 Google Play 管理中心。
- 撤消:当您撤消时,用户会立即失去对订阅的访问权限。例如,如果因技术错误而导致用户无法访问您的商品,因而用户不想继续使用该商品,则可以使用此选项。您的应用应按照撤消中的说明来处理这些取消事件。
下表说明了取消、退款和撤消之间的区别。
停止续订 | 退还款项 | 撤消访问权限 | |
取消 | 是 | 否 | 否 |
退款 | 否 | 是 | 否 |
撤消 | 是 | 是 | 是 |
为订阅者推迟结算
您可以使用 Google Play Developer API 中的 Purchases.subscriptions:defer 将订阅者的下一个结算日期向前推。在推迟期内,用户会订阅您的内容并且拥有完全访问权限,但不会被扣款。订阅续订日期会更新以反映新的日期。
推迟结算可让您做到以下几点:
- 将免费访问权限作为一种特别优惠提供给用户,如购买电影时免费一周。
- 将免费访问权限作为一种善意的表示提供给客户。
每次调用该 API,结算最短可推迟一天,最长为一年。如需进一步推迟结算,您可以在新的结算日期到来之前再次调用该 API。
例如,Darcy 按月订阅了 Fishing Quarterly 应用的在线内容。正常情况下,她在每个月第一天都需要支付 1.25 英镑的费用。在 3 月,她参与了应用发布商的在线调查活动。该发布商为她提供了免费六周的奖励,将下一笔付款推迟到 5 月 15 日,也就是在她先前预定结算日期(即 4 月 1 日)的六周后。Darcy 不需要支付 4 月或 5 月初的费用,并且仍能访问相关内容。在 5 月 15 日,她支付了当月 1.25 英镑的正常订阅费用。她的下一个续订日期现在为 6 月 15 日。
推迟结算时,您可能需要通过电子邮件或在应用中通知用户,告知用户他们的结算日期发生了变化。
更改订阅价格
警告:您不应更改通过 Google 订阅的订阅价格。
Google Play 可让您将数字产品销售给世界各地的众多用户,这些用户位于不同的语言区域,而这些语言区域在货币和定价方面有着不同的考虑因素。有时,由于区域性费用或币值波动,您可能决定需要更改订阅价格。如果您愿意继续让现有订阅者按现有价格支付费用,则可以创建一个新的 SKU,让其采用更新后的价格,并将该 SKU 提供给新订阅者。
如果您不能继续让订阅者按他们在为订阅注册时为其提供的价格支付费用,并且愿意为决定不接受新价格的用户取消所有订阅,则可以强制执行价格变动。如果用户不同意新价格,他们的订阅会被取消。为了最大限度地提高选择接受率并鼓励用户采取行动,您的应用应向用户显示相关的消息,告知他们即将发生的价格变动。如需详细了解价格变动消息,请参阅通知价格变动。
如需更改订阅价格,请执行以下操作:
- 登录 Google Play 管理中心。
- 找到包含您想要更改价格的订阅的应用。
- 依次选择商店发布 > 应用内商品,然后打开订阅标签页。
选择您要更改的价格旁边的修改链接,如图 10 所示:
图 10. 修改订阅价格字段。 输入新的订阅价格。
当您更改价格时,系统会显示一个确认对话框,如图 11 所示。
图 11. 当您修改订阅价格时,系统会显示一条警告。 此对话框说明了价格变动对新订阅者和现有订阅者有何影响。请注意以下几点:
- 价格变动一旦确认,便无法撤消。
- Google Play 从确认后七天开始通知用户价格变动。
- 如果订阅价格上调,用户必须在 30 天内批准价格变动,否则他们的订阅会自动取消。
- 如果订阅价格下调,对于现有订阅者,会在下一个续订日期自动应用这一价格变动。对于在价格下调后订阅的所有用户,会自动实行下调后的价格。
点击应用以继续。
系统会显示一个确认对话框,再次说明新订阅价格何时生效。
图 12. 显示订阅价格变动何时生效的确认对话框。
通知用户价格变动
每当您做出价格变动时,都应通知现有订阅者,尤其是在价格上调时。
当您上调订阅价格时,Google Play 至少要过七天才会通知您的现有订阅者;也就是说,您可以在此期间提前通知他们价格变动的消息。当 Google Play 通知用户时,它会显示一个类似于图 13 中所示的对话框。此对话框会显示旧价格、新价格以及新价格的生效日期。

在您的应用中,您可以通过以下方式显示此对话框:
- 当用户打开您的应用时,启动价格变动确认流程。
- 将用户引导至订阅中心,以使用深层链接查看价格变动。
您的应用可以查看订阅资源中的 priceChange
字段来确定用户是否有待处理的价格变动。如果存在此字段,它指示订阅发生了价格变动,而 priceChange.state
字段指示价格变动是已被接受还是未决。
启动价格变动确认流程
如需在您的应用启动时显示 Google Play 价格变动对话框,请使用 BillingClient.launchPriceChangeConfirmationFlow()
。
在显示价格变动对话框之前,您也可以显示自己的消息或对话框来解释价格变动背后的原因。如果您创建并显示这种类型的自定义消息,则用户更有可能以新价格续订。
下面是启动价格变动确认流程的示例:
Kotlin
val priceChangeFlowParams = PriceChangeFlowParams.newBuilder() .setSkuDetails(changedPriceSubscriptionSkuDetails) .build() billingClient.launchPriceChangeConfirmationFlow(activity, priceChangeFlowParams, object : PriceChangeConfirmationListener() { override fun onPriceChangeConfirmationResult(responseCode: Int) { if (responseCode == BillingResponseCode.OK) { // User has confirmed the price change. } else if (responseCode == BillingResponseCode.USER_CANCELED) { // User hasn't confirmed the price change and should retain // access until the end of the current billing cycle. } } })
Java
PriceChangeFlowParams priceChangeFlowParams = PriceChangeFlowParams.newBuilder() .setSkuDetails(changedPriceSubscriptionSkuDetails) .build(); billingClient.launchPriceChangeConfirmationFlow(activity, priceChangeFlowParams, new PriceChangeConfirmationListener() { @Override public void onPriceChangeConfirmationResult(int responseCode) { if (responseCode == BillingResponseCode.OK) { // User has confirmed the price change. } else if (responseCode == BillingResponseCode.USER_CANCELED) { // User hasn't confirmed the price change and should retain // access until the end of the current billing cycle. } } });
处理用户对价格变动的确认
如果用户接受订阅的新价格,订阅会续订,并且可以像其他任何续订一样进行处理。此外,您还会收到 SUBSCRIPTION_PRICE_CHANGE_CONFIRMED
实时开发者通知。
处理价格变动被拒情况
如果用户在旧订阅到期时尚未接受价格变动,则会变为退订,并且您会收到 SUBSCRIPTION_CANCELED
通知。可以按照取消中的说明来处理此事件。
意外价格变动
如果您意外地更改了订阅价格,应立即撤消所做的更改。只要价格在七天内还原,现有订阅者就不会收到有关意外价格变动的通知。请注意,在第一次价格变动到还原期间,新订阅者可能会收到意外价格。
连续做出两次价格变动
您应确保在某一时间只做出一次价格变动。不建议将价格变动用于测试目的。
如果您在七天内先后两次更改了订阅价格,用户只需同意最新的价格变动。
如果价格变动的间隔超过了七天,价格变动不会相互抵消。相反,用户必须同意第一次的价格变动,并且有一个续订周期采用第一次的价格。该续订周期结束后,您便可以开始按第二次的价格收取费用。此后,每个月按第二次的价格收取续订费用。