tvOS IAPs Authenticate But Purchase not Awarded



  • Unfortunately I am relying on Unity IAP to work correctly on tvOS, since I cannot test it myself.

    Are there any device logs you could share at the time of purchase? Did you try to get the Unity IAP sample scene running to see whether there's an issue with the core plugin?



  • I haven't had an opportunity to run any tests with the demo scene on an actual device. Unfortunately I don't have the time resources to do that kind of testing with this project. This IAP implementation, however, does work, unchanged, on an iOS device.

    Here's the console output:

    2020-05-15 11:33:43.699431-0400 thresholdrunner[374:161310] UnityIAP UnityEarlyTransactionObserver: Created
    2020-05-15 11:33:43.701239-0400 thresholdrunner[374:161310] UnityIAP UnityEarlyTransactionObserver: Registered for lifecycle events
    CrashReporter: initialized
    2020-05-15 11:33:43.786335-0400 thresholdrunner[374:161310] Built from '2019.3/staging' branch, Version '2019.3.7f1 (6437fd74d35d)', Build type 'Release', Scripting Backend 'il2cpp'
    -> applicationDidFinishLaunching()
    2020-05-15 11:33:44.111098-0400 thresholdrunner[374:161310] UnityIAP UnityEarlyTransactionObserver: Added to the payment queue
    -> applicationDidBecomeActive()
    [Subsystems] Discovering subsystems at path /private/var/containers/Bundle/Application/CBBDF921-C4C5-4011-ABFB-DA63F8BE59E3/thresholdrunner.app/Data/UnitySubsystems
    GfxDevice: creating device client; threaded=1
    Initializing Metal device caps: Apple A8 GPU
    Initialize engine version: 2019.3.7f1 (6437fd74d35d)
    2020-05-15 11:33:44.710130-0400 thresholdrunner[374:161310] Unbalanced calls to begin/end appearance transitions for <SplashScreenController: 0x102077f50>.
    UnloadTime: 3.386667 ms
    UnityIAP Version: 1.23.1
    UnityEngine.Purchasing.StandardPurchasingModule:Instance(AppStore)
    SIS.IAPManager:Initialize()
     
    (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)
    Start playing the music!
    MoreMountains.InfiniteRunnerEngine.BackgroundMusic:Start()
     
    (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)
    Using registered configuration builder objects
    UnityEngine.Purchasing.StoreCatalogImpl:handleCachedCatalog(Action`1)
    System.Action`1:Invoke(T)
    UnityEngine.Purchasing.<Process>d__4:MoveNext()
    UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)
     
    (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)
    2020-05-15 11:33:49.756677-0400 thresholdrunner[374:161310] UnityIAP: Requesting 6 products
    2020-05-15 11:33:49.758431-0400 thresholdrunner[374:161310] UnityIAP: Requesting product data...
    CloudOnce Initialized
    UnityEngine.Events.UnityAction:Invoke()
    CloudOnce.Internal.Providers.iOSCloudProvider:<Initialize>b__19_0(Boolean)
    UnityEngine.Events.UnityAction`1:Invoke(T0)
    CloudOnce.Internal.Providers.<>c__DisplayClass20_0:<SignIn>b__0(Boolean)
    System.Action`1:Invoke(T)
    System.Action`2:Invoke(T1, T2)
    UnityEngine.SocialPlatforms.GameCenter.GameCenterPlatform:AuthenticateCallbackWrapper(Int32, String)
     
    (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)
    Unloading 5 Unused Serialized files (Serialized files now loaded: 0)
    UnloadTime: 4.711208 ms
    Unloading 12 unused Assets to reduce memory usage. Loaded Objects now: 1484.
    Total: 2.084542 ms (FindLiveObjects: 0.524292 ms CreateObjectMapping: 0.153167 ms MarkObjects: 1.191292 ms  DeleteObjects: 0.214917 ms)
    The referenced script (RewardedAdsButton) on this Behaviour is missing! 
    (Filename:  Line: 199)
    The referenced script on this Behaviour (Game Object 'Button - Watch Ad for Coins') is missing! 
    (Filename:  Line: 334)
    Unloading 3 Unused Serialized files (Serialized files now loaded: 0)
    UnloadTime: 2.617833 ms
    Unloading 116 unused Assets to reduce memory usage. Loaded Objects now: 2873.
    Total: 5.463792 ms (FindLiveObjects: 0.762875 ms CreateObjectMapping: 0.152500 ms MarkObjects: 4.001625 ms  DeleteObjects: 0.545708 ms)
    2020-05-15 11:33:53.337147-0400 thresholdrunner[374:161410] UnityIAP: Received 6 products
    2020-05-15 11:33:53.343429-0400 thresholdrunner[374:161410] UnityIAP: No App Receipt found
    2020-05-15 11:33:53.862377-0400 thresholdrunner[374:161310] UnityIAP: No App Receipt found
    OnInitialize() controller = UnityEngine.Purchasing.PurchasingManager
    UnityEngine.Purchasing.PurchasingManager:CheckForInitialization()
    UnityEngine.Purchasing.PurchasingManager:OnProductsRetrieved(List`1)
    UnityEngine.Purchasing.AppleStoreImpl:OnProductsRetrieved(String)
    System.Action:Invoke()
    UnityEngine.Purchasing.Extension.UnityUtil:Update()
     
    (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)
    UnityIAP: Promo interface is available for 6 items
    UnityEngine.Purchasing.Promo:ProvideProductsToAds(HashSet`1)
    UnityEngine.Purchasing.AppleStoreImpl:OnProductsRetrieved(String)
    System.Action:Invoke()
    UnityEngine.Purchasing.Extension.UnityUtil:Update()
     
    (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)
    2020-05-15 11:33:53.865340-0400 thresholdrunner[374:161310] UnityIAP: Add transaction observer
    2020-05-15 11:33:53.865566-0400 thresholdrunner[374:161310] UnityIAP UnityEarlyTransactionObserver: Request to initiate queued payments
    2020-05-15 11:33:53.970422-0400 thresholdrunner[374:161310] Nr 0: G:1657779475 - 19,949 Points - 2020-05-11 00:15:21 +0000
    2020-05-15 11:33:53.971772-0400 thresholdrunner[374:161310] Nr 1: G:1066583115 - 16,253 Points - 2020-05-02 14:39:18 +0000
    2020-05-15 11:33:53.972997-0400 thresholdrunner[374:161310] Nr 2: U:c1c8f1f724e2365c346db423c8d86ae4 - 10,226 Points - 2020-03-21 21:03:40 +0000
    2020-05-15 11:33:53.975189-0400 thresholdrunner[374:161310] Nr 3: G:195102620 - 8,955 Points - 2020-05-02 07:29:01 +0000
    2020-05-15 11:33:53.976568-0400 thresholdrunner[374:161310] Nr 4: G:38616620 - 8,530 Points - 2020-04-30 15:06:15 +0000
    2020-05-15 11:33:53.978053-0400 thresholdrunner[374:161310] Nr 5: G:1013544399 - 7,211 Points - 2020-05-14 13:51:38 +0000
    2020-05-15 11:33:53.978593-0400 thresholdrunner[374:161310] Nr 6: G:8428297453 - 4,734 Points - 2020-05-09 22:22:50 +0000
    2020-05-15 11:33:53.979084-0400 thresholdrunner[374:161310] Nr 7: G:11507083809 - 4,574 Points - 2020-05-12 21:14:56 +0000
    2020-05-15 11:33:53.980170-0400 thresholdrunner[374:161310] Nr 8: G:58611124 - 3,689 Points - 2020-03-23 00:37:02 +0000
    2020-05-15 11:33:53.981233-0400 thresholdrunner[374:161310] Nr 9: G:1547275131 - 3,670 Points - 2020-03-29 19:48:20 +0000
    localUserScore.value = 4734
    LeaderboardManager:<SetBestScore>b__23_0(Boolean)
    System.Action`1:Invoke(T)
     
    (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)
    2020-05-15 11:33:54.068616-0400 thresholdrunner[374:161310] Nr 0: G:1657779475 - 626 rubies - 2020-05-11 00:15:21 +0000
    2020-05-15 11:33:54.070011-0400 thresholdrunner[374:161310] Nr 1: G:1066583115 - 528 rubies - 2020-05-04 01:26:24 +0000
    2020-05-15 11:33:54.071139-0400 thresholdrunner[374:161310] Nr 2: G:195102620 - 263 rubies - 2020-05-02 07:29:01 +0000
    2020-05-15 11:33:54.072849-0400 thresholdrunner[374:161310] Nr 3: G:38616620 - 261 rubies - 2020-04-30 02:12:58 +0000
    2020-05-15 11:33:54.073591-0400 thresholdrunner[374:161310] Nr 4: G:8428297453 - 171 rubies - 2020-05-09 22:22:50 +0000
    2020-05-15 11:33:54.074200-0400 thresholdrunner[374:161310] Nr 5: G:1013544399 - 157 rubies - 2020-05-14 13:51:38 +0000
    2020-05-15 11:33:54.075862-0400 thresholdrunner[374:161310] Nr 6: G:11507083809 - 129 rubies - 2020-05-12 21:14:15 +0000
    2020-05-15 11:33:54.077007-0400 thresholdrunner[374:161310] Nr 7: U:c1c8f1f724e2365c346db423c8d86ae4 - 127 rubies - 2020-04-28 19:11:44 +0000
    2020-05-15 11:33:54.078246-0400 thresholdrunner[374:161310] Nr 8: G:272913521 - 104 rubies - 2020-05-02 21:56:25 +0000
    2020-05-15 11:33:54.079479-0400 thresholdrunner[374:161310] Nr 9: G:10496451868 - 76 rubies - 2020-05-01 16:44:36 +0000
    localUserRubies.value = 171
    LeaderboardManager:<SetBestScore>b__23_1(Boolean)
    System.Action`1:Invoke(T)
     
    (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)
    IAPItem 000 (UnityEngine.GameObject)
    <Coroutine>d__4:MoveNext()
    UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)
     
    (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)
    2020-05-15 11:34:01.960118-0400 thresholdrunner[374:161310] UnityIAP: PurchaseProduct: QT_TR_Cx1000
    purchase({0}): QT_TR_Cx1000
    SIS.IAPItem:Purchase()
    UnityEngine.Events.UnityAction:Invoke()
    UnityEngine.Events.UnityEvent:Invoke()
    UnityEngine.UI.Button:OnSubmit(BaseEventData)
    UnityEngine.EventSystems.EventFunction`1:Invoke(T1, BaseEventData)
    UnityEngine.EventSystems.ExecuteEvents:Execute(GameObject, BaseEventData, EventFunction`1)
    UnityEngine.EventSystems.StandaloneInputModule:SendSubmitEventToSelectedObject()
     
    (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)
    2020-05-15 11:34:01.981624-0400 thresholdrunner[374:161310] UnityIAP: UpdatedTransactions
    -> applicationWillResignActive()
    -> applicationDidBecomeActive()
    -> applicationWillResignActive()
    -> applicationDidBecomeActive()
    -> applicationWillResignActive()
    -> applicationDidBecomeActive()
    -> applicationWillResignActive()
    -> applicationDidBecomeActive()
    -> applicationWillResignActive()
    -> applicationDidBecomeActive()
    2020-05-15 11:35:41.981631-0400 thresholdrunner[374:161310] UnityIAP: UpdatedTransactions
    2020-05-15 11:35:42.019266-0400 thresholdrunner[374:161310] UnityIAP: Finishing transaction 1000000665526847
    UnityIAP: Promo interface is available for 6 items
    UnityEngine.Purchasing.Promo:ProvideProductsToAds(HashSet`1)
    UnityEngine.Purchasing.JSONStore:OnPurchaseSucceeded(String, String, String)
    System.Action:Invoke()
    UnityEngine.Purchasing.Extension.UnityUtil:Update()
     
    (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 35)
    


  • I ended up with at least a dozen charges for IAPs from Apple for purchases that were not rewarded the consumable/currency.

    Until we can figure out what's up I've had to upload a build that disables the store so that users aren't charged money for a consumable that they aren't getting.

    Again, this works just fine on the iOS store. For AppleTV there seems to be an issue. I can't say that it's directly related to Simple IAP but I have no other place to start at the moment since both the iOS and tvOS version use the same code. The only major difference is the UI. For AppleTV I needed to set up controller support for the IAPButton navigation.



  • I've create an additional post on the Unity IAP Forums.

    https://forum.unity.com/threads/tvos-iaps-authenticate-but-purchase-not-awarded.891754/



  • Except a few missing script references which seem to be related with rewarded videos, I cannot see an issue on the device log. Those should not cause the purchase to not complete. Thank you for posting on the Unity IAP forum - the response so far is a bit underwhelming.

    Double check that:

    • in the IAP Settings for your product, there is no platform override defined for iOS/Mac
    • the IAPListener script on the IAPManager prefab is active
    • in the case of currencies, DBManager.IncreaseFunds is called within the IAPManager script (PurchaseVerified method, line 502)

    As I said, unfortunately I don't have a chance to test this on a device. Still, the difference to iOS is very weird.



  • I don't have time to investigate this morning (EST) but I'll look into in and reply back later today to early tomorrow.

    That said, I'm also having an issue with MacOS standalone which I may post here as well if I don't find a solution in the meantime.



  • It doesn't look like I'm going to get much help from Unity. If you read the linked thread you will see what I mean.

    Maybe you can jump in there as well?



  • That's the standard support from Unity in the IAP section... they usually don't read topics in detail. Totally unrelated responses. But, like I suggested first, running the default Unity IAP sample scene would really point out if there's an issue with Unity IAP, then they have to investigate it. Unfortunately there's nothing else I could add to the discussion at this point.



  • I may have discovered the issue but I haven't been able to test it because of a slew of odd technical difficulties. If I eventually find that the fix works I'll report back here with the solution.



  • Okay so I figured out what was causing the issue. This has nothing to do with building to tvOS.

    When you made your 3 suggestions I was skeptical because I had double checked each one of those previously. In fact, I believe that the issue I was dealing with this week was the same issue that was plaguing me a few weeks ago.

    The IAPListener component was disabled. I did NOT disable this component. In fact, the last time I interacted with it I had enabled it to fix an issue with the iOS/Android build.

    I did not disable this component so I'm a bit dumbfounded as to how this can keep happening. Regardless, thanks for the support.



  • Even with the IAPListener script disabled, users should still be rewarded with products or currency, because the reward is happening in the IAPManager. The IAPListener only displays a UI message to the users to inform about the purchase.

    Did you implement your own reward mechanic into the IAPListener by any chance?

    I will look into the mysterious IAPListener disabling and try to get rid of the OnEnable+OnDisable methods.



  • I did implement the switch that governs the reward mechanic:

    /// <summary>
            /// Handle the completion of purchases, be it for products or virtual currency.
            /// Most of the IAP logic is handled internally already, such as adding products or currency to the inventory.
            /// However, this is the spot for you to implement your custom game logic for instantiating in-game products etc.
            /// </summary>
            public void HandleSuccessfulPurchase(string id)
            {
                if (IAPManager.isDebug) Debug.Log("IAPListener reports: HandleSuccessfulPurchase: " + id);
    
                //differ between ids set in the IAP Settings editor
                switch (id)
                {
                    case ("QT_TR_Cx1000"):
                        DBManager.IncreaseFunds("coins", 1000);
                        ShowMessage("1,000 coins were added to your balance");
                        break;
                    case ("QT_TR_Cx3300"):
                        DBManager.IncreaseFunds("coins", 3300);
                        ShowMessage("3,300 coins were added to your balance");
                        break;
                    case ("QT_TR_Cx6800"):
                        DBManager.IncreaseFunds("coins", 6800);
                        ShowMessage("6,800 coins were added to your balance");
                        break;
                    case ("QT_TR_Cx11500"):
                        DBManager.IncreaseFunds("coins", 11500);
                        ShowMessage("11,500 coins were added to your balance");
                        break;
                    case ("QT_TR_Cx24000"):
                        DBManager.IncreaseFunds("coins", 24000);
                        ShowMessage("24,000 coins were added to your balance");
                        break;
                    case ("QT_TR_Cx62500"):
                        DBManager.IncreaseFunds("coins", 62500);
                        ShowMessage("62,5000 coins were added to your balance");
                        break;
                    default:
                        Debug.LogError(id + " is not a valid case!");
                        break;
                }
            }
    

    This is in the IAPLIstener class. I do believe that this is where this code is supposed to be located as per the tutorial. Should I be calling DBManager.IncreaseFunds() elsewhere?



  • If you are using the latest version of SIS, currency rewards are given automatically on purchase, defined by the amount specified in the editor window:

    alt text

    If you are running an older version, the IAPListener is the correct location - as recorded in the video tutorial. But if you are running the latest version, defined earnings in the editor window and manually in the IAPListener, then you are giving out double currency to your users.



  • I must have the older version as the correct amount of coins are awarded.

    I'll keep this in mind, however, for future projects.

    Thanks.


Log in to reply