Play Billing Library v1.0: renewed subscription missing from queryPurchases result - android

I have an Android app offering auto-renewing subscriptions via In-App Billing, using https://developer.android.com/google/play/billing/billing_library.html.
I'm using a lightly modified BillingManager.java from https://github.com/googlesamples/android-play-billing/ to help with purchase management.
Previously, prior to release (around 4-8 weeks ago), whenever a subscription trial ended and the subscription auto-renewed, I would continue to receive a corresponding Purchase object in the purchases lists upon querying purchases:
PurchasesResult subscriptionResult = mBillingClient.queryPurchases(SkuType.SUBS);
List<Purchase> list = purchasesResult.getPurchasesList();
(see queryPurchases here)
The OrderID had an incremented counter value appended according to the number of renewals that had occurred since the original order (as described under Subscription Order Numbers here).
In the last few days, it seems that whenever a customer's subscription converts to paid from trial, or renews subsequently, queryPurchases returns zero Purchases thereafter. I expect to receive one Purchase object for users with an active subscription (and was getting this during testing a while back - I have the data in my db to confirm it.)
As a result, the app no longer calls our backend server to update the subscription validity and users are denied access to functionality for which they have been charged - not great.
I can view the customer's order (with incremented OrderID) on Google Play Console and the subscription shows as valid (and is not cancelled) and a purchase token is available and can be validated.
Does anyone have any idea why would queryPurchases would stop returning a valid Purchase after the first renewal? (The Purchase is returned as expected prior to the renewal date.)
I'm using the current billing client library, as follows:
implementation 'com.android.billingclient:billing:1.0'
(As a workaround, I can fix this on the back-end by periodically rechecking all submitted purchase tokens, but I'd much prefer to do it on demand triggered by the app, which was working fine previously.)

Related

What is the new "Resubscribe" feature found in Billing Library 2.0 and how is it different than the old Billing Library 1.2.2's?

In the Android Developer Console, I saw this message
Resubscribe isn't currently available for your users because your app
does not use Billing Library 2.0 in all active APKs
But, I was puzzled. Currently, we are using Billing Library 1.2.2.
This is how we decide, whether to show subscription button to user or not.
During queryPurchases, We will perform List<Purchase> purchases = PurchasesResult.getPurchasesList(). If the subscription's SKU is not found in purchases, we will show the subscription button. If not, we will hide the subscription button.
If this is a new subscriber, there will be no SKU in his purchases. Hence, he will see the subscription button, and allowed to subscribe again.
If this is a previous subscribed, and already cancelled user, we assume there will be no SKU in his purchases too!!! Hence, he will see the subscription button, and allowed to subscribe to the same sku again.
As you can see, even with old Billing Library 1.2.2, we are still allow user to resubscribe to same SKU again, to his previous cancelled subscription.
If that is so, why there is a special feature called "Resubscribe" (https://developer.android.com/google/play/billing/subs#resubscribe) in Billing Library 2.0? How does it different from our current Billing Library 1.2.2 flow?
To be perfectly honest, there isn't any enormous difference between resubscribing to the same sku with old and new approach using the resubscribe feature. Why? (None of these are solidly tested by the way, this is a logical explanation.)
In both cases, the subscription elements will stay the same and they will both return in queryPurchases method as long as the subscription is active.
This relates to the queryPurchases method, I haven't tested this yet, but it is possible that, in the old way, multiple purchases with the same sku might return, which may create a confusion. After resubscribing while canceled subscription is still active, the queryPurchases method will return only 1 subscription, causing queryPurchaseHistoryAsync method to return nothing. In the old way, if queryPurchases method returns only 1 purchase after getting a subscription over a canceled subscription with same sku, queryPurchaseHistoryAsync might actually return the old subscription that was canceled for, even if it was still active in a canceled state.
On Google Play Developer API side, there is a method that links a purchase token to the older one. For this, the Purchase.getLinkedPurchaseToken() function might return different values after subscribing to same sku, between the old way and new way. I presume, resubscribing to an active canceled subscription with the old way will generate a new purchase token, and getLinkedPurchaseToken(). This does not affect the BillingClient itself since there is no getLinkedPurchaseToken() method but logically this should be the result.
Bottom line: The only difference I can say is that resubscribing with the new way might reduce confusions, while on the old way there might be unnecessary data that you want to avoid from. As long as you have a subscription that's returned from queryPurchases where it matches your sku, you can consider that the user has an active subscription.
https://developer.android.com/google/play/billing/subs#resubscribe
Users can resubscribe in a number of different scenarios:
Before the subscription has expired, users can repurchase the same subscription in your app. This generates a new subscription and
purchase token.
Before the subscription has expired, users can restore the subscription in the Google Play subscriptions center. This keeps the
same subscription and purchase token.
After the subscription has expired, users can also repurchase the same SKU up to 1 year after expiration through the Google Play
subscriptions center. This generates a new subscription and purchase
token.
More details are provided in the release notes of 2.0 here: https://developer.android.com/google/play/billing/release-notes
I think the API is for subscriptions made outside your app (for example, from Google Play Subscriptions Center (mentioned in bullet point 3), or at a physical store).
Based on your question, it seems that you already handle the other scenarios regarding a user not having a subscription or having cancelled their subscription - but these flows apply to within the app, not outside. To gracefully handle purchases made outside the app you must use 2.x or higher.
The ability to process subscriptions outside the app, such as Google Play subscription Center or a physical store is not available in 1.x. It is available from 2.x+
Presuming you don't confuse the flow of subscriptions , that will remain as it is. Additional features have been added to Google play billing . As we talk , Google play billing 3.0 is up and ready. Follow this link
https://developer.android.com/google/play/billing/release-notes#3-0-0-summary-changes
Resubscribe feature will make restoring subscriptions easier.
There are scenarios where managing subscription should be made easy .
Subscription Restore and Resubscribe
Lets assume a user for some reason cancels the subscription renewals and before the subscription is expired and wants to subscribe it again. Now if user wants to resume it again. This newly feature will allow to resume the subscription as if they were never cancelled. For this the condition is that the subscription must not have expired . If it has expired , then here it is . Users will have to resubscribe instead. To resume any paused subscription users will need to resubscribe , you will have to treat this as you have been treating it.
Account hold feature
A user subscribes and sometimes users are unable to pay their subscription, whether due to financial woes or an expired credit card. In these cases, developers can initiate an Account Hold instead of cancelling it . This will allow users to manage the subscriptions until they fix the payment at their end.
Developers with existing apps will need to integrate Account Hold and Subscription Restore by November 1st. Unless they opt out, they’ll also need to integrate Subscription Pause and Resubscribe. If they fail to do so by the deadline, future updates may be rejected, thus delaying the launch of new features, bug fixes and metadata.

Test subscription is revoked by GooglePlay

I'm working on a subscription renewal feature, in test mode, with testing payment methods. Problem is that we receive cancelation subscription webhook, GooglePlay makes subscription revoke. ​​
From params:
​"cancelReason": "1"
Status code from the docs,
Subscription was canceled by the system, for example, because of a
billing problem.
Also from the docs
Revoking a subscription instantly removes access to the subscription
and is usually done when you or Google suspects fraud.
Usually, it sends cancelation webhook immediately after renewal, even when it was successful, so there are cases when I got two e-mails, about renewal success and cancelation. In my case renewal called after 5 minutes (doc)
Have someone idea, what could be the reason? Is it some "Google anti-fraud system". Because for testing purpose we have short subscription period but the big price. But probably anti-fraud should not be executed when we do testing, with testing payment methods, when there is no real transaction.
The problem was, that we didn't acknowledge new subscriptions.
From the docs:
If you use the Google Play Billing Library version 2.0 or newer, you
must acknowledge all purchases within three days. Failure to properly
acknowledge purchases results in those purchases being refunded.
Regarding subscriptions:
For subscriptions, you must acknowledge any purchase that contains a
new purchase token. This means that all initial purchases, plan
changes, and re-signups need to be acknowledged, but you do not need
to acknowledge subsequent renewals.
Test acknowledging purchase with license testers:
For purchases made by license testers, the acknowledgment window is
shorter. Instead of three days, purchases are refunded and revoked if
they are not acknowledged within five minutes.
UPDATE
changes in documentation
You should also verify that purchases are properly acknowledged as
described in processing purchases. For purchases from license testers, a > purchase will be refunded after 3 minutes if your app does not
acknowledge the purchase and you will receive an email about the
cancellation. You can also check the Orders tab in the Google Play
Console to see if an order was refunded after 3 minutes.

billingClient.queryPurchases returns the list with already cancelled subsription

Steps to reproduce (test account):
Complete subscription process in the app
Cancel subscription in Play Store app and wait till it ends to completion (for monthly test subscriptions 5 minutes for the date of writing)
Expected: Subscription is no longer in the list which billingClient.queryPurchases(SUB_SKU_TYPE) returns
Actual: Subscription is still in the list which billingClient.queryPurchases(SUB_SKU_TYPE) returns (even after ~1 hour)
Reported bug: https://github.com/googlesamples/android-play-billing/issues/122
As it is stated in the documentation queryPurchases works with cache without doing any network calls, this could be a reason for this issue. queryPurchaseHistoryAsync could be a good alternative but Purchase class doesn't have state of the actual purchase (i.e. SUBSCRIBED, CANCELLED, etc.).
Is there any option to fix this issue using Play Billing Lib or it is required to make direct network calls using old In-App Billing Api?

Android In-App Subscription PurchaseState is always 0

In my android app using in-app subscription monthly plan. I have purchased a subscription product with test account. After one hour I cancelled it manually from my phone.
After I query using inventory.getPurchase(monthlyplan), I always get purchase state is 0.
I waited more than one day; still getting response of purchase state is 0. Can any one help me on this?
You may want to check this document - Subscription Cancellation:
Users can view the status of all of their subscriptions and cancel them if necessary from the My Apps screen in the Play Store app. Currently, the In-app Billing API does not provide support for programatically canceling subscriptions from inside the purchasing app.
When the user cancels a subscription, Google Play does not offer a refund for the current billing cycle. Instead, it allows the user to have access to the canceled subscription until the end of the current billing cycle, at which time it terminates the subscription. For example, if a user purchases a monthly subscription and cancels it on the 15th day of the cycle, Google Play will consider the subscription valid until the end of the 30th day (or other day, depending on the month).
Important: In all cases, you must continue to offer the content that your subscribers have purchased through their subscriptions, as long any user is able to access it. That is, you must not remove any content while any user still has an active subscription to it, even if that subscription will terminate at the end of the current billing cycle. Alternatively, you can use the refund and revoke API to revoke each subscriber's subscription (one by one) and refund their subscription payments. Removing content that any subscriber is entitled to access will result in penalties. Please see the policies document for more information.
There are some good insights regarding the following (also found in the same document):
App uninstallation
Refunding and revoking subscriptions
Here is a related SO question that also talk about cancelling subscription in-app.

google in-app subscription unexpected behavior

I trying to test Android In-App Billing V3 to make subscription purchases.
Im aware of the following:
"Test subscription purchases recur daily, regardless of the product's subscription period."
but I noticed the following behavior:
A user buys a monthly subscription through google play, the client passes the information to the server. On the server side, I make an API call to google to get more info about the subscription.
I go to the Google play dashboard and cancel the subscription. (it changes from renewing on X to expire on X).
I buy the same subscription again but I have the following behavior:
Purchase token is the same as in #1. My assumption that the purchase
token will be different.
autoRenewing is still set to false (even
though google play dashboard shows "will renew on x").
expiryMills still shows the original expiration which is in the past (I resubscribed a couple of days later so I would expect the expiryMills to be updated)
Im not sure if this is the correct beahvior or not ...
I would expect the following: If im in within the period, so after the user cancels and then resubscribes, the autoRenewing will "true", and if im after the period, I will get a new purchase token so that the information I get from google api will match the google play dashboard.
Ofir

Categories

Resources