title: Unity IAP (2.2.7 & 3.0.1) consumable item, transaction completion issue
body: <p>I have 12 consumable items in &quot;Ready To Submit&quot; status and I am trying to purchase 1 of them again and again by using
  a sandbox tester account. In the initialization process, I can receive the product successfully. I can initiate a purchase flow by giving the name
  of the product. In the &quot;ProcessPurchase&quot; callback, I can read all required data like transactionId, payload, etc. and completing the process
  by returning PurchaseProcessingResult.Complete. I expect UnityIAP to complete the transaction and make the current item available to purchase again.</p>
  <p>The problem is, when I try to buy the previous item again, it shows &quot;This In-App Purchase has already been bought&quot; popup. Here is the log file :</p>
  <pre><code>PurchaseController - ,Purchasing product asychronously: 'mini_coin_pack'
  PurchaseController:BuyProductID(String)
  UnityEngine.Events.UnityAction:Invoke()
  UnityEngine.Events.UnityEvent:Invoke()
  UnityEngine.EventSystems.EventFunction`1:Invoke(T1, BaseEventData)
  UnityEngine.EventSystems.ExecuteEvents:Execute(GameObject, BaseEventData, EventFunction`1)
  UnityEngine.EventSystems.StandaloneInputModule:ProcessTouchPress(PointerEventData, Boolean, Boolean)
  UnityEngine.EventSystems.StandaloneInputModule:ProcessTouchEvents()
  UnityEngine.EventSystems.StandaloneInputModule:Process()
   
  (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 39)
  
  2021-04-15 15:34:14.006798+0300 mygame[1689:850412] UnityIAP: PurchaseProduct: mini_coin_pack
  purchase(mini_coin_pack)
  UnityEngine.Events.UnityAction:Invoke()
  UnityEngine.Events.UnityEvent:Invoke()
  UnityEngine.EventSystems.EventFunction`1:Invoke(T1, BaseEventData)
  UnityEngine.EventSystems.ExecuteEvents:Execute(GameObject, BaseEventData, EventFunction`1)
  UnityEngine.EventSystems.StandaloneInputModule:ProcessTouchPress(PointerEventData, Boolean, Boolean)
  UnityEngine.EventSystems.StandaloneInputModule:ProcessTouchEvents()
  UnityEngine.EventSystems.StandaloneInputModule:Process()
   
  (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 39)
  
  2021-04-15 15:34:14.048335+0300 mygame[1689:850412] UnityIAP: UpdatedTransactions
  -&gt; applicationWillResignActive()
  -&gt; applicationDidBecomeActive()
  2021-04-15 15:34:22.947604+0300 mygame[1689:850412] UnityIAP: UpdatedTransactions
  2021-04-15 15:34:22.948039+0300 mygame[1689:850412] UnityIAP: DuplicateTransaction error with product mini_coin_pack and transactionId 1000000801477725
  -&gt; applicationWillResignActive()
  onPurchaseFailedEvent(productId:mini_coin_pack message:Duplicate transaction occurred)
  UnityEngine.Purchasing.PurchasingManager:OnPurchaseFailed(PurchaseFailureDescription)
  System.Action:Invoke()
  UnityEngine.Purchasing.Extension.UnityUtil:Update()
   
  (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 39)
  
  PurchaseController - ,OnPurchaseFailed, Product : mini_coin_pack, Reason : DuplicateTransaction
  PurchaseController:OnPurchaseFailed(Product, PurchaseFailureReason)
  System.Action:Invoke()
  UnityEngine.Purchasing.Extension.UnityUtil:Update()
   
  (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 39)
  
  PurchaseController - ,Store specific error code: Unknown
  PurchaseController:OnPurchaseFailed(Product, PurchaseFailureReason)
  System.Action:Invoke()
  UnityEngine.Purchasing.Extension.UnityUtil:Update()
   
  (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 39)
  
  PurchaseController - ,Purchase failure description message: Duplicate transaction occurred
  PurchaseController:OnPurchaseFailed(Product, PurchaseFailureReason)
  System.Action:Invoke()
  UnityEngine.Purchasing.Extension.UnityUtil:Update()
   
  (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 39)
  
  -&gt; applicationDidBecomeActive()
  </code></pre>
  <p>When I kill and relaunch the app, following logs show that there is still a transaction to complete from previous try.</p>
  <pre><code>2021-04-15 15:35:03.181235+0300 mygame[1699:852283] UnityIAP UnityEarlyTransactionObserver: Created
  2021-04-15 15:35:03.182006+0300 mygame[1699:852283] UnityIAP UnityEarlyTransactionObserver: Registered for lifecycle events
  CrashReporter: initialized
  2021-04-15 15:35:03.215730+0300 mygame[1699:852283] Built from '2019.4/staging' branch, Version '2019.4.23f1 (3f4e01f1a5ec)', Build type 'Release', Scripting Backend 'il2cpp'
  2021-04-15 15:35:03.228051+0300 mygame[1699:852283] MemoryManager: Using 'Default' Allocator.
  -&gt; applicationDidFinishLaunching()
  2021-04-15 15:35:03.528270+0300 mygame[1699:852283] UnityIAP UnityEarlyTransactionObserver: Added to the payment queue
  -&gt; applicationDidBecomeActive()
  GfxDevice: creating device client; threaded=1
  Initializing Metal device caps: Apple A8 GPU
  Initialize engine version: 2019.4.23f1 (3f4e01f1a5ec)
  CrashReporter: No pending report exists at /var/mobile/Containers/Data/Application/01EA9697-0BD5-40AF-BB20-967567B5EAE2/Library/Caches/CrashReports/crash-pending.plcrash
  UnloadTime: 1.242625 ms
  UnityIAP Version: 3.0.1
  UnityEngine.Purchasing.StandardPurchasingModule:Instance(AppStore)
  PurchaseController:InitializePurchasing()
   
  (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 39)
  
  2021-04-15 15:35:06.133617+0300 mygame[1699:852283] UnityIAP: Requesting 1 products
  2021-04-15 15:35:06.201046+0300 mygame[1699:852283] UnityIAP: Requesting product data...
  2021-04-15 15:35:07.031669+0300 mygame[1699:852283] UnityIAP: Received 1 products
  PurchaseController - ,OnInitialized
  PurchaseController:OnInitialized(IStoreController, IExtensionProvider)
  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: 39)
  
  PurchaseController - ,Mini Coin Pack, is ready to purchase!
  PurchaseController:OnInitialized(IStoreController, IExtensionProvider)
  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: 39)
  
  UnityIAP: Initialization complete with  1 items
  UnityEngine.Purchasing.Promo:ProvideProductsToAds(HashSet`1, Boolean)
  UnityEngine.Purchasing.AppleStoreImpl:OnProductsRetrieved(String)
  System.Action:Invoke()
  UnityEngine.Purchasing.Extension.UnityUtil:Update()
   
  (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 39)
  
  2021-04-15 15:35:07.079768+0300 mygame[1699:852283] UnityIAP: Add transaction observer
  2021-04-15 15:35:07.080293+0300 mygame[1699:852283] UnityIAP: UpdatedTransactions
  2021-04-15 15:35:07.084949+0300 mygame[1699:852283] UnityIAP UnityEarlyTransactionObserver: Request to initiate queued payments
  Already recorded transaction 1000000801477725
  UnityEngine.Purchasing.PurchasingManager:ProcessPurchaseIfNew(Product)
  UnityEngine.Purchasing.JSONStore:OnPurchaseSucceeded(String, String, String)
  System.Action:Invoke()
  UnityEngine.Purchasing.Extension.UnityUtil:Update()
   
  (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 39)
  
  2021-04-15 15:35:07.095638+0300 mygame[1699:852283] UnityIAP: Finishing transaction 1000000801477725
  </code></pre>
  <p>The last line of the above log, shows that ProcessPurchase callback method is called during app launch and transaction has tried to complete again.</p>
  <p>Here is my sandbox code I used during testing :</p>
  <pre><code>using UnityEngine;
  using UnityEngine.Purchasing;
  using UnityEngine.UI;
  
  public class PurchaseController : MonoBehaviour, IStoreListener
  {
      private IStoreController _storeController;
      private IExtensionProvider _extensionProvider;
  
      [SerializeField] private Button _purchaseButton;
      
      private string _miniCoinPack = &quot;mini_coin_pack&quot;;
  
      private void Awake()
      {
          _purchaseButton.onClick.AddListener(BuyConsumable);
          DontDestroyOnLoad(gameObject);
      }
  
      private void Start()
      {
          if (_storeController == null)
          {
              InitializePurchasing();
          }
      }
      
      private void InitializePurchasing()
      {
          if (IsInitialized()) return;
          var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
          builder.AddProduct(_miniCoinPack, ProductType.Consumable);
          UnityPurchasing.Initialize(this, builder);
      }
      
      public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
      {
          _storeController = controller;
          _extensionProvider = extensions;
          
          foreach (var product in _storeController.products.set)
          {
              if (product.hasReceipt)
              {
                  _storeController.ConfirmPendingPurchase(product);
              }
              if (product.availableToPurchase)
              {
                  Log(product.metadata.localizedTitle + &quot;, is ready to purchase!&quot;);
              }
          }
      }
      
      public void OnInitializeFailed(InitializationFailureReason error)
      {
          Log(&quot;OnInitializeFailed: &quot; + error);
      }
      
      private bool IsInitialized()
      {
          return _storeController != null &amp;&amp; _extensionProvider != null;
      }
      
      public void BuyConsumable()
      {
          BuyProductID(_miniCoinPack);
      }
      
      private void BuyProductID(string productId)
      {
          if (IsInitialized())
          {
              Product product = _storeController.products.WithID(productId);
              if (product != null &amp;&amp; product.availableToPurchase)
              {
                  Log(string.Format(&quot;Purchasing product asychronously: '{0}'&quot;, product.definition.id));
                  _storeController.InitiatePurchase(product, &quot;{\&quot;userID\&quot;:\&quot;313131696969\&quot;}&quot;);
              }
              else
              {
                  Log(&quot;BuyProductID: FAIL. Not purchasing product, either is not found or is not available for purchase&quot;);
              }
          }
          else
          {
              Log(&quot;BuyProductID FAIL. Not initialized.&quot;);
          }
      }
  
      public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)
      {
          Log(&quot;purchase success for : &quot; + args.purchasedProduct.definition.id);
          return PurchaseProcessingResult.Complete;
      }
  
      public void OnPurchaseFailed(Product product, PurchaseFailureReason failureReason)
      {
          Log(string.Format(&quot;OnPurchaseFailed, Product : {0}, Reason : {1}&quot;, product.definition.storeSpecificId, failureReason));
          var transactionHistoryExtensions = _extensionProvider.GetExtension&lt;ITransactionHistoryExtensions&gt;();
          Log(&quot;Store specific error code: &quot; + transactionHistoryExtensions.GetLastStoreSpecificPurchaseErrorCode());
          if (transactionHistoryExtensions.GetLastPurchaseFailureDescription() != null)
          {
              Log(&quot;Purchase failure description message: &quot; + transactionHistoryExtensions.GetLastPurchaseFailureDescription().message);
          }
      }
  
      private void Log(string message)
      {
          Debug.Log(string.Concat(&quot;PurchaseController - ,&quot;, message));
      }
  }
  </code></pre>
  <p>I have tried different ways to integrate UnityIAP into my sandbox Unity project like :</p>
  <ul>
  <li>using only unity package manager and installing (2.2.7 &amp; 3.0.2 respectively)</li>
  <li>activating In-App Purchasing &amp; Analytics services and installing UnityIAP package from there.</li>
  </ul>
  <p><strong>Unity Version</strong> : 2019.4.22f1, 2019.4.23f1</p>
  <p><strong>Unity IAP Version</strong> : 2.2.7, 3.0.2</p>
  <p><strong>Test Device</strong> : iPhone 6, iOS 12.5.1</p>
  <p><strong>Test User</strong> : Sandbox Tester (Country : United States, Interrupted Purchases : disabled, Apple Pay: Yes)</p>
  <p><strong>App Store Connect App Status</strong> : Prepare For Submission (Not submitted yet!)</p>
  <p><strong>In App Purchase Items</strong> : (Type:Consumable, Status:Ready To Submit)</p>
  <p>It seems like this problem is fixed with UnityIAP-2.2.2 version as stated here : <a href="https://forum.unity.com/threads/unity-iap-package-3-0-2-is-now-available.415517/page-2" rel="nofollow noreferrer">https://forum.unity.com/threads/unity-iap-package-3-0-2-is-now-available.415517/page-2</a>
  but it still exist in 2.2.7 &amp; 3.0.2 versions.</p>
  <p>Is there anyone else who face the same or similar behaviour while implementing UnityIAP?</p>