subscription-states
Subscription States
A Google Play subscription moves through seven states between the first purchase and final termination. Each state has a concrete access decision: grant, retain until expiry, or revoke. Get the mapping wrong and you either give away paid content or revoke access a user already paid for.
This skill walks you through confirming your app reads the correct state source, deciding the access rule for each state, and writing the mapping code.
Phase 1: Discovery
Before changing anything, confirm where your entitlement decision reads subscription state from. The authoritative source is the subscriptionState field on the SubscriptionPurchaseV2 resource returned by purchases.subscriptionsv2.get on the Google Play Developer API. The client Purchase object from queryPurchasesAsync() does not carry this field.
Answer these questions:
- Does your backend call
purchases.subscriptionsv2.get(not the legacypurchases.subscriptions.get)? - Does your entitlement function read
subscriptionStatefrom that response rather than inferring state from the RTDN notification type? - Does the function check
expiryTimewhen the state isSUBSCRIPTION_STATE_CANCELED? - Does your client code treat a
Purchasereturned byqueryPurchasesAsync()as "has a purchase," not "has access"?
If any answer is no, fix the source of truth first. Inferring state from the notification type is the single most common cause of wrong entitlement decisions, because two different transitions can produce the same RTDN type. For example, SUBSCRIPTION_RECOVERED fires both when a grace period retry succeeds and when a user fixes payment during account hold.