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

IAP Renewal Subscription Help

Discussion in 'Unity IAP' started by tamana, Aug 5, 2019.

  1. tamana

    tamana

    Joined:
    Mar 14, 2017
    Posts:
    17
    Hello, Im trying to implement subscription system on my project.
    Im now facing serious problem with SubscriptionManager

    Code (CSharp):
    1.  
    2.             bool validPurchase = true;
    3. #if UNITY_ANDROID || UNITY_IOS || UNITY_STANDALONE_OSX
    4.             var validator = new CrossPlatformValidator(GooglePlayTangle.Data(),
    5.                 AppleTangle.Data(), Application.identifier);
    6.  
    7.             try
    8.             {
    9.                 var result = validator.Validate(e.purchasedProduct.receipt);
    10.                 CheckIfPurchaseIsFirstTimePurchaseAsync(result, e.purchasedProduct);
    11.             }
    12.             catch (IAPSecurityException)
    13.             {
    14.                 Debug.Log("Invalid receipt, not unlocking content");
    15.                 validPurchase = false;
    16.             }
    17. #endif
    18.             if (validPurchase)
    19.             {
    20.                 return ProcessPurchase_WithID(e.purchasedProduct.definition.id);
    21.             }
    22.  
    23.             return PurchaseProcessingResult.Pending;
    the code above is the callback after an item was purchased.

    Code (CSharp):
    1. public GetsugakuInformation GetGetsugakuInformation(string storeID)
    2.         {
    3.             SwiftUtility.debugLog("----------------------------------------------");
    4.             string intro_json = string.Empty;
    5.             try
    6.             {
    7.                 if(m_AppleExtensions == null)
    8.                 {
    9.                     SwiftUtility.debugLog("appleExtension is null");
    10.                 }
    11.                 m_AppleExtensions = Extensions.GetExtension<IAppleExtensions>();
    12.                 Dictionary<string, string> introductory_info_dict = m_AppleExtensions.GetIntroductoryPriceDictionary();
    13.  
    14.                 var getsugaku = Array.Find(Controller.products.all, x => x.definition.type == ProductType.Subscription && x.definition.storeSpecificId == storeID);
    15.                 if (getsugaku == null)
    16.                 {
    17.                     SwiftUtility.debugLog("getsugaku is null");
    18.                 }
    19.  
    20.                 intro_json = (introductory_info_dict == null ||
    21.                     !introductory_info_dict.ContainsKey(getsugaku.definition.storeSpecificId)) ? null : introductory_info_dict[getsugaku.definition.storeSpecificId];
    22.                 SubscriptionManager p = new SubscriptionManager(getsugaku, intro_json);
    23.                 if (p == null)
    24.                 {
    25.                     SwiftUtility.debugLog("p is null");
    26.                 }
    27.                 SubscriptionInfo info = p.getSubscriptionInfo();
    28.  
    29.                 SwiftUtility.debugLog($"info.isSubscribed : {info.isSubscribed()}");
    30.                 SwiftUtility.debugLog($"info.isExpired : {info.isExpired()}");
    31.                 SwiftUtility.debugLog($"info.isCancelled : {info.isCancelled()}");
    32.                 SwiftUtility.debugLog($"info.isAutoRenewing : {info.isAutoRenewing()}");
    33.  
    34.                 var getsugakuInfo = new GetsugakuInformation(info.getProductId(), info.getPurchaseDate(), info.getExpireDate(),
    35.                     info.isSubscribed() == Result.True ? true : false,
    36.                     info.isExpired() == Result.True ? true : false,
    37.                     info.isCancelled() == Result.True ? true : false,
    38.                     info.isAutoRenewing() == Result.True ? true : false,
    39.                     info.getRemainingTime());
    40.  
    41.                 return getsugakuInfo;
    42.             }
    43.             catch (Exception e)
    44.             {
    45.  
    46. #if UNITY_ANDROID
    47.                 Debug.Log($"Exception : {e.Message}");
    48. #elif UNITY_IOS
    49.                 SwiftUtility.debugLog($"intro_json : {intro_json}");
    50.                 SwiftUtility.debugLog($"Exception : {e.Message}");
    51.                 SwiftUtility.debugLog($"StackTrace : {e.StackTrace}");
    52. #endif
    53.             }
    54.  
    55.             return GetsugakuInformation.Empty;
    56.         }
    I used the code above to look information from SubscriptionManager class.
    After 5 minutes passed since last purchased,
    isSubscribed became false from true.
    isAutoReneweing became false from true.
    isExpired became true after false.

    The problem is subscription item became null after 5 minutes passed.
    And SubscriptionManager unable to execute getSubscriptionInfo() method after receipt became null

    Question is why the subscribed item wasn't renewed after 5 minutes passed?
    Shouldn't it get renew up to 6 times according to apple documentation?
    Please help me...
     
    Last edited: Aug 5, 2019
  2. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Is this an auto-renew subscription? I suspect that auto-renew may not be available in Sandbox. The fast expire times are expected during testing.
     
  3. domdev

    domdev

    Joined:
    Feb 2, 2015
    Posts:
    375
    Hi I'm using subscription, how I can detect if the subscription was newly renewed?
     
  4. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    @domdev I believe you'll get a ProcessPurchase callback upon renew. You can also check the receipt fields.
     
  5. domdev

    domdev

    Joined:
    Feb 2, 2015
    Posts:
    375
    yes but I wanna get the trigger where user subscription was renewed..
     
  6. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Yes, that was my suggestion. You will get the trigger when IAP is initialized, there is no callback during a running game, if that is what you are asking. So if a subscription was renewed at midnight on the Play Store, the next time the user launches your app in the morning, they would receive this.
     
  7. domdev

    domdev

    Joined:
    Feb 2, 2015
    Posts:
    375
    I mean how? in initialized I only check if has hasReceipt, and that only for checking if subsciption still active.. my goal is to give a reward monthly for subscribe users.. so I want to get maybe at least date to compare.. or a trigger.. im okay with during open of the app initialized
     
  8. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Are you not receiving a ProcessPurchase callback when the subscription renews? How are you tracking your purchases on the device, are you saving to a local binary file, or to PlayerPrefs by chance? Another solution, if their subscription is active, just start tracking one month from their initial purchase (save the purchase date locally)
     
  9. domdev

    domdev

    Joined:
    Feb 2, 2015
    Posts:
    375
    right now I'm just using this 3 code for checking
    Debug.Log(m_StoreController.products.WithID(kProductIDSubscription).hasReceipt + " hasReceipt");
    Debug.Log(m_StoreController.products.WithID(kProductIDSubscription).receipt + " receipt");
    Debug.Log(m_StoreController.products.WithID(kProductIDSubscription).availableToPurchase + " availableToPurchase");

    but not sure where to get when the subcription renews
     
  10. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    It would help to troubleshoot if you could answer my questions.
     
  11. domdev

    domdev

    Joined:
    Feb 2, 2015
    Posts:
    375
    what do you mean?
    Are you not receiving a ProcessPurchase callback when the subscription renews?
    - yes I'm getting ProcessPurchase callback, but I'm dont know where to get the remaining time before renewal happens
    How are you tracking your purchases on the device
    - I'm using monitor in adb and srdebugger asset if not adb
    are you saving to a local binary file, or to PlayerPrefs by chance?
    - no I'm not saving yet, but planing if no choice.. but I wanna make it online or updated as possible to aviod cheating for smart users
     
  12. domdev

    domdev

    Joined:
    Feb 2, 2015
    Posts:
    375
    Hi jeff, I was getting now purchase date and remaining time, but now it seems the time was not the same base of my location.. like this , got
    purchaseDate 08/30/2019 01:52:51
    and date for the next billing 09/06/2019 01:52:51..
    is it possible to used online time? base in what is given? like I want it check everytime the user opens the app..

    next billing 09/06/2019 01:52:51 - time when user opens the app, is it right? and what time should I get? base from user
     
  13. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    We don't control the time or receipt format, these are Apple and Google receipts. If you received a ProcessPurchase, then it just renewed.
     
  14. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    By tracking your purchases, I meant, how are you persisting the purchase on the user device. Also, you can use server side validation if you choose, in addition to local receipt validation, and save purchases to the cloud. This is what many large studios use.
     
  15. sanathkukkillaya

    sanathkukkillaya

    Joined:
    Nov 14, 2019
    Posts:
    37
    Hi Jeff,
    I came across this thread while I was checking an answer for something else.
    I wasn't aware till now that on auto-renewal of a subscription, ProcessPurchase callback is called when we call Unity purchasing.initialize(). Now as per this thread and some other threads that I checked, ProcessPurchase should be automatically called.

    To test this, I tried checking my logs to see if this was happening in my game as well. I bought a subscription, waited for 5 min, verified that the subscription was renewed by checking in the Play store, and then again opened my game. But while I could see that initialisation was successful, ProcessPurchase didn't get called.

    Should I call some method after initialisation, in OnInitialized method, such as store controller.InitiatePurchase()?
    Is my understanding of the flow correct?
     
  16. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    I was mistaken, ProcessPurchase is not expected upon subscription renewal. You'll want to check the receipt for subscription status. If no receipt, then no subscription.