If I Raise My Subscriber Tier Do I Get Charged Again

This topic describes how to handle subscription lifecycle events, such as renewals and expirations. It also describes additional subscription features such as offering promotions and allowing your users to manage their own subscriptions.

Before reading this topic, be sure you've read Integrate the Google Play Billing Library into your app for general instructions on how to sell and manage products in your app.

If you haven't configured subscription products for your app, see Create and configure your products.

Subscriptions overview

A subscription represents a set of benefits users can access during a specified time period. For example, a subscription might entitle a user to access a music streaming service.

You can have multiple subscriptions within the same app, either to represent different sets of benefits, or different tiers of a single set of benefits ("Silver" and "Gold" tiers, for example).

Through base plans and offers, you can create multiple configurations for the same subscription product. For example, you can create an introductory offer for users who have never subscribed to your app. Similarly, you can create an upgrade offer for users who are already subscribed.

For a detailed overview of subscription products, base plans, and offers, see the documentation in the Play Console Help Center.

Handling the subscription lifecycle

A purchased subscription can go through various state changes throughout its lifecycle, and your app needs to respond to each change. To check the subscription's state, your app can query using either BillingClient.queryPurchasesAsync() in the Google Play Billing Library or Purchases.subscriptionsv2:get in the Google Play Developer API.

BillingClient.queryPurchasesAsync() Purchases.subscriptionsv2:get
State Is returned? isAutoRenewing Is returned? expiryTime subscriptionState autoRenewing
Active Yes True Yes Future SUBSCRIPTION_STATE_ACTIVE True
Canceled Yes False Yes Future SUBSCRIPTION_STATE_CANCELED False
In grace period Yes True Yes Future (end of grace period) SUBSCRIPTION_STATE_IN_GRACE_PERIOD True
On hold No N/A Yes Past (end of expected expiration time, or end of grace period, if any) SUBSCRIPTION_STATE_ON_HOLD True
Paused No N/A Yes Past SUBSCRIPTION_STATE_PAUSED True
Expired No N/A Yes Past SUBSCRIPTION_STATE_EXPIRED False

If your app stores subscription state on a secure backend server, you should listen for state changes using Real-time developer notifications to ensure state is kept in-sync. A SubscriptionNotification is sent for events affecting subscription state such as renewals and cancellations.

Your app needs to handle the state changes that are described in the following sections.

New subscriptions

Be sure to follow our recommendations for handling new purchases. When a subscription is purchased, the subscription is then returned by BillingClient.queryPurchasesAsync(), and a SubscriptionNotification with type SUBSCRIPTION_PURCHASED notification is sent. When you receive this notification, you should query the Google Play Developer API to get the latest subscription state. The subscription resource looks similar to the following example. Note that the resource will have an acknowledgementState of ACKNOWLEDGEMENT_STATE_PENDING until you acknowledge the purchase:

          {   "kind": "androidpublisher#subscriptionPurchaseV2",   "startTime": "2022-04-22T18:39:58.270Z",   "regionCode": "US",   "subscriptionState": "SUBSCRIPTION_STATE_ACTIVE",   "latestOrderId": "GPA.3333-4137-0319-36762",   "acknowledgementState": "ACKNOWLEDGEMENT_STATE_PENDING", // need to acknowledge new purchases   "lineItems": [     {       "productId": "sub_variant_plan01",       "expiryTime": next_renewal_date,       "autoRenewingPlan": {         "autoRenewEnabled": true       }     }   ], }                  

Renewals

If a subscription renews succesfully, the subscription continues to be returned by BillingClient.queryPurchasesAsync().

A SUBSCRIPTION_RENEWED notification is also sent when a subscription renews. Your app should make sure the user is still entitled to the subscription and then update the subscription state with the new expiryTime provided in the subscription resource returned from the Google Play Developer API. The subscription resource looks similar to the following:

          {   "kind": "androidpublisher#subscriptionPurchaseV2",   "startTime": "2022-04-22T18:39:58.270Z",   "regionCode": "US",   "subscriptionState": "SUBSCRIPTION_STATE_ACTIVE",   "latestOrderId": "GPA.3333-4137-0319-36762",   "acknowledgementState": "ACKNOWLEDGEMENT_STATE_ACKNOWLEDGED",   "lineItems": [     {       "productId": "sub_variant_plan01",       "expiryTime": next_renewal_date,       "autoRenewingPlan": {         "autoRenewEnabled": true       }     }   ] }                  

Expirations

Once a subscription expires, the subscription is no longer returned in BillingClient.queryPurchasesAsync() and the user should lose access to the subscription.

A SubscriptionNotification with type SUBSCRIPTION_EXPIRED is also sent when a subscription expires. When you receive this notification, you should query the Google Play Developer API to get the latest subscription state. The subscription resource looks similar to the following:

          {   "kind": "androidpublisher#subscriptionPurchaseV2",   ...   "subscriptionState": "SUBSCRIPTION_STATE_EXPIRED",   ...   "lineItems": [     {       "productId": "sub_variant_plan01",       "expiryTime": expiration_time_in_past,       ...     }   ], }                  

Cancellations

A user can voluntarily cancel a subscription from the Play Store or have their subscription automatically cancelled if they don't recover after being in account hold. When a user cancels a subscription they retain access to the content until the end of the current billing cycle. When the billing cycle ends, access is revoked.

When a subscription is cancelled but not yet expired, it is returned from BillingClient.queryPurchasesAsync(). Cancelling a subscription triggers a SUBSCRIPTION_CANCELED notification. When you receive this notification, the subscription resource returned from the Google Play Developer API contains autoRenewing = false, and the expiryTime contains the date when the user should lose access to the subscription. If expiryTime is in the past, then the user loses entitlement immediately. Otherwise, the user should retain entitlement until it is expired. The subscription resource looks similar to the following:

          {   "kind": "androidpublisher#subscriptionPurchaseV2",   ...   "subscriptionState": "SUBSCRIPTION_STATE_CANCELED",   ...   "lineItems": [     {       "productId": "sub_variant_plan01",       "expiryTime": expiration_time,       ...     }   ], }                  

You app can look at the cancelReason in the subscription resource returned from the Google Play Developer API to learn why the subscription was cancelled (e.g. the customer cancelled or had billing issues). If the subscription was cancelled by the user, you can look at the cancelSurveyResult field to learn why the user cancelled the subscription.

Your app might want to display a message in your app informing the user that their subscription was cancelled, such as "Your subscription will expire on _somedate. Your app can also deep link to the Google Play Store to let users restore their subscription.

If you display this message, you should also offer users the ability to permanently dismiss the message.

Note also that cancellation messages might frustrate users, especially users who manually cancelled a subscription as opposed to having their subscription cancelled because their payment was outdated. You might choose not to inform users who manually cancelled a subscription.

Revocations

A subscription can be revoked from a user for a variety of reasons, including your app revoking the subscription by using Purchases.subscriptions:revoke or the purchase being charged back. In this situation, your app should revoke entitlement from the user immediately. A revoked subscription is no longer returned from BillingClient.queryPurchasesAsync(). A SubscriptionNotification with type SUBSCRIPTION_REVOKED is also sent when this occurs. When you receive this notification, the subscription resource returned from the Google Play Developer API contains autoRenewing = false, and expiryTime contains the date when the user should lose access to the subscription. The subscription resource looks similar to the following:

          {   "kind": "androidpublisher#subscriptionPurchaseV2",   ...   "subscriptionState": "SUBSCRIPTION_STATE_ACTIVE",   ...   "lineItems": [     {       "productId": "sub_variant_plan01",       "expiryTime": expiration_time,       ...     }   ], }                  

Account hold

Account hold is a subscription state that begins when a user's form of payment fails and any associated grace period has ended without payment resolution. When a subscription enters into account hold, you should block access to your content or service. The account hold period lasts for up to 30 days.

During account hold, the subscription is not returned by BillingClient.queryPurchasesAsync().

During account hold, you should handle any cancellations, restorations, or repurchases of your subscriptions as needed.

When a user enters into account hold, you should leverage Real-time developer notifications to inform your user why access to the subscription was suspended. Within your app, you should provide a message with instructions on how to fix their payment method and regain access to the subscription. Your message should include a link to the Google Play subscription settings so that they can fix their payment method. As an example, you might use a message similar to the following:

          "There is a problem with your subscription. Click here to go to the Google Play subscription settings to fix your payment method."                  

If your users can access subscription content outside of your app, you might want to send a push notification or an email to the user to let them know that their subscription is no longer active.

If your customer was able to fix their payment issue, you can display a message in your app informing users when their subscription was restored. As an example, you might use a message similar to the following:

          "Your form of payment was updated, and your subscription has been recovered."                  

With Real-time developer notifications, you receive a SubscriptionNotification with type SUBSCRIPTION_ON_HOLD when a subscription enters account hold. Call the Google Play Developer API from your secure backend server to retrieve the new subscription information. During account hold, the expiryTime of the subscription resource is set to a past timestamp:

          {   "kind": "androidpublisher#subscriptionPurchaseV2",   ...   "subscriptionState": "SUBSCRIPTION_STATE_ON_HOLD",   ...   "lineItems": [     {       "productId": "sub_variant_plan01",       "expiryTime": timestamp_in_past,       ...     }   ], }                  

Once the user fixes their payment method, the subscription returns to an active state, and you must then restore access to the subscribed content.

If your app relies solely on queryPurchasesAsync() to determine whether a user is entitled to a subscription, then your app should automatically handle the subscription recovering from account hold.

If your app synchronizes subscription state with a server, you should listen for SubscriptionNotification with type SUBSCRIPTION_RECOVERED to be notified when a subscription is recovered and the user should regain access. If you query for a subscription after receiving this notification, the expiryTime is now set to a timestamp in the future:

          {   "kind": "androidpublisher#subscriptionPurchaseV2",   ...   "subscriptionState": "SUBSCRIPTION_STATE_ACTIVE",   ...   "lineItems": [     {       "productId": "sub_variant_plan01",       "expiryTime": next_renewal_date,       ...     }   ], }                  

If the user does not fix their payment method before the end of the account hold period, you receive a SUBSCRIPTION_CANCELED Real-time developer notification. For instructions on handling a cancellation, see subscription cancellations. When you query for the subscription that was cancelled in this way, the returned expiryTime is set to a past timestamp:

          {   "kind": "androidpublisher#subscriptionPurchaseV2",   ...   "subscriptionState": "SUBSCRIPTION_STATE_CANCELED",   ...   "lineItems": [     {       "productId": "sub_variant_plan01",       "expiryTime": timestamp_in_past,       ...     }   ], }                  

Grace period

If grace period is enabled, subscriptions enter grace period if there are payment issues at the end of a billing cycle. During this time, the user should still have access to the subscription while Google Play tries to renew the subscription. You can specify the length of a grace period from the in-app product settings in the Google Play Console.

If your app relies solely on queryPurchasesAsync() to check whether a user is entitled to a subscription, then your app should automatically handle grace period, as queryPurchasesAsync() continues to return cancelled purchases before their expiration dates.

If your app synchronizes subscription state with a backend, you should listen for the SubscriptionNotification with type SUBSCRIPTION_IN_GRACE_PERIOD to be notified when the user enters a grace period. While the user is in a grace period, the subscription resource contains autoRenewEnabled = true.

          {   "kind": "androidpublisher#subscriptionPurchaseV2",   ...   "subscriptionState": "SUBSCRIPTION_STATE_IN_GRACE_PERIOD",   ...   "lineItems": [     {       "productId": "sub_variant_plan01",       "expiryTime": timestamp_in_future,       "autoRenewingPlan": {         "autoRenewEnabled": true       }     }   ], }                  

When a user enters a grace period, you should display a message in your app that tells users how to fix their payment method. Otherwise, the user loses access to subscription when the grace period ends. This message can deep link to the Google Play Store to help the user manage their subscription.

As soon as the user fixes their payment method, the subscription renews, and your app can handle the renewal as described in renewals.

If the user does not fix their payment method during grace period, the subscription enters account hold.

Paused subscriptions

You can prevent voluntary churn by enabling users to pause their subscription. When you enable the pause feature, users can choose to pause their subscription for a period of time between one week and three months, depending on the recurring period. Once enabled, the pause option surfaces both in the subscriptions center and in the cancel flow. Note that annual subscriptions cannot be paused, and the pause limits of one week and three months are subject to change at any time.

To enable users to pause their subscription, do the following:

  1. Sign in to the Google Play Console.
  2. Select your app, and then go to Store presence > In-app products > Subscriptions.
  3. Expand the Subscription settings section.
  4. Check Activate Pause.

A subscription pause takes effect only after the current billing period ends. While the subscription is paused, the user doesn't have access to the subscription. At the end of the pause period, the subscription resumes, and Google attempts to renew the subscription. If the resume is successful, the subscription becomes active again. If the resume fails due to a payment issue, the user enters the account hold state, as shown in figure 1:

A user pauses their subscription and then enters account hold
Figure 1. A user pauses their subscription and then enters account hold.

A user can also choose to manually resume a subscription at any time during the pause period, as shown in figure 2. When a user resumes manually, the billing date changes to the manual resume date.

A user pauses and then resumes their subscription
Figure 2. A user pauses and then resumes their subscription.

When a user's subscription is paused, the subscription is not returned by queryPurchasesAsync(). If the subscription is resumed, the subscription is then returned by queryPurchasesAsync().

If your app synchronizes subscription state with a secure backend server, you should listen to Real-time developer notifications to maintain state. These notifications also allow you to notify your users in your app that they have paused their subscription and don't have access to it. You should also provide a way for the user to manually resume the subscription by using a deep link to Google Play.

A SubscriptionNotification with type SUBSCRIPTION_PAUSE_SCHEDULE_CHANGED is sent when your user initiates a pause of their subscription. At this time, the user should keep access to their subscription, and the subscription resource contains autoRenewing = true, paymentState = 1 (Payment Received), and future values for expiryTime and autoResumeTimeMillis.

A SubscriptionNotification with type SUBSCRIPTION_PAUSED is sent when the pause goes into effect. At this time, the user should lose access to their subscription, and the subscription resource contains autoRenewing = true, and paymentState = 0 (pending), a future value for autoResumeTimeMillis, and a past value for expiryTime.

A SubscriptionNotification with type SUBSCRIPTION_RENEWED is sent if the subscription is resumed either automatically at the end of the pause period or if the user chose to manually resume the subscription. This should be handled as described in renewals.

A SubscriptionNotification with type SUBSCRIPTION_ON_HOLD is sent if there was a payment failure while trying to resume the subscription. This should be handled as described in the account hold section.

Restorations

A cancelled subscription remains visible in the Play Store app until its expiration date. A user can restore a cancelled subscription before it expires by clicking Resubscribe (previously Restore) in the Subscriptions section in the Google Play Store app.

subscriptions section in the google play store app showing a              cancelled subscription with a resubscribe button
Figure 3. Account > Subscriptions section in the Google Play Store app showing a cancelled subscription with a Resubscribe button.

If your app relies solely on queryPurchasesAsync() to determine whether a user is entitled to a subscription, then your app should automatically handle restorations, as queryPurchasesAsync() continues to return cancelled purchases before their expiration dates. A restored subscription continues to renew as if it was not cancelled.

If your app synchronizes subscription state with a backend, you should listen for the SubscriptionNotification with type SUBSCRIPTION_RESTARTED. Once received, your app can respond to the notification, record that the subscription is now set to renew, and stop displaying restoration messaging in your app. The subscription resource looks similar to the following:

          {   "kind": "androidpublisher#subscriptionPurchaseV2",   ...   "subscriptionState": "SUBSCRIPTION_STATE_ACTIVE",   ...   "lineItems": [     {       "productId": "sub_variant_plan01",       "expiryTime": next_renewal_date       ...     }   ], }                  

Upgrades, downgrades, and resignups

When a user upgrades, downgrades, or resignup from your app before the subscription expires, the old subscription is invalidated, and a new subscription is created with a new purchase token.

In addition, the subscription resource returned from the Google Play Developer API will contain a linkedPurchaseToken that indicates the old purchase from which the user upgraded, downgraded, or resubscribed. You can use the linkedPurchaseToken to look up the old subscription and identify the existing user account so that you can associate the new purchase with the same account. We also recommend that you use the Google Play Developer API to acknowledge the purchase to reduce user friction. The subscription resource looks similar to the following:

          {   "kind": "androidpublisher#subscriptionPurchaseV2",   ...   "subscriptionState": "SUBSCRIPTION_STATE_ACTIVE",   "linkedPurchaseToken": old_purchase_token,   ...   "lineItems": [     {       "productId": "sub_variant_plan01",       "expiryTime": next_renewal_date,       "autoRenewingPlan": {         "autoRenewEnabled": true       }     }   ], }                  

Prepaid plans integration

Prepaid plans do not automatically renew upon expiration. To extend their subscription entitlement without interruption, the user must top-up a prepaid plan for the same subscription.

For top-ups, launch the billing flow as you would with the original purchase. You do not need to indicate that a purchase is a top-up.

Prepaid plan top-ups always use the IMMEDIATE_AND_CHARGE_FULL_PRICE proration mode, and you don't need to set this mode explicitly. The user is immediately charged for a full billing period, and their entitlement is extended by the duration specified in the top-up.

After a top-up, the following fields in the Purchase result object are updated to reflect the most recent top-up purchase:

  • Order id
  • Purchase time
  • Signature
  • Purchase token
  • Acknowledged

The following Purchase fields always contain the same data found in the original purchase:

  • Package name
  • Purchase state
  • Products
  • Auto renewing

Prepaid purchase acknowledgement

Similar to auto-renewing subscriptions, you must acknowledge prepaid plans after purchase. Both the initial purchase and any top-ups need to be acknowledged. For more information, see Processing purchases.

Due to the potential for short prepaid plan durations, it is important to acknowledge the purchase as soon as possible.

Prepaid plans with a duration of one week or longer must be acknowledged within three days.

Prepaid plans with a duration shorter than one week must be acknowledged within half the plan duration. For example, developers have 1.5 days to acknowledge a three-day prepaid plan.

As a developer, you must make it easy for your customers to manage their subscription. Your app should include a link on a settings or preferences screen that allows users to manage their subscriptions. An example of this link is shown in figure 4.

The Google Play Subscriptions button in this image is an              example of a 'manage subscriptions' link.
Figure 4. The Google Play Subscriptions button is an example of a "Manage subscriptions" link.

In this link's click handler, add logic to determine whether the user has any non-expired subscriptions for your app, where expiryTime is in the future or autoRenewing is set to true.

Each subscription's productId matches the product ID that you assigned to it when creating it in the Play Console. To programmatically determine the productId for an existing subscription, query your app's backend for a list of subscriptions associated with a particular user.

If the user has a non-expired subscription, you can direct them to a URL similar to the following, replacing "your-sub-product-id" and "your-app-package" with the subscription ID and app package info:

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

If a user doesn't have any non-expired subscriptions within your app, use the following URL to direct them to the page that shows all of their other subscriptions, as shown in figures 5 and 6:

          https://play.google.com/store/account/subscriptions                  
The Play Store subscriptions screen shows status for all              of a user's subscriptions.
Figure 5. The Play Store subscriptions screen shows status for all of a user's subscriptions.
Tap on a subscription to see additional details.
Figure 6. Tap on a subscription to see additional details.

You can find example code for subscription link logic in the Classy Taxi sample app.

Allow users to upgrade, downgrade, or change their subscription

You can offer users different subscription tiers, such as a base tier and a premium tier. Figure 7 shows a screen that offers two subscription tiers:

this app contains two subscription tiers
Figure 7. This app has two subscription tiers.

Users should be able to access a screen similar to figure 7 to upgrade or downgrade a subscription. When upgrading or downgrading a subscription, you can set the proration mode that determines how the change affects your subscribers.

The following table lists available proration modes:

Proration mode Description
IMMEDIATE_WITH_TIME_PRORATION The subscription is upgraded or downgraded immediately. Any time remaining is adjusted based on the price difference, and credited toward the new subscription by pushing forward the next billing date. This is the default behavior.
IMMEDIATE_AND_CHARGE_PRORATED_PRICE The subscription is upgraded immediately, and the billing cycle remains the same. The price difference for the remaining period is then charged to the user.
IMMEDIATE_WITHOUT_PRORATION The subscription is upgraded or downgraded immediately, and the new price is charged when the subscription renews. The billing cycle remains the same.
DEFERRED The subscription is upgraded or downgraded only when the subscription renews.
IMMEDIATE_AND_CHARGE_FULL_PRICE The subscription is upgraded or downgraded and the user is charged full price for the new entitlement immediately. The remaining value from the previous subscription is either carried over for the same entitlement, or prorated for time when switching to a different entitlement.

If the user is changing subscription entitlements, you must specify the proration rate at runtime. For changes in entitlement, you cannot specify a default proration mode through the Google Play Console.

If the user is not changing subscription entitlements, you can use the default proration mode configured through the Play Console. You can also override this behavior by specifying a proration mode in SubscriptionUpdateParams. Note the following restrictions:

  • When upgrading, downgrading, or doing a same-subscription switch to a prepaid plan from either a prepaid plan or auto-renewing plan, the only allowed proration mode is IMMEDIATE_AND_CHARGE_FULL_PRICE. If you specify any other proration mode, the purchase fails, and an error is shown to the user.
  • When switching plans within the same subscription to an auto-renewing plan from a prepaid plan, valid proration modes are IMMEDIATE_AND_CHARGE_FULL_PRICE and IMMEDIATE_WITHOUT_PRORATION. If you specify any other proration mode, the purchase fails, and an error is shown to the user.

Proration examples

To understand how each proration mode works, consider the following scenario:

Samwise has a subscription to online content from the Country Gardener app. He currently has a monthly subscription to the Tier 1 version of the content, which is text-only. This subscription costs him $2 per month, and it renews on the first of the month.

On April 15, Samwise chose to upgrade to the annual version of the Tier 2 subscription, which includes video updates and costs $36 per year.

When upgrading the subscription, the developer selects a proration mode. The following list describes how each proration mode affects Samwise's subscription:

IMMEDIATE_WITH_TIME_PRORATION
Samwise's Tier 1 subscription ends immediately. Since he paid for a full month (April 1-30) but upgraded halfway through the subscription period, half of a month's subscription ($1) is applied to his new subscription. However, since that new subscription costs $36 per year, the $1 credit balance pays for only 10 days (April 16-25), so on April 26, he is charged $36 for a new subscription and another $36 on April 26th of each year following.
IMMEDIATE_AND_CHARGE_PRORATED_PRICE
This mode can be used because the Tier 2 subscription price per time unit ($36/year = $3/month) is greater than Tier 1 subscription price per time unit ($2/month). Samwise's Tier 1 subscription is immediately ended. Since he paid for a full month but used only half of it, half of a month's subscription ($1) is applied to his new subscription. However, since that new subscription costs $36/year, the remaining 15 days costs $1.50, so he is charged the difference of $0.50 for his new subscription. On May 1st, Samwise is charged $36 for his new subscription tier and another $36 on May 1 of each year following.
IMMEDIATE_WITHOUT_PRORATION
Samwise's Tier 1 subscription is immediately upgraded to Tier 2 with no extra charge, and on May 1st he is charged $36 for his new subscription tier and another $36 on May 1 of each year following.
DEFERRED
Samwise's Tier 1 subscription continues until it expires on April 30. On May 1st, the Tier 2 subscription takes effect, and Samwise is charged $36 for his new subscription tier.
IMMEDIATE_AND_CHARGE_FULL_PRICE
Samwise's Tier 1 subscription is immediately ended. His Tier 2 subscription begins today and he is charged $36. Since he paid for a full month but used only half of it, half of a month's subscription ($1) is applied to his new subscription. Since that new subscription costs $36/year, he would get 1/36th of a year added on to his subscription period (~10 days). Therefore, Samwise's next charge would be 1 year and 10 days from today for $36. After that, he is charged $36 each year following.

When choosing a proration mode, be sure to review our proration recommendations.

Your app can offer users an upgrade or downgrade using the same steps as with launching a purchase flow. However, when upgrading or downgrading, you need to provide details for the current subscription, the future (upgraded or downgraded) subscription, and the proration mode to use, as shown in the following example:

          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             .setOldSkuPurchaseToken("old_purchase_token")             .setReplaceSkusProrationMode(ProrationMode.IMMEDIATE_AND_CHARGE_FULL_PRICE)             .build())     .build();  BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams);  // process purchase results from PurchasesUpdatedListener registered with BillingClient public void onPurchaseUpdated(BillingResult billingResult, @Nullable List<Purchase> purchases) {   // check BillingResult   // process returned Purchase list, e.g. grant entitlement }                  

For the immediate replacement proration modes, your app receives the new purchase in your PurchasesUpdatedListener. The purchase is also available in BillingClient.queryPurchasesAsync(). When you receive the purchase token, follow the same verification process as with verifying a new purchase token. Make sure to acknowledge these purchases with BillingClient.acknowledgePurchase() from the Google Play Billing Library or Purchases.subscriptions:acknowledge from the Google Play Developer API.

The Google Play Developer API returns a linkedPurchaseToken in the subscription resource. Be sure to invalidate the token provided in the linkedPurchaseToken to ensure that the old token is not used to gain access to your services. See Upgrades, downgrades, and resignups for information on handling upgrade and downgrade purchases.

For the deferred replacement mode, your app receives a call to your PurchasesUpdatedListener with an empty list of purchases and a status of whether the upgrade or downgrade was successful. Until the replacement takes effect, BillingClient.queryPurchasesAsync() continues to return the purchase for the original subscription plan. Once the new plan takes effect, queryPurchasesAsync() returns the purchase data for the new subscription, and a SUBSCRIPTION_RENEWED notification is sent to your secure backend server. For deferred replacements, it is strongly recommended to listen to this notification and to acknowledge the purchase using Purchases.subscriptions:acknowledge. The linkedPurchaseToken in the subscription resource can be used to determine which user in your subscription backend, if applicable, should be updated with the new entitlement. Your app should not rely on the user opening the app and acknowledging via BillingClient.acknowledgePurchase(), since the user might not open the app within three days of the plan change taking effect.

Upgrading with free trial or intro price offers

Free trial eligibility settings apply when a user is upgrading or downgrading. You can adjust the free trial eligibility settings in the Google Play Console.

Note the following:

  • If users can receive only one free trial across all available subscriptions in your app, the plan the user is changing to will not have a free trial or intro price.
  • If you provide one free trial per subscription product, the plan the user is changing to may have a free trial or intro price.

The following table describes the behavior of each proration mode if both the new and old plans have a free trial, and the user is upgrading during a free trial:

One free trial per app One free trial per subscription product
IMMEDIATE_WITH_TIME_PRORATION The user loses the free trial immediately. The remaining free trial period is converted to an equivalent free period of the new tier based on the price difference. The user loses the previous free trial but immediately starts the new free trial. In addition, the remaining free trial period of the old tier is converted to an equivalent free period of the new tier and added to the new free trial.
IMMEDIATE_AND_CHARGE_PRORATED_PRICE

The user loses the free trial immediately. The price difference for the remaining period is then charged to the user. The next billing date remains unchanged.

Note: This option is available only for a subscription upgrade, where the price per unit of time increases.

IMMEDIATE_WITHOUT_PRORATION The user is immediately upgraded to the new tier. The user keeps free trial access to the new tier until the previous billing period ends.
DEFERRED The user keeps free trial access to the old subscription until the next billing date.
IMMEDIATE_AND_CHARGE_FULL_PRICE The user loses the free trial immediately. The new subscription's price is then charged to the user. The next billing date is the new subscription period plus any remaining time from the free trial.

To understand how free trial transitions work in the default case of one free trial per app, consider the following scenario:

Maria has a subscription to online content from the Country Gardener app. She currently has a monthly subscription to the Tier 1 version of the content, which is text-only. This subscription costs her $10/month, and she subscribed on April 1. She is enjoying a 30-day free trial as a first-time subscriber, which means her first payment is due on May 1.

On April 15, Maria chooses to upgrade to the Tier 2 subscription, which includes video updates and costs $20/month. This second subscription has a 30-day trial as well.

The following list describes how the free trial transition for each proration mode:

  • IMMEDIATE_WITH_TIME_PRORATION - Maria is upgraded to Tier 2 immediately. Since Maria upgraded halfway through the subscription period, half of the month's subscription (15 days valued at $10/month) is applied to her new subscription. However, since that new subscription costs $20/month, the 15 day balance pays for only 7.5 days. Maria is not eligible for another free trial to Tier 2, so starting April 22, she is charged $20 every month.
  • IMMEDIATE_AND_CHARGE_PRORATED_PRICE - This mode can be used because the Tier 2 subscription price per time unit ($20/month) is greater than the Tier 1 subscription price per time unit ($10/month). Maria's Tier 1 subscription is immediately upgraded to Tier 2, and she loses her free trial. Since Maria's next billing date was May 1, she is charged $10 today to cover the 2nd half of April, then starting May 1 she is charged $20 every month.
  • IMMEDIATE_WITHOUT_PRORATION - Maria's Tier 1 subscription is immediately upgraded to Tier 2. Maria keeps her free trial until April 30 and now has access to Tier 2 content. Starting May 1, she is charged $20 every month.
  • DEFERRED - Maria's Tier 1 subscription continues until the next payment is due on May 1. On May 1, the Tier 2 subscription takes effect, and Maria is charged $20 on the first of every month.
  • IMMEDIATE_AND_CHARGE_FULL_PRICE - Maria's Tier 1 subscription is immediately upgraded to Tier 2, and she loses her free trial. She is charged $20 today. Since Maria's has 15 days left in her free trial, her next billing date is 1 month + 15 days from now, or July 1st. Starting July 1st, she is charged $20 every month.

The following list describes the transition behavior if the developer instead allows one free trial per subscription:

  • IMMEDIATE_WITH_TIME_PRORATION - Maria is upgraded to Tier 2 immediately. Since Maria upgraded halfway through the subscription period, half of the month's subscription (15 days valued at $10/month) is applied to her new subscription. However, since that new subscription costs $20/month, the 15 day balance pays for only 7.5 days. Maria is eligible for another free trial to Tier 2, so she is not charged for another 37.5 days. Starting May 22, she is charged $20 every month.
  • IMMEDIATE_AND_CHARGE_PRORATED_PRICE - This mode can be used because the Tier 2 subscription price per time unit ($20/month) is greater than the Tier 1 subscription price per time unit ($10/month). Maria's Tier 1 subscription is immediately upgraded to Tier 2, and she loses her free trial. Since Maria's next billing date was May 1, she is charged $10 today to cover the 2nd half of April, then starting May 1 she is charged $20 every month.
  • IMMEDIATE_WITHOUT_PRORATION - Maria's Tier 1 subscription is immediately upgraded to Tier 2. Maria keeps her free trial until April 30 and now has access to Tier 2.
  • DEFERRED - Maria's Tier 1 subscription continues until the next payment is due on May 1. On May 1, the Tier 2 subscription takes effect, and Maria is charged $20 on the first of every month.
  • IMMEDIATE_AND_CHARGE_FULL_PRICE - Maria's Tier 1 subscription is immediately upgraded to Tier 2, and she loses her free trial. She is charged $20 today. Since Maria's has 15 days left in her free trial, her next billing date is 1 month + 15 days from now, or July 1st. Starting July 1st, she is charged $20 every month.

Proration recommendations

The following table shows diferrent proration scenarios along with what we recommend for each scenario:

Scenario Recommended proration mode Result
Upgrading to a more expensive tier IMMEDIATE_AND_CHARGE_PRORATED_PRICE The user receives access immediately while keeping the same billing period.
Downgrading to a less expensive tier DEFERRED The user already paid for the more expensive tier, so they will keep access until the next billing date.
Changing recurring period on the same tier (for example, monthly to annual) DEFERRED The user will pay the new recurring price at the next billing date.
Upgrading while in a free trial, keeping the trial IMMEDIATE_WITHOUT_PRORATION The user keeps free trial access, but upgrades to a higher tier for the remainder of the trial.
Upgrading while in a free trial - ending access to the free trial IMMEDIATE_AND_CHARGE_PRORATED_PRICE The user receives access to the new tier immediately but no longer has a free trial.

Customer management

Using Real-time developer notifications, you can detect in real time when a user decides to cancel. When a user cancels, but before their subscription has expired, you can send them push notifications or in-app messages to ask them to resubscribe.

After a user has cancelled their subscription, you can try to win them back either in your app, or through the Play store. The following table describes various subscription scenarios along with associated winback actions and app requirements.

Before subscription expiration After subscription expiration
In-app In Play Store In-app In Play Store
Winback feature In-app subscription Restore In-app subscription Resubscribe
User goes through checkout flow Yes No Yes Yes
User subscription remains associated with the same SKU User can sign up for same or different SKU Yes User can sign up for same or different SKU Yes
Creates new purchase token Yes No Yes Yes
Enabled by default No Yes, support required for all devs No

Apps without Billing Library 2.0+: No

Apps with Billing Library 2.0+: Yes. Devs can opt-out in Console.

When user is charged

If using same SKU: end of current billing period.

If using different SKU: depends on proration mode.

End of current billing period Immediately Immediately
Implementation required Provide a re-signup UI in your app

Detect change in subscription state

Deep-link to Play Store

Provide a re-signup UI in your app Handle out-of-app purchases

Before subscription expiration - in-app

For subscriptions that have been canceled but have not yet expired, you can allow subscribers to restore their subscription within your app by applying the same in-app product purchase flow as for new subscribers. Ensure your UI reflects that the user has an existing subscription. For example, you might want to display the user's current expiration date and recurring price with a Reactivate button.

Most of the time, you will want to offer the user the same price and SKU they were already subscribed to, as follows:

  • Initiate a new subscription purchase with the same SKU.
  • The new subscription replaces the old one and renews on the same expiration date. The old subscription is immediately marked as expired.
  • As an example, Achilles has a subscription to Example Music App, and the subscription is due to expire on August 1. On July 10, he resubscribes to the one-month subscription at the same price per month. The new subscription is prorated with the remaining credit, is immediately active, and still renews on August 1.

If you would like to offer a different price—for example a new free trial or a winback discount—you can instead offer a different SKU to the user:

  • Initiate an upgrade or downgrade with the different SKU using the proration mode IMMEDIATE_WITHOUT_PRORATION.
  • The new subscription replaces the old one and renews on the same expiration date. The user is charged the price of the new SKU, including any introductory prices, on the original expiration date. If the old subscription was created using an obfuscated account id, that same id should be passed to the BillingFlowParams for upgrades and downgrades.
  • As an example, Achilles has a subscription to Example Music App, and the subscription is due to expire on August 1. On July 10, he resubscribes to an annual subscription with an introductory price. The new subscription is immediately active, and the user is charged the introductory price on August 1.
  • If you decide to include a free trial or intro price in your winback SKU, ensure that the user is eligible by unchecking the Allow one free trial per app box in the Google Play Console, which restricts the user to getting one free trial per app.

When you receive the purchase token, process the purchase just as you would with a new subscription. Additionally, the Google Play Developer API returns a linkedPurchaseToken in the subscription resource. Be sure to invalidate the token provided in the linkedPurchaseToken to ensure that the old token is not used to gain access to your services.

Before subscription expiration - in Play Store

While the subscription is canceled but still active, users can restore the subscription in the Google Play subscriptions center by clicking Resubscribe (previously Restore). This keeps the same subscription and purchase token.

subscriptions section in the google play store app showing a              cancelled subscription with a resubscribe button
Figure 8. Account > Subscriptions section in the Google Play Store app showing a cancelled subscription with a Resubscribe button.

For more information on restoring subscriptions, see Restorations.

After subscription expiration - in-app

You can allow expired subscribers to resubscribe within your app by applying the same in-app product purchase flow as for new subscribers. Note the following:

  • To offer users a discount, you might want to offer a product ID with special pricing for your subscription, also called a winback SKU. You can provide the offer in your app, or you can notify the user of the offer outside of the app, such as in email.
  • To start a winback subscription, launch the purchase flow in your Android app using the Google Play Billing Library. This is the same process as with a new subscription, but you can determine the SKU that is available to the user.
  • If you decide to include a free trial or intro price in your winback SKU, ensure that the user is eligible by unchecking the Allow one free trial per app box in the Google Play Console, which restricts the user to getting one free trial per app.
  • If the user resubscribes to the same SKU, they are no longer eligible for free trials or introductory price. Ensure that your UI reflects this.

When you receive the purchase token, process the purchase just as you would with a new subscription. You will not receive a linkedPurchaseToken in the subscription resource.

After subscription expiration - in Play Store

If enabled, users can resubscribe to the same SKU for up to one year after expiration by clicking Resubscribe in the Google Play subscriptions center. This generates a new subscription and purchase token.

subscriptions section in the google play store app showing a              cancelled and expired subscription with resubscribe and remove              buttons
Figure 9. Account > Subscriptions section in the Google Play Store app showing a cancelled and expired subscription with Resubscribe and Remove buttons.

Resubscribing is considered an out-of-app purchase, so be sure to follow best practices for handling purchases made from outside your app.

You can create promotion codes to give selected users an extended free trial to an existing subscription. To learn more, see Promo codes.

For free trials, Google Play verifies that the user has a valid payment method before starting the free trial. Some users may see this verification as a hold or charge on their payment method. This hold or charge is temporary and is later reversed or refunded.

After the trial period ends, the user's payment method is charged for the full subscription amount.

If a user cancels a subscription at any time during the free trial, the subscription remains active until the end of the trial, and they aren't charged when the free trial period ends.

Cancel, refund, or revoke

You can use the Google Play Developer API to cancel, refund, or revoke a subscription. This functionality is also available in the Google Play Console.

  • Cancel: Users can cancel a subscription on Google Play. You can also provide an option for users to cancel in your app or on your website. Your app should handle these cancellations as described in Revocations.
  • Refund: When you refund, the user can continue to use the subscription. Refunds can be used if, for example, there was a technical error that prevented the user from accessing your product, but the error has been resolved. Note that to refund more than the most recent payment, or if you want to issue a partial refund, you must use the Google Play Console.
  • Revoke: When you revoke, the user immediately loses access to the subscription. This can be used if, for example, there was a technical error that prevented the user from accessing your product, and the user does not want to continue using the product. Your app should handle these cancellations as described in Revocations.

The following table illustrates the differences between cancel, refund, and revoke.

Stops renewal Refund money Revoke access
Cancel Yes No No
Refund No Yes No
Revoke Yes Yes Yes

Defer billing for a subscriber

You can advance the next billing date for an auto-renewing subscriber by using Purchases.subscriptions:defer from the Google Play Developer API. During the deferral period, the user is subscribed to your content with full access but is not charged. The subscription renewal date is updated to reflect the new date.

Deferred billing allows you to do the following:

  • Give users free access as a special offer, such as giving one week free for purchasing a movie.
  • Give free access to customers as a gesture of goodwill.

Billing can be deferred by as little as one day and by as long as one year per API call. To defer the billing even further, you can call the API again before the new billing date arrives.

As an example, Darcy has a monthly subscription to online content for the Fishing Quarterly app. She is normally billed £1.25 on the first of each month. In March, she participated in an online survey for the app publisher. The publisher rewards her with six free weeks by deferring the next payment until May 15, which is six weeks after her previously scheduled billing date of April 1. Darcy is not charged for April or the beginning of May and still has access to the content. On May 15, she is charged the normal £1.25 subscription fee for the month. Her next renewal date is now June 15.

When deferring, you might want to notify the user by email or within the app to notify them that their billing date has changed.

Changing subscription prices

For information about how to change subscription prices using the Play Console, see the documentation in the Play Console Help Center.

Warning: You should not change the price of a Subscribe with Google subscription.

Google Play allows you to sell your digital products around the world to many users in different locales with different currencies and pricing considerations. Sometimes, due to regional costs, currency fluctuations, or other reasons, you may decide you need to change the price of your subscription.

You can change the price of any base plan or offer, and the new price will take effect within an hour for all new purchases.

Users on prepaid plans always pay the current price for top-ups and plan changes.

Users currently subscribed to auto-renewing plans are not affected by default. Instead, a legacy price cohort is created. If desired, you can change the price of the base plan to the current price by ending the cohort. You cannot change the price of an existing subscriber's free or introductory offer pricing phases.

For more information on using legacy price cohorts, please see the Play Console Help Center.

Communicate your price change to the user

You should notify your existing subscribers whenever you change the price of their base plan, especially if the price is increasing.

When you increase the price of a subscription, you have at least seven days to notify your existing subscribers about the price change before Google Play begins directly notifying them.

Existing subscribers have at least 30 days to review the price increase and decide whether to accept it. If they do not accept the price increase, their subscription is automatically canceled before they would otherwise pay the higher price.

Users can review a price increase in the Play Store subscription screen, where a dialog similar to figure 13 is shown.

Generic dialog notifying the user of a subscription price change
Figure 13. Example dialog notifying the user of a subscription price change.

Google Play directly notifies existing subscribers about all upcoming price changes.

Within your app, we recommend you also notify affected users and provide a deep link to the Play Store subscription screen.

When you decrease the price of a subscription, users do not need to agree to the change, and are not shown the price change dialog. They are charged the lower price starting on their next billing date.

Handle user confirmation of the price change

If the user accepts your subscription price increase, or if you've decreased the price, the subscription renews and can be processed just like any other renewal. Additionally, you receive a SubscriptionNotification with type SUBSCRIPTION_PRICE_CHANGE_CONFIRMED.

Handle when a price increase is not accepted

If a user hasn't accepted your price increase before they would otherwise pay the higher price, they are automatically unsubscribed, and you receive a SubscriptionNotification with type SUBSCRIPTION_CANCELED. This event can be handled as described in Cancellations.

Accidental price change

If you've accidentally changed the price of a subscription, reverse the change immediately. As long as the price is reverted within seven days, existing subscribers are not notified about the accidental price change. Note that new subscribers might receive the accidental price during the time between the first price change and the reversion.

Handling two price changes in a row

If you've ended a legacy price cohort with a price increase, and then you change the price again, any eligible users no longer need to respond to the first price change, as only the second price change now applies.

You should ensure that you do only one price change at a time. Price changes are not recommended for testing purposes.

If you change a subscription price twice within a seven-day period, impacted users only need to agree only to the latest price change.

Handling payment declines

If there are payment issues at the end of a billing cycle, Google will periodically attempt to renew the subscription for some time before canceling. This retry period can last up to 30 days plus any specified grace period length. During this time, Google also sends the user emails and notifications to ask them to update their payment method.

Upon payment decline, the subscription will first enter grace period, if enabled. During the grace period, the user should still have access to the subscription.

After any grace period has ended, the subscription enters account hold for up to 30 days. During account hold, you can block access to the subscription.

To maximize the likelihood of subscription recovery during a payment decline, you can inform your user of a payment issue and ask them to fix it.

You can either do this yourself, as described in the grace period and account hold sections, or you can implement the in-app messaging API, where Google will surface a message to users in your app.

In-app messaging

If you've enabled in-app messaging with InAppMessageCategoryId.TRANSACTIONAL, Google Play will show users messaging during grace period and account hold once per day and provide them an opportunity to fix their payment without leaving the app.

Snackbar notifying the user to fix their payment
Figure 14. Snackbar notifying the user to fix their payment.

We recommend that you call this API whenever the user opens the app to determine whether the message should be shown.

If the user successfully recovered their subscription, you will receive a response code of SUBSCRIPTION_STATUS_UPDATED along with a purchase token. You should then use this purchase token to call the Google Play Developer API and refresh the subscription status in your app.

Integrate in-app messaging

To show in-app messaging to user, use BillingClient.showInAppMessages().

Here is an example of triggering the in-app messaging flow:

Kotlin

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.                 }             }         })            

Java

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.                 }             }         });            

duartemays1993.blogspot.com

Source: https://developer.android.com/google/play/billing/subscriptions

0 Response to "If I Raise My Subscriber Tier Do I Get Charged Again"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel