Search Unity

  1. Calling all beginners! Join the FPS Beginners Mods Challenge until December 13.
    Dismiss Notice
  2. It's Cyber Week at the Asset Store!
    Dismiss Notice

Check if subscription has ended

Discussion in 'Unity IAP' started by wouter_vugt, Oct 20, 2018.

  1. wouter_vugt

    wouter_vugt

    Joined:
    Feb 25, 2015
    Posts:
    104
    Hi,

    I am new to subscriptions, but have found a few things while testing and want to check if i set it up correctly.

    Currently to check if a subscription has ended I use (on initialized):
    IF there is a receipt
    if (info.isExpired () == Result.True)
    AND IF there is NO receipt
    then also assume (if was active) it is now not valid anymore.

    I would have excepted to only check the isExpired(), but I noticed that while testing on android the receipt went null when subscription was cancelled... which is not logical to me, but if it works this way so be it.

    My questions;
    -is this all I need to check for the end of a subscription (also for other platforms like ios)?
    -Since isExperired is never triggered in my tests, is checking agains result.True the right way or should I check against a string.
    -Should is use IsSubscribed == Result.True instead of isExperired() or both? (also what is the difference, i assume when one is active the other is always false or not?).
    -also what is the use of all the method for checking experiation etc if the receipt is null anyway once it is expired?

    Thank you, hopefully someone can help me with this so I can finally publish.
     
  2. wouter_vugt

    wouter_vugt

    Joined:
    Feb 25, 2015
    Posts:
    104
    btw testing on android the next billing date etc is also invalid, only showing the date of purchase for all. is this normal while testing subscriptions or is something wrong?
     
  3. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    6,094
    If there is no receipt, they do not have an active subscription. Subscriptions on Google Alpha/Beta testing expire very fast, within minutes. This is expected.
     
  4. wouter_vugt

    wouter_vugt

    Joined:
    Feb 25, 2015
    Posts:
    104
    doesn't that defeat the purpose of the IsSubscribed() method?
    If there is a receipt then the user is subscribed and otherwise you cannot check it since the receipt is gone.

    Anyway another question; is there a way to update the subscriptionInfo during runtime?
    I want to check for an active subscription everytime the user brings the app in focus.
    Right now if the user subscription has ended he can keep using the app until he restarts it.
     
  5. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    6,094
    @wouter_vugt There currently isn't a way to update the subscriptionInfo at runtime. Generally during IAP initialization is sufficient. Are you assuming that a user has the app open for more than a day or a week? I would not think that is very common. I don't think it would be a good user experience to remove a product in a middle of game play, but rather at game launch.
     
  6. wouter_vugt

    wouter_vugt

    Joined:
    Feb 25, 2015
    Posts:
    104
    Hi jeff,

    Well I almost never turn my phone off and keep apps running in the background.
    But I do see your point and I think I agree.

    Could you answer the isSubscribed question. As far as I understand you basically can't use it, since if a subscription has ended the receipt is gone as well.

    Btw do subscriptions also work on windows platform and/or mac?
     
  7. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    6,094
    If the corresponding stores allow you to create subscriptions, then we should support it. info.hasReceipt can determine whether a subscription is valid or not. The reason we need info.isSubscribed() method is for a subscription that may have a valid receipt when IAP initializes, but after a while it may expire, so the developer can use this to check if this subscription is still valid or not. During IAP initialization, the hasReceipt and info.isSubscribed do have the same functionality. In addition, we tested the next billing date, and is working as expected:

    10-25 12:52:52.553 15965 15979 I Unity : purchase date is: 10/25/2018 19:52:25
    10-25 12:52:52.553 15965 15979 I Unity :
    10-25 12:52:52.553 15965 15979 I Unity : (Filename: ./artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)
    10-25 12:52:52.553 15965 15979 I Unity :
    10-25 12:52:52.553 15965 15979 I Unity : subscription next billing date is: 11/25/2018 19:52:25
    10-25 12:52:52.553 15965 15979 I Unity :
     
    Last edited: Oct 25, 2018
  8. wouter_vugt

    wouter_vugt

    Joined:
    Feb 25, 2015
    Posts:
    104
    Thanks for your response.

    The info.IsSusbscribed() uses the receipt it got when IAP was initialized right.
    So when I use that to check if the receipt is still valid after initialization it wouldn't take into account any update that happens to the receipt (it might be renewed has a new end date etc), right?
    Or can I use that function confidently to check the subscription validation during runtime of the app (and it takes into account if the user paid for a new period etc)?

    Also the next billing date doesn't work while testing, the shortened time you get when testing doesn't reflect there. (which means during testing you receive the wrong end date etc).
     
    Last edited: Oct 28, 2018
  9. wouter_vugt

    wouter_vugt

    Joined:
    Feb 25, 2015
    Posts:
    104
    Very important:
    What is the differente between IsCancelled and IsSubscribed ?
    Currently i only check for isSubscribed, but noticed that when I cancel my test subscription on Android it returns isCancelled as true and isSubscribed as true.
    However the expire date is set a year later instead of 30min later, and even after cancellation the app remains as valid even through iT should be expired.
    Only when the recept is gone does it lock my app again.

    Is this an error due To the isexpired date not being set on the test times (30min) or am I doing something wrong?
    (How i have iT now: if has a receipt and isSubscribed is true then unlock else lock the app again (this only checks on initialisation) i am worried i am missing something here)

    Thanks :)
     
    Last edited: Oct 28, 2018
  10. wouter_vugt

    wouter_vugt

    Joined:
    Feb 25, 2015
    Posts:
    104
    Seriously, please give me more information than that, I asked a couple of questions and this is barely a response.
    I have been paying for unity for years, but I would expect some support for that in return, the few times I need it.
    The app is published as is and I need to know how this works exactly because the documentation is crap really.
    If I made some big mistakes I can release an update, but based on the documentation what I am doing should be correct, but again the documentation is really unclear.

    1.
    The documentation says this about the isCancelled:
    " A cancelled subscription means the Product is currently subscribed, but will not renew on the next billing date"

    Which means the product is still valid until the next billing date, at which point it will not renew.
    Meaning I would lock people out of the app while time was remaining on their subscription period.
    Also why would I need anything else then isSubscribed, I assume that when a user is subscribed they should get their product. If they cancelled their subscription and it expires I assume at that point the isSubscribed() function should return false.

    If I do need to use more then just the isSubscribed (and receipt check) then please just tell me straight out, what I am missing.

    2.
    Is the IsSubscribed() function an updated function. Meaning I could use at runtime reliably to check if the user is still subscribed or does it simply use cached data from initialization?
     
  11. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    6,094
    I am checking.
     
  12. wouter_vugt

    wouter_vugt

    Joined:
    Feb 25, 2015
    Posts:
    104
    any news on this...
     
  13. wouter_vugt

    wouter_vugt

    Joined:
    Feb 25, 2015
    Posts:
    104
    Really need to know...
     
  14. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    6,094
    What is the difference between IsCancelled and IsSubscribed ?

    * IsCancelled means the subscription will not be auto-renewed, but before the next billing date, it still be valid and IsSubscribed is true.

    As far as I understand you basically can't use it, since if a subscription has ended the receipt is gone as well.

    * If the UnityIAP does not initialize again, even though the subscription is expired, the receipt will not be gone.

    Btw do subscriptions also work on windows platform and/or mac?

    * Subscriptions only fully work on Android and Mac platforms

    So when I use that to check if the receipt is still valid after initialization it wouldn't take into account any update that happens to the receipt (it might be renewed has a new end date etc), right?

    * Yes, the receipt can only reflect the moment UnityIAP initializes. After the initialization, new updates will not occur in the receipt. That’s why we provide the getExpireDate() method, it will tell this subscription’s next billing date, before this date this subscription will be valid. And if this subscription is not cancelled (i.e. isAutoRenewing() is true), it will be renewed automatically on GooglePlay store after the next billing date. If you want to get the real time update of a subscription product, the best way is to use this google service https://developers.google.com/android-publisher/api-ref/inappproducts

    UnityIAP will not process and track the subscription products on GooglePlay store, what we do is during UnityIAP initialization, UnityIAP gets this subscription’s product info and provide it to the developers through the “SubscriptionManager” class.

    Or can I use that function confidently to check the subscription validation during runtime of the app (and it takes into account if the user paid for a new period etc)?

    * In current subscription support, this can only support to check during the Initialization process. This feature is very likely to be added in the future.

    However the expire date is set a year later instead of 30min later, and even after cancellation the app remains as valid even through iT should be expired.

    * The expire date for test mode for google play store is a little confusing. The one we get from google play store will be the same one you set up on Google Play console (like one month or one year) and the real one is actually the short one (like several minutes). So it is normal when the expireDate is the duration you set up on Google Play store.

    * cancellation will not let the subscription expire immediately. Cancel a subscription only means it will not be auto renewed in the next billing period, but it will be valid in the current billing period.

    Is the IsSubscribed() function an updated function. Meaning I could use at runtime reliably to check if the user is still subscribed or does it simply use cached data from initialization?

    * The IsSubscribed() function is not an updated one. This may be an added feature in the future to make it be a updated one.
     
    StijnPaladin and unityjingyao like this.
  15. wouter_vugt

    wouter_vugt

    Joined:
    Feb 25, 2015
    Posts:
    104
    Hi Jeff,

    Thanks for your extensive answer, appreciate it, believe this will be helpful for other as well.
    From what I understand the way I set it up now and how I thought it worked is correct.

    If possible it would be great to setup android test times in unity iAP as well.
    Since now if I test and cancel the subscription after only 5 minutes for example, unity thinks the current receipt is still valid for a year/month (even after new initialization) and so I cannot actively test user cancellations this way.

    Also using the isSubscribed() or any other method is currently only useful on initialization from what I understand since anytime after that the user could have changed stuff and you would still be using the outdated receipt from initialization.
    If there was a way to check subscriptions at runtime I think this would be great, as it is now users can use my app basically as long as they leave it open, which I think is unfair, it should stop when the users stopped paying for it.

    I will check on the windows platform, since you say not 'fully' supported, hopefully it is enough supported ;)

    thanks again.
     
  16. wavs

    wavs

    Joined:
    Feb 20, 2017
    Posts:
    2
    Hi,

    Thanks wounter_vugt / Jeff for your post, really helpful.

    I'm wondering: is there a way to know if a subscription product has an introductory price / free trial before purchasing it, as these infos seem to be available via SubscriptionManager only if we have the receipt.
    It will be helpful in order to display real price/free trial duration to the player.

    Thanks
     
  17. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    6,094
    @wavs This is a feature we are looking at for the next release.
     
    wavs likes this.
  18. Biggix

    Biggix

    Joined:
    Dec 8, 2014
    Posts:
    37
    Please could you update on this. Need a way to get the introductory price before the user makes a purchase. It doesn't make any sense otherwise.
     
  19. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    6,094
    No updates at this time. The next release is scheduled for first quarter 2019 which is the closest date provided so far, and we won't know the specific fixes that are going into the release until closer to that time.
     
  20. Biggix

    Biggix

    Joined:
    Dec 8, 2014
    Posts:
    37
    I was expecting that. Another major letdown.

    If anyone's having a similar issue, then a temporary workaround I found is to create a "dummy" consumable purchase with the same price as the introductory price, and then use some ugly code hacks to fetch that dummy price, when you need the introductory price. This works, but of course it isn't something I was willing to do. Not to mention that while for Google Play the IAPs are quite flexible (you can create virtually anything you want) - you will need to explain the requirement for that dummy purchase to Apple Review Team, and most likely they will reject this IAP.
     
  21. andymads

    andymads

    Joined:
    Jun 16, 2011
    Posts:
    1,464
    Do you think we'll see it by the end of March Jeff?
     
  22. PEZO19

    PEZO19

    Joined:
    Oct 24, 2013
    Posts:
    15
    I appreciate your help, but... this is still a mess.

    Please, we need serious support on IAP... This thread is the best to gather information but it is still a pain to read through because it is bloated and it is not as clear as it should be.

    Let me ask just this for the simplest use-case (eg. using it to decide if we need to show an ad - "at this moment").

    1. isSubscribed
    means userHasAValidSubscriptionForThisMomentBasedOnInformationAvailableAtTheTimeOfIAPInitialization ?
    Please let me know if that is right and please consider a better naming scheme, because "isSubscribed" can mean a lot of different things.

    2.A. What happens if
    + at the time of IAP init user has a valid subscription (isSubscribed returns true)
    + isCancelled returns true
    + while using the app, subscription goes invalid

    - At this point: isSubscribed returns false? (Being "pessimistic" about renewing?)

    2.B. What happens if
    + at the time of IAP init user has a valid subscription (isSubscribed returns true)
    + isCancelled returns false
    + while using the app, subscription renews

    - At this point: isSubscribed returns true? (Being "optimistic" about renewing?)

    2.C. What happens if
    + at the time of IAP init user has a valid subscription (isSubscribed returns true)
    + isCancelled returns false, BUT
    + user Cancels the subscription without restarting the app

    + while using the app, subscription goes invalid

    - Does isSubscribed (still) returns true? ( Being "optimistic" about renewing (BUT WRONG)? )

     
  23. PEZO19

    PEZO19

    Joined:
    Oct 24, 2013
    Posts:
    15
    Also it is not clear:

    Result from "isExpired" must equal to "!isSubscribed" in all the cases, right?
     
  24. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    6,094
    Subscriptions don't go invalid during game play, you check them when IAP initializes. So if the subscription time actually expires in the middle of game play, you plan to pull the product in the middle of their game? I might suggest to let them play out the current session. If you really want to pull the product during game play, you will need to reinitialize IAP during the game. Please see my previous post regarding isSubscribed. You can be subscribed (like through the end of the month), but is expired. Same for cancelled. Like any subscription, if you cancel it, you still get to keep it through the time period in which you already paid.
     
  25. PEZO19

    PEZO19

    Joined:
    Oct 24, 2013
    Posts:
    15
    I think you totally ignored some of my questions. Let's go explicit, please give me an example scenario how it is possible for every cases below (if you think something is possible, but I marked it as "not possible, right?").

    I am still not sure about the relation between isSubscribed(), isExpired() and isCancelled().

    Every method gives back a boolean so its 2*2*2=8 cases what they can give back in a particular moment.

    isSubscribed, isExpired, isCancelled : How is it possible? / Scenario
    1. false , false , false : user never subscribed
    2. false , false , true : not possible, right?
    3. false , true , false : not possible, right?

    4. true , false , false : user subscribed, did not cancel (will renew), did not expire (active sub)
    5. true , true , false : not possible, right?
    6. true , false , true : user subscribed, cancelled (will not renew), did not expire (active sub)
    7. false , true , true : not possible, right?
    8. true , true , true : user subscribed, cancelled (will not renew), expired (inactive sub)

    Are 6. and 8. legit?
    It seems really weird to being isSubscribed but isCancelled at the same time.
    - Especially in the case of 8. which seems close to 1. in meaning.
    - Or 2. is legit instead of 6.?

    [ MAIN QUESTION, PLEASE DO NOT IGNORE ]
    So to decide if a user has an active sub we must use this logic:
    isSubscribed() && !isExpired() , right?
    (info.isSubscribed() == Result.True ) && (info.isExpired() == Result.False)


    From here: https://docs.unity3d.com/Manual/UnityIAPSubscriptionProducts.html

    public Result isSubscribed()
    Returns a Result enum to indicate whether this Product is currently subscribed or not.

    public Result isExpired()
    Returns a Result enum to indicate whether this Product has expired or not.

    public Result isCancelled()
    Returns a Result enum to indicate whether this Product has been cancelled. A cancelled subscription means the Product is currently subscribed, but will not renew on the next billing date.
     
    Last edited: Nov 8, 2019
  26. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    6,094
  27. PEZO19

    PEZO19

    Joined:
    Oct 24, 2013
    Posts:
    15
    [ MAIN QUESTION, PLEASE DO NOT IGNORE ]
    So to decide if a user has an active sub we must use this logic:
    isSubscribed() && !isExpired() , right?
    (info.isSubscribed() == Result.True ) && (info.isExpired() == Result.False)

    Or what else??? Please, it is literally IAP 101 and not clear at all.
     
  28. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    6,094
    "So in this case, isSubscribed and isExpired are both true." and "we are checking".
     
  29. PEZO19

    PEZO19

    Joined:
    Oct 24, 2013
    Posts:
    15
    Great, thanks, I am looking forward to it!

    About testing: on Android it seems working fine to me with the logic as "isSubscribed" only, but not with "isSubscribed && !isExpired". But only tried it with Test subscription.

    Not tested on iOS yet at all.
     
  30. SamOYUnity3D

    SamOYUnity3D

    Unity Technologies

    Joined:
    May 12, 2019
    Posts:
    41
    You said "isSubscribed && !isExpired" doesn't work, does it mean that isExpired is true in some cases? After testing, at least in the test subscription mode I did not see isExpired=true, can you confirm? Thank you.

    The following are the test results(test subscription mode):

    After subscribing to the product:
    isSubscribed true
    isExpired: false
    isCancelled:false

    After unsubscribing in subscription management, if the subscription has not expired:
    isSubscribed: true
    isExpired: false
    isCancelled: true

    After unsubscribing in subscription management, if the subscription expires:
    Receipt is null

    If the user did not successfully renew at the time of renewal, before the grace period (if there is a grace period):
    isSubscribed true
    isExpired: false
    isCancelled:false

    If the user does not successfully renew at the time of renewal, after the grace period (if there is a grace period):
    Receipt is null
     
  31. SamOYUnity3D

    SamOYUnity3D

    Unity Technologies

    Joined:
    May 12, 2019
    Posts:
    41
    Currently isExpired will always be false on the Android platform, but this may change in the future as IAP continues to improve.