Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Unity IAP .isSubscribed() is always true?

Discussion in 'Unity IAP' started by ina, Oct 16, 2021.

  1. ina

    ina

    Joined:
    Nov 15, 2010
    Posts:
    1,080
    Unity IAP, latest Unity, latest IAP... it seems `.isSubscribed()` is always true? How does one find out whether a user has actually subscribed to an IAP product?

    ```
    for(int i = 0; i < subscription_product_id.Length; i++){
    SubscriptionInfo si = new SubscriptionInfo(subscription_product_id);
    print(si.isSubscribed() + " " + si.isCancelled()); // this returns true undefined for all products even ones that are not subscribed
    }
    ```
     
    Last edited: Oct 18, 2021
  2. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Have you subscribed to this product, what type is it? What is subscription_product_id.Length coming from? You're not using the value of i in you for loop, I'm not sure what this code is supposed to be doing.
     
  3. ina

    ina

    Joined:
    Nov 15, 2010
    Posts:
    1,080
    Hi! I simplified the code and forgot to include the index. Corrected. It's simply to check the subscription true state - of which every single product is true somehow.

    AFAIK I did not subscribe to the product. It returns true for every single subscription product, even when both 1 month and 1 year subscriptions are different products.

    I also sanity checked in an empty project.
     
  4. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Got it, it sounds like an issue at our end that we will look into.
     
  5. ina

    ina

    Joined:
    Nov 15, 2010
    Posts:
    1,080
    This seems pretty major. Is there another solution to checking if a user has a valid subscription or not?
     
  6. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    You can check the receipt directly, it's readable text that you can print out and examine the properties.
     
  7. ina

    ina

    Joined:
    Nov 15, 2010
    Posts:
    1,080
    Last edited: Oct 22, 2021
  8. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
  9. ina

    ina

    Joined:
    Nov 15, 2010
    Posts:
    1,080
    I'm trying to understand what your documented but not implemented feature .isSubscribed() is meant to do, when it gets fixed. What it is fixed, what are you guys checking for?
     
  10. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    I believe it's the isSubscribed property in the receipt, I would need to check. Have you generated the tangle files (menu Services/In-App Purchasing/Receipt Validation Obfuscator)? To be clear, it was working at one point, but needs checking again since we've started using Google Billing Library v3. And v4 is just around the corner, as is StoreKit2.
     
  11. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Please show your full code. If there is a receipt, generally there is a subscription. Did you issue a refund? You said earlier "I did not subscribe to the product". That would mean the receipt is still null, are you checking? You need to check for a non-null receipt before you do anything else. Please share your full purchasing script
     
  12. ina

    ina

    Joined:
    Nov 15, 2010
    Posts:
    1,080
    Are you saying that .isSubscribed() works (?)

    In that case, should my snippet above return false when an account has not subscribed to a product?

    So far I am testing in editor only set to iOS. It returns true always, even for an account that does not have anything subscribed. Only the AppStore subscription products have been setup.
     
  13. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    No, you shouldn't even be running that code. If there has been no purchase, the receipt is null. Please show your full code, as requested. You need to check for a null receipt before you run your code. Put in an "if" statement prior to your code.

    if (item.receipt != null)
    {
    //your code goes here
    }
    else
    {
    // no purchase!
    }
     
  14. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    @ina Please check out the Sample IAP Project v2 https://forum.unity.com/threads/sample-iap-project.529555/#post-6950270

    Code (CSharp):
    1.  public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
    2.     {
    3.         MyDebug("OnInitialized: PASS");
    4.  
    5.         m_StoreController = controller;
    6.         m_StoreExtensionProvider = extensions;
    7.         m_AppleExtensions = extensions.GetExtension<IAppleExtensions>();
    8.         m_GoogleExtensions = extensions.GetExtension<IGooglePlayStoreExtensions>();
    9.  
    10.         Dictionary<string, string> dict = m_AppleExtensions.GetIntroductoryPriceDictionary();
    11.        
    12.         foreach (UnityEngine.Purchasing.Product item in controller.products.all)
    13.         {
    14.             if (item.receipt != null)
    15.             {
    16.                 string intro_json = (dict == null || !dict.ContainsKey(item.definition.storeSpecificId)) ? null : dict[item.definition.storeSpecificId];
    17.  
    18.                 if (item.definition.type == ProductType.Subscription)
    19.                 {
    20.                     SubscriptionManager p = new SubscriptionManager(item, intro_json); //or just pass null for intro_json on Google
    21.                     SubscriptionInfo info = p.getSubscriptionInfo();
    22.                     MyDebug("SubInfo: " + info.getProductId().ToString());
    23.                     //Debug.Log(info.getPurchaseDate());
    24.                     MyDebug("getExpireDate: " + info.getExpireDate().ToString());
    25.                     MyDebug("isSubscribed: " + info.isSubscribed().ToString());
    26.                     //Debug.Log(info.isExpired());
    27.                     //Debug.Log(info.isCancelled());
    28.                     //Debug.Log(info.isFreeTrial());
    29.                     //Debug.Log(info.isAutoRenewing());
    30.                     //Debug.Log(info.getRemainingTime());
    31.                     //Debug.Log(info.isIntroductoryPricePeriod());
    32.                     //Debug.Log(info.getIntroductoryPrice());
    33.                     //Debug.Log(info.getIntroductoryPricePeriod());
    34.                     //Debug.Log(info.getIntroductoryPricePeriodCycles());
    35.                 }
    36.             }
    37.         }
    38.     }
     
    Last edited: Oct 29, 2021
  15. ina

    ina

    Joined:
    Nov 15, 2010
    Posts:
    1,080
    I think I might be not setting things up properly - also tried downloading the Sample IAP Project 2. Is Google Tangle obfuscator required for this to work in editor?

    Error is The type initializer for 'UnityEngine.Purchasing.Security.GooglePlayTangle' threw an exception.
     
  16. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Already replied on your other post. You need to generate the tangle files. Separate issue.
     
  17. ina

    ina

    Joined:
    Nov 15, 2010
    Posts:
    1,080
    @JeffDUnity3D So I checked out the samples included in IAP 4.1.1, but they don't seem to include how to validate without the user having made a purchase. (For example, Restore, or on Application start.)

    So the loop in my snippet above was what I thought a method to check for .isSubscribed(), but it seems to return true for all. What is the right way to check if a product has been subscribed (regardless of whether a purchase transaction has occurred)?
     
  18. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Yes, a user of course needs to make a purchase before you can validate the purchase receipt. Once purchased, the receipt is always available, including on their next session. ProcessPurchase is triggered during Restore, the receipt is available then also. As mentioned, if the receipt is null, no purchase has (ever) been made. The code above would be used on application start, that's when you initialize IAP. You only initialize IAP once.