title: Unity IAP - how to restore my Android purchases
body: <p>I made an Android payment system with IAP and it is currently registered in the App Store. However, a customer paid for the product and used it, but when I turned on the app again, the payment disappeared and the payment was proceeded again, and the window said, &quot;It's an item I already have,&quot; and I couldn't pay.</p>
  <p>So we need to add payment restoration function, but the official document and googling don't have an accurate restoration method. The only way to find it is old ways and errors I need to add a restoration function as soon as possible. How can I do this? I added the corresponding payment code below UNI.T version is 2021.3.3f1</p>
  <p>Also, I added a script to the IAP button using OnPurchaseComplete without IStoreListener and proceeded with the payment, and I would like to recover it. They're all non-consumable products.</p>
  <p>IAPScript:</p>
  <pre><code>using System;
  using System.Collections.Generic;
  using UnityEngine;
  using UnityEngine.Purchasing;
  using UnityEngine.UI;
  using UnityEngine.Purchasing.Security;
  
  
  public class IAPScript : GenericSingleton&lt;IAPScript&gt; 
  {
      public string ChapterID_01 = &quot;hisshow_vr_ani_01&quot;;
      public string ChapterID_02 = &quot;hisshow_vr_ani_02&quot;;
      public string ChapterID_03 = &quot;hisshow_vr_ani_03&quot;;
      public string ChapterID_04 = &quot;hisshow_vr_ani_04&quot;;
      public string ChapterID_05 = &quot;hisshow_vr_ani_05&quot;;
      public string ChapterID_06 = &quot;hisshow_vr_ani_06&quot;;
      public string AllChapterID = &quot;hisshow_vr_ani_package&quot;;
      public string PilgrID = &quot;hisshow_vr_360_package&quot;;
  
  
      //Code for activating the corresponding commodity button
      public AdventurePurchaseManager AdventurePurchaseManager;
      public PilgrimagePurchassManager PilgrimagePurchassManager;
      //
  
  
      private void Start()
      {
          /*PlayerPrefs.DeleteKey(&quot;Cash1900_01&quot;);
          PlayerPrefs.DeleteKey(&quot;Cash1900_02&quot;);
          PlayerPrefs.DeleteKey(&quot;Cash1900_03&quot;);
          PlayerPrefs.DeleteKey(&quot;Cash1900_05&quot;);
          PlayerPrefs.DeleteKey(&quot;Cash1900_06&quot;);
          PlayerPrefs.DeleteKey(&quot;Cash7900&quot;);
          PlayerPrefs.DeleteKey(&quot;Cash3900&quot;);*/
          Debug.Log(&quot;IAPScript&quot;);
          GameObject obj = GameObject.Find(&quot;Canvas&quot;);
          AdventurePurchaseManager = obj.transform.GetChild(1).GetChild(0).GetChild(1).GetComponent&lt;AdventurePurchaseManager&gt;();
          PilgrimagePurchassManager = obj.transform.GetChild(1).GetChild(1).GetChild(3).GetComponent&lt;PilgrimagePurchassManager&gt;();
  
      }
  
  
  
      public void OnPurchaseComplete(Product product)
      {
          if (product.definition.id == ChapterID_01)
          {
              Debug.Log(&quot;챕터1 결제 완료&quot;);
              PlayerPrefs.SetString(&quot;Cash1900_01&quot;, &quot;buy&quot;);
              AdventurePurchaseManager.SelectOpen_Chapter();
  
          }
  
          if (product.definition.id == ChapterID_02)
          {
              Debug.Log(&quot;챕터2 결제 완료&quot;);
              PlayerPrefs.SetString(&quot;Cash1900_02&quot;, &quot;buy&quot;);
              AdventurePurchaseManager.SelectOpen_Chapter();
          }
  
          if (product.definition.id == ChapterID_03)
          {
              Debug.Log(&quot;챕터3 결제 완료&quot;);
              PlayerPrefs.SetString(&quot;Cash1900_03&quot;, &quot;buy&quot;);
              AdventurePurchaseManager.SelectOpen_Chapter();
          }
  
          if (product.definition.id == ChapterID_04)
          {
              /*Debug.Log(&quot;챕터3 결제 완료&quot;);
              PlayerPrefs.SetString(&quot;Cash1900_04&quot;, &quot;buy&quot;);
              AdventurePurchaseManager.SelectOpen_Chapter();
              CodelessIAPStoreListener.Instance.StoreController.InitiatePurchase(ChapterID_04);*/
          }
  
          if (product.definition.id == ChapterID_05)
          {
              Debug.Log(&quot;챕터5 결제 완료&quot;);
              PlayerPrefs.SetString(&quot;Cash1900_05&quot;, &quot;buy&quot;);
              AdventurePurchaseManager.SelectOpen_Chapter();
          }
  
          if (product.definition.id == ChapterID_06)
          {
              Debug.Log(&quot;챕터6 결제 완료&quot;);
              PlayerPrefs.SetString(&quot;Cash1900_06&quot;, &quot;buy&quot;);
              AdventurePurchaseManager.SelectOpen_Chapter();
          }
  
          if (product.definition.id == AllChapterID)
          {
              PlayerPrefs.SetString(&quot;Cash7900&quot;, &quot;buy&quot;);
              Debug.Log(&quot;올 챕터 결제 완료&quot;);
              AdventurePurchaseManager.AllChapter();
          }
  
          if (product.definition.id == PilgrID)
          {
              PlayerPrefs.SetString(&quot;Cash3900&quot;, &quot;buy&quot;);
              Debug.Log(&quot;성지순례 모든 챕터 결제 완료&quot;);
              PilgrimagePurchassManager.Opne_All();
          }
  
      }
  
      public void OnPurchaseFailed(Product product, PurchaseFailureReason reason)
      {
          Debug.Log(&quot;결제 실패&quot;);
      }
  
  }
  </code></pre>
  <p>AdventurePurchaseManager:</p>
  <pre><code>using System.Collections;
  using System.Collections.Generic;
  using UnityEngine;
  using UnityEngine.Purchasing;
  
  public class AdventurePurchaseManager : MonoBehaviour
  {
      public AdventureChapter[] chapters;
      public GameObject Package;
      public IAPButton iAPButton;
  
      private void Awake()
      {
          chapters = GetComponentsInChildren&lt;AdventureChapter&gt;();
          Package = transform.parent.Find(&quot;Package&quot;).gameObject;
          iAPButton = Package.GetComponent&lt;IAPButton&gt;();
  
          if (transform.parent.parent.name != &quot;SelectVr&quot;)
          {
              iAPButton = Package.GetComponent&lt;IAPButton&gt;();
              iAPButton.onPurchaseComplete.AddListener(IAPScript.Instance.OnPurchaseComplete);
              iAPButton.onPurchaseFailed.AddListener(IAPScript.Instance.OnPurchaseFailed);
          }
      }
  
      private void Start()
      {
          if (PlayerPrefs.HasKey(&quot;Cash7900&quot;))
          {
              Open_AllChapter();
              Debug.Log(&quot;PlayerPrefs.HasKey(Cash7900)&quot;);
          }
          else
          {
              SelectOpen_Chapter();
          }
        
      }
  
      private void OnEnable()
      {
          StartCoroutine(&quot;delay_OnEnable&quot;);
      }
  
  
      public void AllChapter()
      {
          StartCoroutine(&quot;delay_OnEnable&quot;);
      }
  
      public void SelectOpen_Chapter()
      {
          StartCoroutine(&quot;delay_SelectOpenChapter&quot;);
      }
  
      IEnumerator delay_OnEnable()
      {
          yield return new WaitForSeconds(0.02f);
          if (PlayerPrefs.HasKey(&quot;Cash7900&quot;))
          {
              Open_AllChapter();
          }
          else
          {
              SelectOpen_Chapter();
          }
  
      }
  
      IEnumerator delay_SelectOpenChapter()
      {
          yield return new WaitForSeconds(0.02f);
  
          bool[] checkBuyChapter = new bool[6];
  
          chapters[3].SetFree();
          checkBuyChapter[3] = true;
  
          if (PlayerPrefs.HasKey(&quot;Cash1900_01&quot;))
          {
              chapters[0].SetPurchase();
              checkBuyChapter[0] = true;
          }
          else
          {
              chapters[0].SetLock();
              checkBuyChapter[0] = false;
          }
  
          if (PlayerPrefs.HasKey(&quot;Cash1900_02&quot;))
          {
              chapters[1].SetPurchase();
              checkBuyChapter[1] = true;
          }
          else
          {
              chapters[1].SetLock();
              checkBuyChapter[1] = false;
          }
  
  
          if (PlayerPrefs.HasKey(&quot;Cash1900_03&quot;))
          {
              chapters[2].SetPurchase();
              checkBuyChapter[2] = true;
          }
          else
          {
              chapters[2].SetLock();
              checkBuyChapter[2] = false;
          }
  
          /* if (PlayerPrefs.HasKey(&quot;Cash1900_04&quot;))
           {
               chapters[4].SetPurchase();
               checkBuyChapter[4] = true;
           }
           else
           {
               chapters[4].SetLock();
               checkBuyChapter[4] = false;
           }*/
  
        /*  if (PlayerPrefs.HasKey(&quot;Cash1900_04&quot;))
          {
              chapters[3].SetFree();
              checkBuyChapter[3] = true;
  
          }*/
  
  
  
          if (PlayerPrefs.HasKey(&quot;Cash1900_05&quot;))
          {
              chapters[4].SetPurchase();
              checkBuyChapter[4] = true;
          }
          else
          {
              chapters[4].SetLock();
              checkBuyChapter[4] = false;
          }
  
  
          if (PlayerPrefs.HasKey(&quot;Cash1900_06&quot;))
          {
              chapters[5].SetPurchase();
              checkBuyChapter[5] = true;
          }
          else
          {
              chapters[5].SetLock();
              checkBuyChapter[5] = false;
              Debug.Log(&quot;test&quot;);
          }
  
          bool check = true;
          for (int i = 0; i &lt; checkBuyChapter.Length; i++)
          {
              if (checkBuyChapter[i] == false)
              {
                  check = false;
              }
          }
  
          if (check)
          {
              Package.gameObject.SetActive(false);
          }
          else
          {
              Package.gameObject.SetActive(true);
          }
  
      }
  
      public void Open_AllChapter()
      {
          foreach (var chapter in chapters)
          {
              if (chapter.myIndex == 3)
              {
                  chapter.SetFree();
              }
              else
              {
                  chapter.SetPurchase();
              }
          }
          Package.gameObject.SetActive(false);
      }
  }
  </code></pre>
  <p>AdventureChapter:</p>
  <pre><code>using System.Collections;
  using System.Collections.Generic;
  using UnityEngine;
  using UnityEngine.UI;
  using UnityEngine.Purchasing;
  
  public class AdventureChapter : MonoBehaviour
  {
      public int myIndex;
  
      [SerializeField] private GameObject dim;
      [SerializeField] private GameObject paid;
      [SerializeField] private GameObject sell;
      [SerializeField] private GameObject free;
      [SerializeField] private GameObject locked;
      [SerializeField] private Button button;
  
      [SerializeField] private IAPButton IAPButton;
  
  
      private void Awake()
      {
          myIndex = transform.GetSiblingIndex();
  
          dim = transform.Find(&quot;Dim&quot;).gameObject;
          paid = transform.Find(&quot;Paid&quot;).gameObject;
          sell = transform.Find(&quot;Sell&quot;).gameObject;
          free = transform.Find(&quot;Free&quot;).gameObject;
          locked = transform.Find(&quot;Locked&quot;).gameObject;
          button = GetComponent&lt;Button&gt;();
  
          if (transform.parent.parent.parent.name != &quot;SelectVr&quot;)
          {
              IAPButton = locked.GetComponent&lt;IAPButton&gt;();
              IAPButton.onPurchaseComplete.AddListener(IAPScript.Instance.OnPurchaseComplete);
              IAPButton.onPurchaseFailed.AddListener(IAPScript.Instance.OnPurchaseFailed);
          }
  
      }
  
      private void OnEnable()
      {
  
      }
  
      public void SetFree()
      {
          dim.SetActive(false);
          paid.SetActive(false);
          sell.SetActive(false);
          free.SetActive(true);
          locked.SetActive(false);
          button.interactable = true;
      }
      public void SetLock()
      {
          dim.SetActive(true);
          paid.SetActive(false);
          sell.SetActive(true);
          free.SetActive(false);
          locked.SetActive(true);
          button.interactable = false;
      }
      public void SetPurchase()
      {
          dim.SetActive(false);
          paid.SetActive(true);
          sell.SetActive(false);
          free.SetActive(false);
          locked.SetActive(false);
          button.interactable = true;
      }
  }
  </code></pre>
  <p>PilgrimagePurchassManager:</p>
  <pre><code> using System.Collections;
   using System.Collections.Generic;
   using UnityEngine;
   using UnityEngine.UI;
   using UnityEngine.U2D;
   using UnityEngine.Purchasing;
  
   public class PilgrimagePurchassManager : MonoBehaviour
   {
      [SerializeField] private Image[] pgImages;
      [SerializeField] private Button[] pgButtons;
      [SerializeField] private GameObject Package;
      [SerializeField] private string[] pgWordIndex;
  
      public SpriteAtlas Pilgrimage;
  
      private IAPButton IAPButton;
  
      private void Awake()
      {
          pgImages = new Image[transform.childCount];
          pgButtons = new Button[transform.childCount];
  
          for (int i = 0; i &lt; transform.childCount; i++)
          {
              pgImages[i] = transform.GetChild(i).GetComponent&lt;Image&gt;();
              pgButtons[i] = transform.GetChild(i).GetComponent&lt;Button&gt;();
          }
  
          Package = transform.parent.GetChild(4).gameObject;
          if (transform.parent.parent.parent.name != &quot;VideoExit&quot;)
          {
              IAPButton = Package.GetComponent&lt;IAPButton&gt;();
              IAPButton.onPurchaseComplete.AddListener(IAPScript.Instance.OnPurchaseComplete);
              IAPButton.onPurchaseFailed.AddListener(IAPScript.Instance.OnPurchaseFailed);
          }
  
  
          pgWordIndex = new string[] {&quot;02&quot;,&quot;05&quot;,&quot;04&quot;,&quot;03&quot;,&quot;16&quot;, &quot;18&quot;, &quot;22&quot;, &quot;21&quot;, &quot;19&quot;, &quot;20&quot;, &quot;10&quot;, &quot;11&quot; ,&quot;09&quot;, &quot;07&quot; ,&quot;23&quot; ,&quot;08&quot;, &quot;06&quot;, &quot;12&quot;, &quot;13&quot;, &quot;14&quot;, &quot;15&quot;, &quot;17&quot; };
      }
  
      private void OnEnable()
      {
          
          if (PlayerPrefs.HasKey(&quot;Cash3900&quot;))
          {
              Opne_All();
          }
          else
          {
              for (int i = 0; i &lt; pgButtons.Length; i++)
              {
                  if (i &lt; 4)
                  {
                      pgButtons[i].enabled = true;
                      pgButtons[i].interactable = true;
                      pgImages[i].sprite = Pilgrimage.GetSprite($&quot;Pilgrimage_spot_{pgWordIndex[i]}_unlock&quot;);
                  }
                  else
                  {
                      pgButtons[i].enabled = false;
                      pgButtons[i].interactable = false;
  
                      pgButtons[i].enabled = true;
                      pgButtons[i].enabled = false;
                      pgImages[i].sprite = Pilgrimage.GetSprite($&quot;Pilgrimage_spot_{pgWordIndex[i]}_lock&quot;);
                  }
              }
              Package.gameObject.SetActive(true);
          }
      }
  
  
  
      public void Opne_All()
      {
          StartCoroutine(&quot;Delay_OPenAll&quot;);
      }
  
      IEnumerator Delay_OPenAll()
      {
          yield return new WaitForSeconds(0.02f);
          for (int i = 0; i &lt; pgButtons.Length; i++)
          {
              pgButtons[i].enabled = true;
              pgButtons[i].interactable = true;
              pgImages[i].sprite = Pilgrimage.GetSprite($&quot;Pilgrimage_spot_{pgWordIndex[i]}_unlock&quot;);
          }
          Package.gameObject.SetActive(false);
      }    
  
  }
  </code></pre>