The logs are huge, what are we looking for? Are there exceptions or errors in the logs? Please filter, and please provide steps to reproduce. What type of product are you trying to purchase after the Restore? You can only purchase non-consumables and subscriptions once. To be fair, we’ve heard of this behavior from another user also, but I’m not able to reproduce. Also share the version of IAP and Unity that you are using.
Is this a recent issue? Did Apple change anything? Does anyone know any update here? Because we too are facing this issue. Our last build, things looked fine. Today when we again tested the build for something else, we got stuck in the purchase screen, due to DuplicateTransaction issue.
I tested for a while. After some time it goes away, and I am able to buy the product. Seems like IAppleExtension.RestoreTransaction() seems to initiate something that takes some while to complete. Although I receive the boolean, still there seems to be some process running that prevents the current product from purchasing.
Got it, thanks for sharing. So the user has never purchased the product before (or any product), yet is receiving Duplicate Transaction? This only happens on the very first purchase by the user? Is this a consumable product?
We are using a subscription product. I am not sure if this happens for other types of products as well. During testing, I can replicate this once the subscription is expired, and I click on restore purchase. before clicking on the product
So the product was purchases previously if the subscription is expired. Please include all steps for clarity. There does seem to be an issue, but we need clear steps to reproduce.
To clarify, this will occur whenever we try to restore a purchase, when there is nothing to restore. So there are two likely scenarios-
First time we click on Restore button, there will be no products purchased yet. After this if we try to buy something, the duplicatetransaction error is shown
If we buy a subscription, and after a few minutes, it expires (sandbox mode). Now if we try to restore, again there is nothing to restore. After this if we try to buy the subscription again, the duplicatetransaction error will be shown.
Hope I am clear here. I might be wrong about how restore works, since this is the first time I am implementing this. But I have followed the documentations as far as possible, and there is not much to do other than just call RestoreTransaction and wait for a result (which will always be returned).
@JeffDUnity3D As a quick hotfix is there any way to check if there are any products to restore? This way I can ensure that restore runs only when there are actually products to restore. Please this is a bit urgent issue.
Our products were consumables, but still got this duplicate transaction issue. We were using Apple Sandbox to test the purchases, so it might be a Sandbox-only issue. Unfortunately, we didn’t know how to reproduce the issue, it happened randomly, once it happened, it happened all the time.
@JeffDUnity3D , any updates on this issue? Were you able to replicate this or look into it? This is a pretty major issue since it will not let us proceed further in the game as the user is not able to buy anything.
@better_walk_away were you able to test if this issue occurs in production as well?
@JeffDUnity3D I seem to have found another issue with Restore Purchase. The restore purchase method appears to be triggering the ProcessPurchase callback multiple times. I am not sure why. We just have two subscription products, so as far as I understand, the restore purchase is called for each product. So at the most there should be two calls.
However somehow the ProcessPurchase seems to be triggering multiple times for me. I previously thought, since I was calling Pending status and confirming it after validation, there must have been some loop running which was resulting in multiple calls. However, after checking and changing the code to call Complete status for RestorePurchase, I can still see that multiple calls to ProcessPurchase are happening. I’ll share my code below for your reference.
public void RestorePurchases()
{
Debug.Log("Restore IAP link");
if (!IsInitialized())
{
Debug.Log("RestorePurchases FAIL. Not initialized.");
OnRestoreComplete?.Invoke(false);
return;
}
if (Application.platform == RuntimePlatform.IPhonePlayer ||
Application.platform == RuntimePlatform.OSXPlayer)
{
Debug.Log("RestorePurchases started ...");
var apple = _extensionProvider.GetExtension<IAppleExtensions>();
isRestoring = true;
apple.RestoreTransactions((result) =>
{
Debug.Log("RestorePurchases continuing: " + result + ". If no further messages, no purchases available to restore.");
OnRestoreComplete?.Invoke(result);
});
}
else
{
Debug.Log("RestorePurchases FAIL. Not supported on this platform. Current = " + Application.platform);
OnRestoreComplete?.Invoke(false);
}
}
The last time I ran the app, the Restored products count was around 135. This is causing the loading time to take a very long time, and more critically the purchase flow to behave very unexpectedly.
I am really a bit worried right now, since I have had multiple issues with Unity IAP. This is the 3rd or 4th major issue that I am facing with subscription. A couple of them, you have already mentioned that they are being looked into. Another one, related to testing times, you’ve said that you cannot control. However this issue and the previous issue with the duplicate transaction are the major issues that is really causing me a lot of frustration. I am not being able to submit the game to the app store due to these restore issues.
How can there be so many bugs in this? Am I doing something really wrong with my code structure? Or are there really these many game-breaking bugs in subscription module of Unity IAP? How are there so many games out there created with Unity with subscription? Is there any way I can contact one of you guys and understand what could be causing these issues?
Though we are also facing this duplicate transaction issue when testing using TestFlight and the Sandbox environment, we decided to roll out the new version of the game regardless, we rolled out the new version of the game on Christmas Eve. So far, we haven’t received any error messages regarding iOS IAP, so I think it’s a Sandbox-only issue.
@better_walk_away Thanks for that information. If its only in Sandbox mode, I can convince the QA team to pass the build. However, I feel this is something that needs to be addressed on priority by Unity, since this is a potential blocker as user will neither be able to restore, nor able to purchase a new subscription.
We have no control over the Apple Sandbox environment. You might expect multiple callbacks if you are using their test environment and the subscription renewed several times within 15 minutes for example.
@JeffDUnity3D Can you give me an idea on how I can handle this scenario? How can I control which product is being restored? Will the first product be the correct item to restore or the last product?
Also, it would be very helpful if you could help me understand how this code works:
var apple = _extensionProvider.GetExtension<IAppleExtensions>();
isRestoring = true;
apple.RestoreTransactions((result) =>
{
Debug.Log("RestorePurchases continuing: " + result + ". If no further messages, no purchases available to restore.");
OnRestoreComplete?.Invoke(result);
});
As per my understanding, the OnRestoreComplete should be called once all the products have completed ProcessPurchase. But I am not sure if this is 100% valid. Sometimes OnRestoreComplete is called after all products, and sometimes ProcessPurchase will still be called after OnRestoreComplete, I think. I keep getting a bit lost with my async logs, to be honest. I just want to restore one product and then discard the others. So I am thinking of keeping some boolean flag. But I am not getting where exactly to add it.