Search code examples
androidgoogle-playin-app-billinggoogle-play-consolegoogle-play-developer-api

Google Play Developer API - Why linkedPurchaseToken is not found when user perform resubscribe?


In our backend server, when user

  1. Cancel the subscription.
  2. Re-subscribe again after few days.

It is crucial for us to know, the old purchase token, and the new purchase token, are both referring to the same user.

Reason is that, previous, user had already created some data in server, using old cancelled subscription purchase token.

When user cancelled the subscription, and re-subscribe again, we want to ensure the user still authorized to access the old data, using the new purchase token.

We expect we can get the information from linkedPurchaseToken, where the new purchase token, will point to the old purchase token.

This is described in https://medium.com/androiddevelopers/implementing-linkedpurchasetoken-correctly-to-prevent-duplicate-subscriptions-82dfbf7167da

However, based on our test result, this is not the case.

Google Play Developer API

credentials = service_account.Credentials.from_service_account_file(
    constant.PATH_TO_SERVICE_ACCOUNT_JSON, 
    scopes = constant.SCOPES
)
    
androidpublisher = googleapiclient.discovery.build(
    'androidpublisher', 
    'v3', 
    credentials = credentials
)

product = androidpublisher.purchases().subscriptions().get(
    packageName = "com.xxx.yyy",
    subscriptionId = product_id,
    token = token
).execute()

return product

Current active subscription

{
   'startTimeMillis':'1619245597271',
   'expiryTimeMillis':'1619246015249',
   'autoRenewing':True,
   'priceCurrencyCode':'SGD',
   'priceAmountMicros':'6980000',
   'countryCode':'SG',
   'developerPayload':'',
   'paymentState':1,
   'orderId':'GPA.3314-4833-2752-47988',
   'purchaseType':0,
   'acknowledgementState':1,
   'kind':'androidpublisher#subscriptionPurchase'
}

Previous cancelled subscription

{
   'startTimeMillis':'1619244776697',
   'expiryTimeMillis':'1619245074590',
   'autoRenewing':False,
   'priceCurrencyCode':'SGD',
   'priceAmountMicros':'6980000',
   'countryCode':'SG',
   'developerPayload':'',
   'cancelReason':3,
   'orderId':'GPA.3358-9904-1003-13416',
   'purchaseType':0,
   'acknowledgementState':1,
   'kind':'androidpublisher#subscriptionPurchase'
}

We do not have linkedPurchaseToken information. Hence, there is no way for us to know, both subscriptions are referring to a same user.

In Google Play Console, it is able to tell the subscriptions are from the same user, even the order id is different. However, there is no way to know such, via Google Play Developer API respond.

enter image description here


Our initial guess is that, this can due to Resubscribe feature is not enabled in our Google Play Console.

enter image description here

But, currently, all our production/ beta/ tester APK have been upgraded to 3.0.1 long time ago. So, we are not sure whether there is such "Resubscribe is not currently available for your users because your app does not use Billing Library 2.0 in all active APKs." message.

Any idea, how we can find out, whether the latest active subscription, and cancelled inactive subscription, are in fact referring to the same user?


Solution

  • A resubscription before the original, cancelled subscription has expired will re-use the same purchase token. A re-subscription after the original subscription has already expired is treated like a new purchase, so you will get a brand new purchase token, and the linkedPurchaseToken field will not be set. The linked purchase token field will be really only be set for upgrade and downgrade flows. See Purchase Tokens and Order IDs docs.

    In the past, linkedPurchaseToken was set for resubscription flows, which would occur if you cancelled and resubscribed before the original subscription expired. With Resubscribe this is no longer the case. (Note that Medium article has an updated note with this info - disclaimer I am the author of that article). Specifically from the Resubscribe docs:

    A restored subscription uses the same the purchaseToken from when the subscription was cancelled. All cancellation fields are cleared from the resource.

    So linkedPurchaseToken will not be set. Note: this only occurs when the resubscribe happens before the expiration of the original subscription.

    In the example purchases you provided above, it looks to me as though the second purchase happened after the original first subscription expired. ( 'startTimeMillis':'1619245597271' from new subscription is larger than 'expiryTimeMillis':'1619245074590' from old subscription, so the old subscription had already expired. In this case, the new subscription is treated as a brand new subscription with a brand new purchase token.

    In response to your question about how you may be able to tie the two purchases together, the answer is that you cannot, by design, from using just the information provided by Google Play. Each purchase token, and its associated info, does not contain user identifiable information.

    When you say, however, that there is "data in [the] server" saved from the first purchase, that makes me think you have a back-end server with some sort of user accounts. In this case, it is on your back-end server and in your own code that you should associate the two purchases with a particular user. This is the correct way to do this (see the Classy Taxi sample).

    Note: I noticed the upgrade/downgrade docs still mention re-signups which is out-of-date.