Search Unity

How do I know if a payment was successful or not?

Discussion in 'Unity IAP' started by LumoKvin, Dec 20, 2019.

  1. LumoKvin

    LumoKvin

    Joined:
    Sep 28, 2019
    Posts:
    195
    Capture.PNG

    • Is GrantCredits called after the user's credit card is charged? Or, is there a different way to verify the purchase?
    • Once I verify a successful purchase, do I store that info locally on the device?
     
  2. SamOYUnity3D

    SamOYUnity3D

    Unity Technologies

    Joined:
    May 12, 2019
    Posts:
    626
    • Is GrantCredits called after the user's credit card is charged? Or, is there a different way to verify the purchase?
    Yes, GrantCredits will be called after a successful purchase. You can also handle purchases by implementing the IStoreListener interface.
    https://docs.unity3d.com/2019.1/Documentation/Manual/UnityIAPInitialization.html

    • Once I verify a successful purchase, do I store that info locally on the device?
    If the product type is Non-Consumable or Subscription, you can check and process the product after the next initialization.
    If the product type is Consumable, you need to save the purchase. You can choose to save your purchases to the cloud or locally. Please be aware that saving purchases locally risk data loss or tampering.
    https://docs.unity3d.com/2019.1/Documentation/Manual/UnityIAPProcessingPurchases.html
     
    Last edited: Dec 20, 2019
    LumoKvin likes this.
  3. LumoKvin

    LumoKvin

    Joined:
    Sep 28, 2019
    Posts:
    195
    Thanks for the info. That is very helpful.

    If a user purchases a Non-Consumable or Subscription, the GrantCredits method will be called every time the user starts the app? Is this dependent on an internet connection?

    So, the GrantCredits method would be a good place to call something like HidePaymentButton? Or, if I want to hide the payment button, is it better to use something like IStoreController.products.WithID(productId).hasReceip?
     
    Last edited: Dec 20, 2019
  4. SamOYUnity3D

    SamOYUnity3D

    Unity Technologies

    Joined:
    May 12, 2019
    Posts:
    626
    Because of the limited functionality of Codeless IAP, I suggest you use Code IAP instead of Codeless IAP.

    *If a user purchases a Non-Consumable or Subscription, the GrantCredits method will be called every time the user starts the app?
    No, the GrantCredits method only processes purchases that have not been completed at the next initialization.
    If you want to check Non-Consumable or Subscription purchases, you can check after IAP initialization.
    Code (CSharp):
    1.     public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
    2.     {
    3.         this.controller = controller;
    4.         this.extensions = extensions;
    5.         CheckPurchasedProducts();
    6.     }
    7.  
    8.     private void CheckPurchasedProducts()
    9.     {
    10.         foreach (Product product in controller.products.all)
    11.         {
    12.             if (product.hasReceipt == true)
    13.             {
    14.                 if (product.definition.type == ProductType.NonConsumable)
    15.                 {
    16.                     ProcessNonConsumableProduct(product);
    17.                 }
    18.                 else if (product.definition.type == ProductType.Subscription)
    19.                 {
    20.                     ProcessSubscriptionProduct(product);
    21.                 }
    22.  
    23.             }
    24.         }
    25.     }
    *Is this dependent on an internet connection?
    Yes

    *So, the GrantCredits method would be a good place to call something like HidePaymentButton? Or, if I want to hide the payment button, is it better to use something like IStoreController.products.WithID(productId).hasReceip?
    You can use the GrantCredits method hide button after purchase and use the IStoreController.products.WithID(productId).hasReceip hide button on the next launch.
     
    JeffDUnity3D likes this.
  5. shahin2019

    shahin2019

    Joined:
    Mar 17, 2019
    Posts:
    19
    how can I make a IAP Subscription code in unity 2019.1.9 for google play ,
    means when he buy 5000 score subscription so add 5000 score to UIManager but it expired so back scores ? I do not using subscription so far ,I want if subscriptions was for 2 months call it after first month and add 5000 score for second month too, and when it was expired so it be 0 score
    help me please

    Is this code correct?


    [code=CSharp] using System;

    using System.Collections.Generic;

    using UnityEngine;

    using UnityEngine.Purchasing;

    using CodeStage.AntiCheat.ObscuredTypes;

    public class ShopManager2 : MonoBehaviour,IStoreListener

    { public static ShopManager2 Instance{ set; get;}

    private static IStoreController m_StoreController;

    private static IExtensionProvider m_StoreExtensionProvider;

    public static string kProductIDConsumable = "consumable";

    public static string kProductIDNonConsumable = "nonconsumable";

    public static string kProductIDSubscription = "subscription";

    private static string kProductNameAppleSubscription="com.unity3d.subscription.new";

    private static string kProductNameGooglePlaySubscription ="com.company.s.subscription.zshahin";

    void Start()

    {

    if (m_StoreController == null)

    {

    InitializePurchasing();

    }

    }

    public void InitializePurchasing()

    {

    if (IsInitialized())

    {

    return;

    }

    var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());

    builder.AddProduct(kProductIDConsumable, ProductType.Consumable);

    builder.AddProduct(kProductIDNonConsumable, ProductType.NonConsumable);

    builder.AddProduct(kProductIDSubscription, ProductType.Subscription, new IDs(){

    { kProductNameAppleSubscription, AppleAppStore.Name },

    { kProductNameGooglePlaySubscription, GooglePlay.Name },

    });

    UnityPurchasing.Initialize(this, builder);

    }

    private bool IsInitialized()

    {

    return m_StoreController != null && m_StoreExtensionProvider != null;

    }

    public void BuyConsumable()

    {

    BuyProductID(kProductIDConsumable);

    }

    public void BuyNonConsumable()

    {

    BuyProductID(kProductIDNonConsumable);

    }

    public void BuySubscription()

    {

    BuyProductID(kProductIDSubscription);

    }

    void BuyProductID(string productId)

    {

    if (IsInitialized())

    {

    Product product = m_StoreController.products.WithID(productId);

    if (product != null && product.availableToPurchase)

    {

    Debug.Log(string.Format("Purchasing product asychronously: '{0}'", product.definition.id));

    m_StoreController.InitiatePurchase(product);

    }

    else

    {

    Debug.Log("BuyProductID: FAIL. Not purchasing product, either is not found or is not available for purchase");

    }

    }

    else

    {

    Debug.Log("BuyProductID FAIL. Not initialized.");

    }

    }

    public void RestorePurchases()

    {

    if (!IsInitialized())

    {

    Debug.Log("RestorePurchases FAIL. Not initialized.");

    return;

    }

    if (Application.platform == RuntimePlatform.IPhonePlayer ||

    Application.platform == RuntimePlatform.OSXPlayer)

    {

    Debug.Log("RestorePurchases started ...");

    var apple = m_StoreExtensionProvider.GetExtension<IAppleExtensions>();

    apple.RestoreTransactions((result) => {

    Debug.Log("RestorePurchases continuing: " + result + ". If no further messages, no purchases available to restore.");

    });

    }

    else

    {

    Debug.Log("RestorePurchases FAIL. Not supported on this platform. Current = " + Application.platform);

    }

    }

    public void OnInitialized(IStoreController controller, IExtensionProvider extensions)

    {

    Debug.Log("OnInitialized: PASS");

    m_StoreController = controller;

    m_StoreExtensionProvider = extensions;

    }

    public void OnInitializeFailed(InitializationFailureReason error)

    {

    Debug.Log("OnInitializeFailed InitializationFailureReason:" + error);

    }

    public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)

    { //This can be called anytime after initialization

    //And it should probably be limited to Google Play and not just Android

    #if UNITY_ANDROID

    foreach (Product p in m_StoreController.products.all) {

    GooglePurchaseData data = new GooglePurchaseData(p.receipt);

    if (p.hasReceipt) {

    Debug.Log(data.json.autoRenewing);

    Debug.Log(data.json.orderId);

    Debug.Log(data.json.packageName);

    Debug.Log(data.json.productId);

    Debug.Log(data.json.purchaseTime);

    Debug.Log(data.json.purchaseState);

    Debug.Log(data.json.purchaseToken);

    }

    }

    #endif

    if (String.Equals(args.purchasedProduct.definition.id, kProductIDConsumable, StringComparison.Ordinal))

    {

    Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));

    }

    else if (String.Equals(args.purchasedProduct.definition.id, kProductIDNonConsumable, StringComparison.Ordinal))

    {

    Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));

    }

    else if (String.Equals(args.purchasedProduct.definition.id, kProductIDSubscription, StringComparison.Ordinal))

    {

    Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));

    }

    else

    {

    Debug.Log(string.Format("ProcessPurchase: FAIL. Unrecognized product: '{0}'", args.purchasedProduct.definition.id));

    }

    return PurchaseProcessingResult.Complete;

    }

    public void OnPurchaseFailed(Product product, PurchaseFailureReason failureReason);

    {

    Debug.Log(string.Format("OnPurchaseFailed: FAIL. Product: '{0}', PurchaseFailureReason: {1}", product.definition.storeSpecificId, failureReason));

    }

    }[/code]
     
  6. SamOYUnity3D

    SamOYUnity3D

    Unity Technologies

    Joined:
    May 12, 2019
    Posts:
    626
    You can check if the user has purchased a subscription, if it is then add 5000 score, otherwise do not add.
    Code (CSharp):
    1.   /// <summary>
    2.     /// This will be called when Unity IAP has finished initialising.
    3.     /// </summary>
    4.     public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
    5.     {
    6.         m_Controller = controller;
    7.         m_GooglePlayStoreExtensions = extensions.GetExtension<IGooglePlayStoreExtensions>();
    8.         Dictionary<string, string> introductory_info_dict = m_AppleExtensions.GetIntroductoryPriceDictionary();
    9.  
    10.         foreach (var item in controller.products.all)
    11.         {
    12.             if (item.availableToPurchase)
    13.             {
    14.                 // this is the usage of SubscriptionManager class
    15.                 if (item.receipt != null)
    16.                 {
    17.                     if (item.definition.type == ProductType.Subscription)
    18.                     {
    19.                             string intro_json = (introductory_info_dict == null || !introductory_info_dict.ContainsKey(item.definition.storeSpecificId)) ? null : introductory_info_dict[item.definition.storeSpecificId];
    20.  
    21.                             try
    22.                             {
    23.                                 SubscriptionManager p = new SubscriptionManager(item, intro_json);
    24.                                 SubscriptionInfo info = p.getSubscriptionInfo();
    25.                                 {
    26.                                     if (info.getProductId() == "YourProductID")//If the user purchases a subscription, add 5000 score, otherwise do not add
    27.                                     {
    28.                                         Add5000Scrore();
    29.                                     }
    30.                                 }
    31.                             }
    32.                             catch (Exception ex)
    33.                             {
    34.                                 Debug.Log(ex);
    35.                             }
    36.                     }
    37.  
    38.                     else
    39.                     {
    40.                         Debug.Log("the product is not a subscription product");
    41.                     }
    42.                 }
    43.  
    44.                 else
    45.                 {
    46.                     Debug.Log("the product should have a valid receipt");
    47.                 }
    48.  
    49.             }
    50.         }
    51.     }
     
  7. shahin2019

    shahin2019

    Joined:
    Mar 17, 2019
    Posts:
    19
    ok I wrote a new script , is this correct?
    Code (CSharp):
    1. using System;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using System.Collections;
    5. using UnityEngine.Purchasing;
    6.  
    7.  
    8.     public class ShopManager2  : MonoBehaviour, IStoreListener
    9.     {        public static ShopManager2 Instance{ set; get;}
    10.    
    11.         private static IStoreController m_StoreController;    
    12.         private static IExtensionProvider m_StoreExtensionProvider;
    13.  
    14.     public static string em_1000s = "com.company.ss.1000s";
    15.     public static string em_2000s = "com.company.ss.2000s";
    16.         public static string PRODUCT_Removeadss = "com.company.ss.xxx";
    17.  
    18.         public static string ProductIDConsumable =    "consumable";
    19.         public static string ProductIDNonConsumable = "nonconsumable";
    20.         public static string ProductIDSubscription =  "subscription";
    21.  
    22.     private void Awake(){
    23.  
    24.         Instance = this;
    25.     }
    26.         void Start()
    27.         {
    28.             if (m_StoreController == null)
    29.             {
    30.                 InitializePurchasing();
    31.             }
    32.         }
    33.  
    34.         public void InitializePurchasing()
    35.         {
    36.             if (IsInitialized())
    37.             {
    38.                 return;
    39.             }
    40.         var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
    41.             builder.AddProduct(ProductIDConsumable, ProductType.Consumable);
    42.  
    43.             builder.AddProduct(em_1000s, ProductType.Consumable);
    44.         builder.AddProduct(em_2000s, ProductType.Consumable);
    45.             builder.AddProduct(PRODUCT_Removeadss, ProductType.Consumable);
    46.  
    47.             builder.AddProduct(ProductIDNonConsumable, ProductType.NonConsumable);
    48.             builder.AddProduct(ProductIDSubscription, ProductType.Subscription);
    49.  
    50.             UnityPurchasing.Initialize(this, builder);
    51.         }
    52.  
    53.  
    54.         private bool IsInitialized()
    55.         {
    56.             return m_StoreController != null && m_StoreExtensionProvider != null;
    57.         }
    58.  
    59.  
    60.         public void BuyConsumable()
    61.         {
    62.             BuyProductID(ProductIDConsumable);
    63.         }
    64.  
    65.  
    66.         public void BuyNonConsumable()
    67.         {
    68.             BuyProductID(ProductIDNonConsumable);
    69.         }
    70.  
    71.  
    72.         public void BuySubscription()
    73.         {
    74.             BuyProductID(ProductIDSubscription);
    75.         }
    76.  
    77.     public void em_1000ss()
    78.         {
    79.         BuyProductID(em_1000s);
    80.         }
    81.     public void em_2000ss()
    82.         {
    83.         BuyProductID(em_2000s);
    84.         }
    85.         public void removeadsss()
    86.         {
    87.             BuyProductID(PRODUCT_Removeadss);
    88.         }
    89.  
    90.         void BuyProductID(string productId)
    91.         {
    92.             if (IsInitialized())
    93.         {    //This can be called anytime after initialization
    94.             //And it should probably be limited to Google Play and not just Android
    95.             #if UNITY_ANDROID
    96.             foreach (Product p in m_StoreController.products.all) {
    97.                 GooglePurchaseData data = new GooglePurchaseData(p.receipt);
    98.  
    99.                 if (p.hasReceipt) {
    100.                     Debug.Log(data.json.autoRenewing);
    101.                     Debug.Log(data.json.orderId);
    102.                     Debug.Log(data.json.packageName);
    103.                     Debug.Log(data.json.productId);
    104.                     Debug.Log(data.json.purchaseTime);
    105.                     Debug.Log(data.json.purchaseState);
    106.                     Debug.Log(data.json.purchaseToken);
    107.                 }
    108.             }
    109.             #endif
    110.  
    111.                 Product product = m_StoreController.products.WithID(productId);
    112.  
    113.                 if (product != null && product.availableToPurchase)
    114.                 {
    115.                     Debug.Log(string.Format("Purchasing product asychronously: '{0}'", product.definition.id));
    116.                     m_StoreController.InitiatePurchase(product);
    117.                 }
    118.                 else
    119.                 {
    120.                     Debug.Log("BuyProductID: FAIL. Not purchasing product, either is not found or is not available for purchase");
    121.                 }
    122.             }
    123.             else
    124.             {
    125.                 Debug.Log("BuyProductID FAIL. Not initialized.");
    126.             }
    127.         }
    128.         public void RestorePurchases()
    129.         {
    130.             if (!IsInitialized())
    131.             {
    132.                 Debug.Log("RestorePurchases FAIL. Not initialized.");
    133.                 return;
    134.             }
    135.  
    136.                 if (Application.platform == RuntimePlatform.IPhonePlayer ||
    137.                 Application.platform == RuntimePlatform.OSXPlayer)
    138.             {
    139.                 Debug.Log("RestorePurchases started ...");
    140.  
    141.                 var apple = m_StoreExtensionProvider.GetExtension<IAppleExtensions>();
    142.                 apple.RestoreTransactions((result) => {
    143.                     Debug.Log("RestorePurchases continuing: " + result + ". If no further messages, no purchases available to restore.");
    144.                 });
    145.         }
    146.             else
    147.             {
    148.                 Debug.Log("RestorePurchases FAIL. Not supported on this platform. Current = " + Application.platform);
    149.             }
    150.         }
    151.  
    152.     public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
    153.     {
    154.         m_Controller = controller;
    155.         m_GooglePlayStoreExtensions = extensions.GetExtension<IGooglePlayStoreExtensions>();
    156.         Dictionary<string, string> introductory_info_dict = m_AppleExtensions.GetIntroductoryPriceDictionary();
    157.  
    158.         foreach (var item in controller.products.all)
    159.         {
    160.             if (item.availableToPurchase)
    161.             {
    162.                 if (item.receipt != null)
    163.                 {
    164.                     if (item.definition.type == ProductType.Subscription)
    165.                     {
    166.                         string intro_json = (introductory_info_dict == null || !introductory_info_dict.ContainsKey(item.definition.storeSpecificId)) ? null : introductory_info_dict[item.definition.storeSpecificId];
    167.  
    168.                         try
    169.                         {
    170.                             SubscriptionManager p = new SubscriptionManager(item, intro_json);
    171.                             SubscriptionInfo info = p.getSubscriptionInfo();
    172.                             {
    173.                                 if (info.getProductId() == "YourProductID")//If the user purchases a subscription, add 5000 score, otherwise do not add
    174.                                 {
    175.                                     Add5000Scrore();
    176.                                 }
    177.                             }
    178.                         }
    179.                         catch (Exception ex)
    180.                         {
    181.                             Debug.Log(ex);
    182.                         }
    183.                     }
    184.  
    185.                     else
    186.                     {
    187.                         Debug.Log("the product is not a subscription product");
    188.                     }
    189.                 }
    190.  
    191.                 else
    192.                 {
    193.                     Debug.Log("the product should have a valid receipt");
    194.                 }
    195.  
    196.             }
    197.         }
    198.     }
    199.  
    200.         public void OnInitializeFailed(InitializationFailureReason error)
    201.         {
    202.             Debug.Log("OnInitializeFailed InitializationFailureReason:" + error);
    203.         }
    204.  
    205.  
    206.         public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)
    207.     {
    208.             if (String.Equals(args.purchasedProduct.definition.id, ProductIDConsumable, StringComparison.Ordinal))
    209.             {
    210.                 Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
    211.             }
    212.             else if (String.Equals(args.purchasedProduct.definition.id, ProductIDNonConsumable, StringComparison.Ordinal))
    213.             {
    214.                 Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
    215.             }
    216.             else if (String.Equals(args.purchasedProduct.definition.id, ProductIDSubscription, StringComparison.Ordinal))
    217.             {
    218.                 Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
    219.             }
    220.  
    221.         if (String.Equals(args.purchasedProduct.definition.id,emtiaz_1000s, StringComparison.Ordinal))
    222.             {
    223.  
    224.  
    225.         }
    226.         else if (String.Equals(args.purchasedProduct.definition.id,emtiaz_2000s, StringComparison.Ordinal))
    227.             {
    228.  
    229.  
    230.             }
    231.             else if (String.Equals(args.purchasedProduct.definition.id,PRODUCT_Removeadss, StringComparison.Ordinal))
    232.             {
    233.  
    234.  
    235.             }
    236.         else if (String.Equals(args.purchasedProduct.definition.id,ProductIDSubscription, StringComparison.Ordinal))
    237.         {
    238.             addscore=5000 ;
    239.  
    240.         }
    241.             else
    242.             {
    243.                 Debug.Log(string.Format("ProcessPurchase: FAIL. Unrecognized product: '{0}'", args.purchasedProduct.definition.id));
    244.             }
    245.                 return PurchaseProcessingResult.Complete;
    246.         }
    247.  
    248.  
    249.         public void OnPurchaseFailed(Product product, PurchaseFailureReason failureReason)
    250.         {
    251.             Debug.Log(string.Format("OnPurchaseFailed: FAIL. Product: '{0}', PurchaseFailureReason: {1}", product.definition.storeSpecificId, failureReason));
    252.     }
    253.     public void Add5000Scrore(){
    254.         add=5000;
    255.     }
    256. }

    2- and is this script must be in my script ( at above ) or I can remove it?:
    Code (CSharp):
    1.  //This can be called anytime after initialization
    2.             //And it should probably be limited to Google Play and not just Android
    3.             #if UNITY_ANDROID
    4.             foreach (Product p in m_StoreController.products.all) {
    5.                 GooglePurchaseData data = new GooglePurchaseData(p.receipt);
    6.  
    7.                 if (p.hasReceipt) {
    8.                     Debug.Log(data.json.autoRenewing);
    9.                     Debug.Log(data.json.orderId);
    10.                     Debug.Log(data.json.packageName);
    11.                     Debug.Log(data.json.productId);
    12.                     Debug.Log(data.json.purchaseTime);
    13.                     Debug.Log(data.json.purchaseState);
    14.                     Debug.Log(data.json.purchaseToken);
    15.                 }
    16.             }
    17.             #endif
    18.  
    answer to 2 questions
     
    Last edited: Apr 10, 2020
  8. SamOYUnity3D

    SamOYUnity3D

    Unity Technologies

    Joined:
    May 12, 2019
    Posts:
    626
    You use the GooglePurchaseData in the wrong place. This is used to verify the receipt, you should use it in ProcessPurchase. https://forum.unity.com/threads/clo...o-renewing-subscriptions.476293/#post-3108170

    And, you can use another way to verify the receipt: https://docs.unity3d.com/Manual/Uni...807.449498332.1586084068-462153974.1569567086

    Code (CSharp):
    1.         void BuyProductID(string productId)
    2.         {
    3.             if (IsInitialized())
    4.         {    //This can be called anytime after initialization
    5.             //And it should probably be limited to Google Play and not just Android
    6.             #if UNITY_ANDROID
    7.             foreach (Product p in m_StoreController.products.all) {
    8.                 GooglePurchaseData data = new GooglePurchaseData(p.receipt);
    9.                 if (p.hasReceipt) {
    10.                     Debug.Log(data.json.autoRenewing);
    11.                     Debug.Log(data.json.orderId);
    12.                     Debug.Log(data.json.packageName);
    13.                     Debug.Log(data.json.productId);
    14.                     Debug.Log(data.json.purchaseTime);
    15.                     Debug.Log(data.json.purchaseState);
    16.                     Debug.Log(data.json.purchaseToken);
    17.                 }
    18.             }
    19.             #endif
    20.                 Product product = m_StoreController.products.WithID(productId);
    21.                 if (product != null && product.availableToPurchase)
    22.                 {
    23.                     Debug.Log(string.Format("Purchasing product asychronously: '{0}'", product.definition.id));
    24.                     m_StoreController.InitiatePurchase(product);
    25.                 }
    26.                 else
    27.                 {
    28.                     Debug.Log("BuyProductID: FAIL. Not purchasing product, either is not found or is not available for purchase");
    29.                 }
    30.             }
    31.             else
    32.             {
    33.                 Debug.Log("BuyProductID FAIL. Not initialized.");
    34.             }
    35.         }
     
  9. shahin2019

    shahin2019

    Joined:
    Mar 17, 2019
    Posts:
    19
    Excuseme SamOYUnity3D,please write full script for me (5000 score and remove ads for weekly subscription in googleplay and amazon(if it is enabled on amazon ) ),because I am confusing,if it is 2 code Separately so please both of them thanks
     
  10. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    We would not be able to write your code, you would want to hire someone. I already provided the code in the Sample project. Please get the Sample project working first. If you don't get the basics working, then any customization won't work either.
     
  11. shahin2019

    shahin2019

    Joined:
    Mar 17, 2019
    Posts:
    19
    thanks for answer, ok , please help
    SamOYUnity3D
    , JeffDUnity3D
    , I am confusing ,I changed it so



    Code (CSharp):
    1. using System;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using System.Collections;
    5. using UnityEngine.Purchasing;
    6.  
    7.  
    8.     public class ShopManager2  : MonoBehaviour, IStoreListener
    9.     {        public static ShopManager2 Instance{ set; get;}
    10.  
    11.         private static IStoreController m_StoreController;
    12.         private static IExtensionProvider m_StoreExtensionProvider;
    13.  
    14.     public static string em_1000s = "com.company.ss.1000s";
    15.     public static string em_2000s = "com.company.ss.2000s";
    16.         public static string PRODUCT_Removeadss = "com.company.ss.xxx";
    17.  
    18.         public static string ProductIDConsumable =    "consumable";
    19.         public static string ProductIDNonConsumable = "nonconsumable";
    20.         public static string ProductIDSubscription =  "subscription";
    21.  
    22.     private void Awake(){
    23.  
    24.         Instance = this;
    25.     }
    26.         void Start()
    27.         {
    28.             if (m_StoreController == null)
    29.             {
    30.                 InitializePurchasing();
    31.             }
    32.         }
    33.  
    34.         public void InitializePurchasing()
    35.         {
    36.             if (IsInitialized())
    37.             {
    38.                 return;
    39.             }
    40.         var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
    41.             builder.AddProduct(ProductIDConsumable, ProductType.Consumable);
    42.  
    43.             builder.AddProduct(em_1000s, ProductType.Consumable);
    44.         builder.AddProduct(em_2000s, ProductType.Consumable);
    45.             builder.AddProduct(PRODUCT_Removeadss, ProductType.Consumable);
    46.  
    47.             builder.AddProduct(ProductIDNonConsumable, ProductType.NonConsumable);
    48.             builder.AddProduct(ProductIDSubscription, ProductType.Subscription);
    49.  
    50.             UnityPurchasing.Initialize(this, builder);
    51.         }
    52.  
    53.  
    54.         private bool IsInitialized()
    55.         {
    56.             return m_StoreController != null && m_StoreExtensionProvider != null;
    57.         }
    58.  
    59.  
    60.         public void BuyConsumable()
    61.         {
    62.             BuyProductID(ProductIDConsumable);
    63.         }
    64.  
    65.  
    66.         public void BuyNonConsumable()
    67.         {
    68.             BuyProductID(ProductIDNonConsumable);
    69.         }
    70.  
    71.  
    72.         public void BuySubscription()
    73.         {
    74.             BuyProductID(ProductIDSubscription);
    75.         }
    76.  
    77.     public void em_1000ss()
    78.         {
    79.         BuyProductID(em_1000s);
    80.         }
    81.     public void em_2000ss()
    82.         {
    83.         BuyProductID(em_2000s);
    84.         }
    85.         public void removeadsss()
    86.         {
    87.             BuyProductID(PRODUCT_Removeadss);
    88.         }
    89.  
    90.         void BuyProductID(string productId)
    91.         {
    92.  
    93.                 if (IsInitialized())
    94.                 {    //This can be called anytime after initialization
    95.                     //And it should probably be limited to Google Play and not just Android
    96.                     #if UNITY_ANDROID
    97.                     foreach (Product p in m_StoreController.products.all) {
    98.                         GooglePurchaseData data = new GooglePurchaseData(p.receipt);
    99.                         if (p.hasReceipt) {
    100.                             Debug.Log(data.json.autoRenewing);
    101.                             Debug.Log(data.json.orderId);
    102.                             Debug.Log(data.json.packageName);
    103.                             Debug.Log(data.json.productId);
    104.                             Debug.Log(data.json.purchaseTime);
    105.                             Debug.Log(data.json.purchaseState);
    106.                             Debug.Log(data.json.purchaseToken);
    107.                         }
    108.                     }
    109.                     #endif
    110.                     Product product = m_StoreController.products.WithID(productId);
    111.                     if (product != null && product.availableToPurchase)
    112.                     {
    113.                         Debug.Log(string.Format("Purchasing product asychronously: '{0}'", product.definition.id));
    114.                         m_StoreController.InitiatePurchase(product);
    115.                     }
    116.                     else
    117.                     {
    118.                         Debug.Log("BuyProductID: FAIL. Not purchasing product, either is not found or is not available for purchase");
    119.                     }
    120.                 }
    121.                 else
    122.                 {
    123.                     Debug.Log("BuyProductID FAIL. Not initialized.");
    124.                 }
    125.             }
    126.         public void RestorePurchases()
    127.         {
    128.             if (!IsInitialized())
    129.             {
    130.                 Debug.Log("RestorePurchases FAIL. Not initialized.");
    131.                 return;
    132.             }
    133.  
    134.                 if (Application.platform == RuntimePlatform.IPhonePlayer ||
    135.                 Application.platform == RuntimePlatform.OSXPlayer)
    136.             {
    137.                 Debug.Log("RestorePurchases started ...");
    138.  
    139.                 var apple = m_StoreExtensionProvider.GetExtension<IAppleExtensions>();
    140.                 apple.RestoreTransactions((result) => {
    141.                     Debug.Log("RestorePurchases continuing: " + result + ". If no further messages, no purchases available to restore.");
    142.                 });
    143.         }
    144.             else
    145.             {
    146.                 Debug.Log("RestorePurchases FAIL. Not supported on this platform. Current = " + Application.platform);
    147.             }
    148.         }
    149.  
    150.     public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
    151.     {
    152.         m_Controller = controller;
    153.         m_GooglePlayStoreExtensions = extensions.GetExtension<IGooglePlayStoreExtensions>();
    154.         Dictionary<string, string> introductory_info_dict = m_AppleExtensions.GetIntroductoryPriceDictionary();
    155.  
    156.         foreach (var item in controller.products.all)
    157.         {
    158.             if (item.availableToPurchase)
    159.             {
    160.                 if (item.receipt != null)
    161.                 {
    162.                     if (item.definition.type == ProductType.Subscription)
    163.                     {
    164.                         string intro_json = (introductory_info_dict == null || !introductory_info_dict.ContainsKey(item.definition.storeSpecificId)) ? null : introductory_info_dict[item.definition.storeSpecificId];
    165.  
    166.                         try
    167.                         {
    168.                             SubscriptionManager p = new SubscriptionManager(item, intro_json);
    169.                             SubscriptionInfo info = p.getSubscriptionInfo();
    170.                             {
    171.                                 if (info.getProductId() == "YourProductID")//If the user purchases a subscription, add 5000 score, otherwise do not add
    172.                                 {
    173.                                     Add5000Scrore();
    174.                                 }
    175.                             }
    176.                         }
    177.                         catch (Exception ex)
    178.                         {
    179.                             Debug.Log(ex);
    180.                         }
    181.                     }
    182.  
    183.                     else
    184.                     {
    185.                         Debug.Log("the product is not a subscription product");
    186.                     }
    187.                 }
    188.  
    189.                 else
    190.                 {
    191.                     Debug.Log("the product should have a valid receipt");
    192.                 }
    193.  
    194.             }
    195.         }
    196.     }
    197.  
    198.         public void OnInitializeFailed(InitializationFailureReason error)
    199.         {
    200.             Debug.Log("OnInitializeFailed InitializationFailureReason:" + error);
    201.         }
    202.  
    203.  
    204.         public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)
    205.     {
    206.             if (String.Equals(args.purchasedProduct.definition.id, ProductIDConsumable, StringComparison.Ordinal))
    207.             {
    208.                 Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
    209.             }
    210.             else if (String.Equals(args.purchasedProduct.definition.id, ProductIDNonConsumable, StringComparison.Ordinal))
    211.             {
    212.                 Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
    213.             }
    214.             else if (String.Equals(args.purchasedProduct.definition.id, ProductIDSubscription, StringComparison.Ordinal))
    215.             {
    216.                 Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
    217.             }
    218.  
    219.         if (String.Equals(args.purchasedProduct.definition.id,em_1000s, StringComparison.Ordinal))
    220.             {
    221.  
    222.  
    223.         }
    224.         else if (String.Equals(args.purchasedProduct.definition.id,em_2000s, StringComparison.Ordinal))
    225.             {
    226.  
    227.  
    228.             }
    229.             else if (String.Equals(args.purchasedProduct.definition.id,PRODUCT_Removeadss, StringComparison.Ordinal))
    230.             {
    231.            
    232.  
    233.             }
    234.         else if (String.Equals(args.purchasedProduct.definition.id,ProductIDSubscription, StringComparison.Ordinal))
    235.         {
    236.             addscore=5000 ;
    237.  
    238.         }
    239.             else
    240.             {
    241.                 Debug.Log(string.Format("ProcessPurchase: FAIL. Unrecognized product: '{0}'", args.purchasedProduct.definition.id));
    242.             }
    243.                 return PurchaseProcessingResult.Complete;
    244.         }
    245.  
    246.  
    247.         public void OnPurchaseFailed(Product product, PurchaseFailureReason failureReason)
    248.         {
    249.             Debug.Log(string.Format("OnPurchaseFailed: FAIL. Product: '{0}', PurchaseFailureReason: {1}", product.definition.storeSpecificId, failureReason));
    250.     }
    251.     public void Add5000Scrore(){
    252.         add=5000;
    253.     }
    254. }
    I wrote it so is it correct, thanks

    thanks
    2- I thought this was a private conversation
    Can I make this conversation private?
    thanks
     
    Last edited: Apr 10, 2020
  12. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    @shahin2019 I would not expect this code to compile. You have not defined addscore or add, for example. And you are not incrementing the value by 5000, you are directly assigning a value (to two separate variables), contrary to the instructions I sent you via DM. Is there a reason you are not following my suggestions? And again, you are awarding points in a subscription model? As mentioned before, this is an incorrect use of a subscription product. What if I use the 5000 points on the first day, do I wait until next week for my subscription to renew? Instead, you want to use a Consumable. If you want to turn off ads with a subscription, you would set a boolean, like showAds = false; Please get the Sample IAP project working first with a single Consumable product, THEN add your customizations. This is common programming practice, get the basics working first!
     
    Last edited: Apr 10, 2020
  13. shahin2019

    shahin2019

    Joined:
    Mar 17, 2019
    Posts:
    19
    OK , I use it for remove ads (bool)
    thanks for answer, ok , please help
    SamOYUnity3D
    , JeffDUnity3D
    , I am confusing ,I changed it again so



    Code (CSharp):
    1. using System;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using System.Collections;
    5. using UnityEngine.Purchasing;
    6.  
    7.  
    8.     public class ShopManager2  : MonoBehaviour, IStoreListener
    9.     {        public static ShopManager2 Instance{ set; get;}
    10.  
    11.         private static IStoreController m_StoreController;
    12.         private static IExtensionProvider m_StoreExtensionProvider;
    13.  
    14.     public static string em_1000s = "com.company.ss.1000s";
    15.     public static string em_2000s = "com.company.ss.2000s";
    16.         public static string PRODUCT_Removeadss = "com.company.ss.xxx";
    17.  
    18.         public static string ProductIDConsumable =    "consumable";
    19.         public static string ProductIDNonConsumable = "nonconsumable";
    20.         public static string ProductIDSubscription =  "subscription";
    21.  
    22.     private void Awake(){
    23.  
    24.         Instance = this;
    25.     }
    26.         void Start()
    27.         {
    28.             if (m_StoreController == null)
    29.             {
    30.                 InitializePurchasing();
    31.             }
    32.         }
    33.  
    34.         public void InitializePurchasing()
    35.         {
    36.             if (IsInitialized())
    37.             {
    38.                 return;
    39.             }
    40.         var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
    41.             builder.AddProduct(ProductIDConsumable, ProductType.Consumable);
    42.  
    43.             builder.AddProduct(em_1000s, ProductType.Consumable);
    44.         builder.AddProduct(em_2000s, ProductType.Consumable);
    45.             builder.AddProduct(PRODUCT_Removeadss, ProductType.Subscription);
    46.  
    47.             builder.AddProduct(ProductIDNonConsumable, ProductType.NonConsumable);
    48.             builder.AddProduct(ProductIDSubscription, ProductType.Subscription);
    49.  
    50.             UnityPurchasing.Initialize(this, builder);
    51.         }
    52.  
    53.  
    54.         private bool IsInitialized()
    55.         {
    56.             return m_StoreController != null && m_StoreExtensionProvider != null;
    57.         }
    58.  
    59.  
    60.         public void BuyConsumable()
    61.         {
    62.             BuyProductID(ProductIDConsumable);
    63.         }
    64.  
    65.  
    66.         public void BuyNonConsumable()
    67.         {
    68.             BuyProductID(ProductIDNonConsumable);
    69.         }
    70.  
    71.  
    72.         public void BuySubscription()
    73.         {
    74.             BuyProductID(ProductIDSubscription);
    75.         }
    76.  
    77.     public void em_1000ss()
    78.         {
    79.         BuyProductID(em_1000s);
    80.         }
    81.     public void em_2000ss()
    82.         {
    83.         BuyProductID(em_2000s);
    84.         }
    85.         public void removeadsss()
    86.         {
    87.             BuyProductID(PRODUCT_Removeadss);
    88.         }
    89.  
    90.         void BuyProductID(string productId)
    91.         {
    92.  
    93.                 if (IsInitialized())
    94.                 {    //This can be called anytime after initialization
    95.                     //And it should probably be limited to Google Play and not just Android
    96.                     #if UNITY_ANDROID
    97.                     foreach (Product p in m_StoreController.products.all) {
    98.                         GooglePurchaseData data = new GooglePurchaseData(p.receipt);
    99.                         if (p.hasReceipt) {
    100.                             Debug.Log(data.json.autoRenewing);
    101.                             Debug.Log(data.json.orderId);
    102.                             Debug.Log(data.json.packageName);
    103.                             Debug.Log(data.json.productId);
    104.                             Debug.Log(data.json.purchaseTime);
    105.                             Debug.Log(data.json.purchaseState);
    106.                             Debug.Log(data.json.purchaseToken);
    107.                         }
    108.                     }
    109.                     #endif
    110.                     Product product = m_StoreController.products.WithID(productId);
    111.                     if (product != null && product.availableToPurchase)
    112.                     {
    113.                         Debug.Log(string.Format("Purchasing product asychronously: '{0}'", product.definition.id));
    114.                         m_StoreController.InitiatePurchase(product);
    115.                     }
    116.                     else
    117.                     {
    118.                        Debug.Log("BuyProductID: FAIL. Not purchasing product, either is not found or is not available for purchase");
    119.                     }
    120.                 }
    121.                 else
    122.                 {
    123.                     Debug.Log("BuyProductID FAIL. Not initialized.");
    124.                 }
    125.             }
    126.         public void RestorePurchases()
    127.         {
    128.             if (!IsInitialized())
    129.             {
    130.                 Debug.Log("RestorePurchases FAIL. Not initialized.");
    131.                 return;
    132.             }
    133.  
    134.                 if (Application.platform == RuntimePlatform.IPhonePlayer ||
    135.                 Application.platform == RuntimePlatform.OSXPlayer)
    136.             {
    137.                 Debug.Log("RestorePurchases started ...");
    138.  
    139.                 var apple = m_StoreExtensionProvider.GetExtension<IAppleExtensions>();
    140.                 apple.RestoreTransactions((result) => {
    141.                    Debug.Log("RestorePurchases continuing: " + result + ". If no further messages, no purchases available to restore.");
    142.                 });
    143.         }
    144.             else
    145.             {
    146.                 Debug.Log("RestorePurchases FAIL. Not supported on this platform. Current = " + Application.platform);
    147.             }
    148.         }
    149.  
    150.     public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
    151.     {
    152.         m_Controller = controller;
    153.         m_GooglePlayStoreExtensions = extensions.GetExtension<IGooglePlayStoreExtensions>();
    154.         Dictionary<string, string> introductory_info_dict = m_AppleExtensions.GetIntroductoryPriceDictionary();
    155.  
    156.         foreach (var item in controller.products.all)
    157.         {
    158.             if (item.availableToPurchase)
    159.             {
    160.                 if (item.receipt != null)
    161.                 {
    162.                     if (item.definition.type == ProductType.Subscription)
    163.                     {
    164.                        string intro_json = (introductory_info_dict == null || !introductory_info_dict.ContainsKey(item.definition.storeSpecificId)) ? null : introductory_info_dict[item.definition.storeSpecificId];
    165.  
    166.                         try
    167.                         {
    168.                             SubscriptionManager p = new SubscriptionManager(item, intro_json);
    169.                             SubscriptionInfo info = p.getSubscriptionInfo();
    170.                             {
    171.                                if (info.getProductId() == "YourProductID")//If the user purchases a subscription, add showAds  , otherwise do not add
    172.                                 {
    173. Ads ();
    174.                                 }
    175.                             }
    176.                         }
    177.                         catch (Exception ex)
    178.                         {
    179.                             Debug.Log(ex);
    180.                         }
    181.                     }
    182.  
    183.                     else
    184.                     {
    185.                         Debug.Log("the product is not a subscription product");
    186.                     }
    187.                 }
    188.  
    189.                 else
    190.                 {
    191.                     Debug.Log("the product should have a valid receipt");
    192.                 }
    193.  
    194.             }
    195.         }
    196.     }
    197.  
    198.         public void OnInitializeFailed(InitializationFailureReason error)
    199.         {
    200.             Debug.Log("OnInitializeFailed InitializationFailureReason:" + error);
    201.         }
    202.  
    203.  
    204.         public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)
    205.     {
    206.             if (String.Equals(args.purchasedProduct.definition.id, ProductIDConsumable, StringComparison.Ordinal))
    207.             {
    208.                 Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
    209.             }
    210.             else if (String.Equals(args.purchasedProduct.definition.id, ProductIDNonConsumable, StringComparison.Ordinal))
    211.             {
    212.                 Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
    213.             }
    214.             else if (String.Equals(args.purchasedProduct.definition.id, ProductIDSubscription, StringComparison.Ordinal))
    215.             {
    216.                 Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
    217.             }
    218.  
    219.         if (String.Equals(args.purchasedProduct.definition.id,em_1000s, StringComparison.Ordinal))
    220.             {
    221.  
    222.  
    223.         }
    224.         else if (String.Equals(args.purchasedProduct.definition.id,em_2000s, StringComparison.Ordinal))
    225.             {
    226.  
    227.  
    228.             }
    229.             else if (String.Equals(args.purchasedProduct.definition.id,PRODUCT_Removeadss, StringComparison.Ordinal))
    230.             {
    231.        
    232.  
    233.             }
    234.         else if (String.Equals(args.purchasedProduct.definition.id,ProductIDSubscription, StringComparison.Ordinal))
    235.         {
    236. if(ui.showads==false){ui.showads=true;//ui is a other script}
    237.         }
    238.             else
    239.             {
    240.                Debug.Log(string.Format("ProcessPurchase: FAIL. Unrecognized product: '{0}'", args.purchasedProduct.definition.id));
    241.             }
    242.                 return PurchaseProcessingResult.Complete;
    243.         }
    244.  
    245.  
    246.         public void OnPurchaseFailed(Product product, PurchaseFailureReason failureReason)
    247.         {
    248.            Debug.Log(string.Format("OnPurchaseFailed: FAIL. Product: '{0}', PurchaseFailureReason: {1}", product.definition.storeSpecificId, failureReason));
    249.     }
    250.     public void ads(){
    251. ui.showAds = true;//ui is a other script
    252.     }
    253. }
    I wrote it so is it correct, thanks
    1- should I use "subscription" here:
    "
    else if (String.Equals(args.purchasedProduct.definition.id,ProductIDSubscription, StringComparison.Ordinal))
    {
    if(showads==false){showads=true;}
    }
    "

    or here: "
    if (info.getProductId() == "YourProductID")//If the user purchases a subscription, add showAds , otherwise do not add
    {
    Ads ();
    "
    Where is the right place for this instruction?
    thanks
    2- I thought this was a private conversation
    Can I make this conversation private?
    thanks
     
  14. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    @shahin2019 Please DO NOT continue to send private emails when you been directly asked not to. If you continue to do so, you will get blocked here on the forum. If you are not able or willing to follow out suggestions, we would not be able to assist. In your logic you just showed, you set showAds = true just after they purchased a subscription to not show ads. This is incorrect logic. You also have a series of If/Else statements with no code associated with the logic. In summary, get the Sample IAP project working FIRST, without ANY changes (except the product names), THEN add your customization. You want to award your products in ProcessPurchase, this is the event that is triggered when a user makes a purchase, please confirm in your testing with the Sample IAP project, coded without any changes. Publish on Google Play first, it's easiest. And also you'll want to learn how to capture device logs, they will be invaluable for troubleshooting later on, once you get it working. These links may help https://forum.unity.com/threads/how-to-capturing-device-logs-on-android.528680/ and https://docs.unity3d.com/Manual/UnityIAPGoogleConfiguration.html
     
    Last edited: Apr 10, 2020