In 4.8.0 the new IAPButton was added. But in the CodelessIAPStoreListener.OnPurchaseFailed method, the handling of the new button was forgotten to add.
When using IAPButton, an error is thrown when cancelling a purchase, because IAPButton is added to the activeCodelessButtons list. Also IAPButton.OnPurchaseFailed() is never called.
public void OnPurchaseFailed(Product product, PurchaseFailureReason reason)
{
var resultProcessed = false;
foreach (var button in activeButtons.Where(button => button.productId == product.definition.id))
{
button.OnPurchaseFailed(product, reason);
resultProcessed = true;
}
// !!! This code is missing!!! Look at ProcessPurchase()
//
// foreach (var button in activeCodelessButtons.Where(button => button.productId == product.definition.id))
// {
// button.OnPurchaseFailed(product, reason);
//
// resultProcessed = true;
// }
foreach (var listener in activeListeners)
{
listener.OnPurchaseFailed(product, reason);
resultProcessed = true;
}
// we expect at least one receiver to get this message
if (!resultProcessed)
{
Debug.LogError("Failed purchase not correctly handled for product \"" + product.definition.id +
"\". Add an active IAPButton to handle this failure, or add an IAPListener to receive any unhandled purchase failures.");
}
}
1 Like
Thank you for the report!
I have confirmed the issue and this will be fixed in our next release.
Until then, you could add an IAPListener without any scripts linked to it and this should avoid the error.
Your new IAPButton will be called with the new OnPurchaseFailed(Product, PurchaseFailureDescription) which you can found in the same file below the code you posted.
1 Like
This happens when confirming purchase in the Fake Window - Purchase succeeds (I think) but fake window doesn’t close.
InvalidOperationException: Collection was modified; enumeration operation may not execute.
System.Collections.Generic.List`1+Enumerator[T].MoveNextRare () (at <88e4733ac7bc4ae1b496735e6b83bbd3>:0)
System.Collections.Generic.List`1+Enumerator[T].MoveNext () (at <88e4733ac7bc4ae1b496735e6b83bbd3>:0)
System.Linq.Enumerable+WhereListIterator`1[TSource].MoveNext () (at <f97e358e7a5e4bf5ba1b3e551d919146>:0)
UnityEngine.Purchasing.CodelessIAPStoreListener.ProcessPurchase (UnityEngine.Purchasing.PurchaseEventArgs e) (at Library/PackageCache/com.unity.purchasing@4.8.0/Runtime/Codeless/CodelessIAPStoreListener.cs:378)
UnityEngine.Purchasing.StoreListenerProxy.ProcessPurchase (UnityEngine.Purchasing.PurchaseEventArgs e) (at Library/PackageCache/com.unity.purchasing@4.8.0/Runtime/Purchasing/StoreListenerProxy.cs:35)
UnityEngine.Purchasing.PurchasingManager.ProcessPurchaseIfNew (UnityEngine.Purchasing.Product product) (at Library/PackageCache/com.unity.purchasing@4.8.0/Runtime/Purchasing/PurchasingManager.cs:310)
UnityEngine.Purchasing.PurchasingManager.OnPurchaseSucceeded (System.String id, System.String receipt, System.String transactionId) (at Library/PackageCache/com.unity.purchasing@4.8.0/Runtime/Purchasing/PurchasingManager.cs:127)
UnityEngine.Purchasing.JSONStore.OnPurchaseSucceeded (System.String id, System.String receipt, System.String transactionID) (at Library/PackageCache/com.unity.purchasing@4.8.0/Runtime/Stores/BaseStore/JSONStore.cs:168)
UnityEngine.Purchasing.FakeStore.<>n__0 (System.String id, System.String receipt, System.String transactionID) <0x22363bd2ad0 + 0x0006a> in <08c596a9a4e94715b9a5f367d86b5b76>:0
UnityEngine.Purchasing.FakeStore+<>c__DisplayClass15_0.<FakePurchase>g__handleAllowPurchase|0 (System.Boolean allow, UnityEngine.Purchasing.PurchaseFailureReason failureReason) (at Library/PackageCache/com.unity.purchasing@4.8.0/Runtime/Stores/FakeStore/FakeStore.cs:142)
UnityEngine.Purchasing.UIFakeStore+<>c__DisplayClass10_0`1[T].<StartUI>b__0 (System.Boolean result, System.Int32 codeValue) (at Library/PackageCache/com.unity.purchasing@4.8.0/Runtime/Stores/FakeStore/UIFakeStore.cs:72)
UnityEngine.Purchasing.UIFakeStore.OkayButtonClicked () (at Library/PackageCache/com.unity.purchasing@4.8.0/Runtime/Stores/FakeStore/UIFakeStore.cs:253)
UnityEngine.Purchasing.UIFakeStoreWindow.OnOkClicked () (at Library/PackageCache/com.unity.purchasing@4.8.0/Runtime/Stores/FakeStore/UIFakeStoreWindow.cs:89)
UnityEngine.Purchasing.UIFakeStoreWindow.DoMainGUI (System.Int32 windowID) (at Library/PackageCache/com.unity.purchasing@4.8.0/Runtime/Stores/FakeStore/UIFakeStoreWindow.cs:68)
UnityEngine.GUI.CallWindowDelegate (UnityEngine.GUI+WindowFunction func, System.Int32 id, System.Int32 instanceID, UnityEngine.GUISkin _skin, System.Int32 forceRect, System.Single width, System.Single height, UnityEngine.GUIStyle style) (at <ff6b5db041e141f9a771d6b39c070602>:0)
And on cancel
Failed purchase not correctly handled for product "no_ads". Add an active IAPButton to handle this failure, or add an IAPListener to receive any unhandled purchase failures.
UnityEngine.GUI:CallWindowDelegate (UnityEngine.GUI/WindowFunction,int,int,UnityEngine.GUISkin,int,single,single,UnityEngine.GUIStyle)
Upon starting game in the editor.
SerializedObjectNotCreatableException: Object at index 0 is null
UnityEditor.Editor.CreateSerializedObject () (at <57a8ad0d1492436d8cfee9ba8e6618f8>:0)
UnityEditor.Editor.GetSerializedObjectInternal () (at <57a8ad0d1492436d8cfee9ba8e6618f8>:0)
UnityEditor.Editor.get_serializedObject () (at <57a8ad0d1492436d8cfee9ba8e6618f8>:0)
UnityEditor.Purchasing.AbstractIAPButtonEditor.OnEnableInternal () (at Library/PackageCache/com.unity.purchasing@4.8.0/Editor/AbstractIAPButtonEditor.cs:26)
UnityEditor.Purchasing.IAPButtonEditor.OnEnable () (at Library/PackageCache/com.unity.purchasing@4.8.0/Editor/IAPButtonEditor.cs:20)
Closing unity and reopening project resolved this error.
Hello firesightstudios,
Is it possible that there’s a call to RemoveButton or a button being disabled while a purchase is being processed?
Are you still able to reproduce or was it a 1 time occurence?