Search Unity

Use of same product ID in unity IAP for play store and app store

Discussion in 'Editor & General Support' started by SAditya, Jun 18, 2019.

  1. SAditya

    SAditya

    Joined:
    May 21, 2019
    Posts:
    19
    So I have a game published in the google play store (For Android) that has 6 IAP in it. Now I want to publish the same game to App store (FOR iOS). So ,can I use the same product ID that i used in the google play store.?
    For Ex-
    If I have a product with product ID in google console as --> add100000 (in managed product,consumable)
    and I create a product ID in apple developer console as --> add100000 , will it work possibly ? or I need to change something else in the script . Please Help.
    Thanks in Advance.



    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. using UnityEngine.Purchasing;
    6. using UnityEngine.UI;
    7.  
    8.  
    9.  
    10.     public class StoreManager : MonoBehaviour ,IStoreListener
    11.     {
    12.  
    13.     public UIMenuCoins ui;
    14.     private static IStoreController m_StoreController;          // The Unity Purchasing system.
    15.     private static IExtensionProvider m_StoreExtensionProvider; // The store-specific Purchasing subsystems.
    16.  
    17.     // Product identifiers for all products capable of being purchased:
    18.     // "convenience" general identifiers for use with Purchasing, and their store-specific identifier
    19.     // counterparts for use with and outside of Unity Purchasing. Define store-specific identifiers
    20.     // also on each platform's publisher dashboard (iTunes Connect, Google Play Developer Console, etc.)
    21.  
    22.     // General product identifiers for the consumable, non-consumable, and subscription products.
    23.     // Use these handles in the code to reference which product to purchase. Also use these values
    24.     // when defining the Product Identifiers on the store. Except, for illustration purposes, the
    25.     // kProductIDSubscription - it has custom Apple and Google identifiers. We declare their store-
    26.     // specific mapping to Unity Purchasing's AddProduct, below.
    27.     public static string kProductIDConsumable = "consumable";
    28.     public static string kProductIDNonConsumable = "nonconsumable";
    29.     public static string kProductIDSubscription = "subscription";
    30.  
    31.  
    32.  
    33.  
    34.     public static string add100000 = "add100000";
    35.  
    36.  
    37.  
    38.  
    39.  
    40.  
    41.  
    42.  
    43.  
    44.  
    45.     // Apple App Store-specific product identifier for the subscription product.
    46.     private static string kProductNameAppleSubscription = "com.unity3d.subscription.new";
    47.  
    48.     // Google Play Store-specific product identifier subscription product.
    49.     private static string kProductNameGooglePlaySubscription = "com.unity3d.subscription.original";
    50.  
    51.     void Start()
    52.     {
    53.         // If we haven't set up the Unity Purchasing reference
    54.         if (m_StoreController == null)
    55.         {
    56.             // Begin to configure our connection to Purchasing
    57.             InitializePurchasing();
    58.         }
    59.     }
    60.  
    61.     public void InitializePurchasing()
    62.     {
    63.         // If we have already connected to Purchasing ...
    64.         if (IsInitialized())
    65.         {
    66.             // ... we are done here.
    67.             return;
    68.         }
    69.  
    70.         // Create a builder, first passing in a suite of Unity provided stores.
    71.         var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
    72.  
    73.         // Add a product to sell / restore by way of its identifier, associating the general identifier
    74.         // with its store-specific identifiers.
    75.  
    76.  
    77.  
    78.         builder.AddProduct(add100000, ProductType.Consumable);
    79.  
    80.  
    81.         // Continue adding the non-consumable product.
    82.         // builder.AddProduct(kProductIDNonConsumable, ProductType.NonConsumable);
    83.         // And finish adding the subscription product. Notice this uses store-specific IDs, illustrating
    84.         // if the Product ID was configured differently between Apple and Google stores. Also note that
    85.         // one uses the general kProductIDSubscription handle inside the game - the store-specific IDs
    86.         // must only be referenced here.
    87.         /* builder.AddProduct(kProductIDSubscription, ProductType.Subscription, new IDs(){
    88.                  { kProductNameAppleSubscription, AppleAppStore.Name },
    89.                  { kProductNameGooglePlaySubscription, GooglePlay.Name },
    90.              });*/
    91.  
    92.         // Kick off the remainder of the set-up with an asynchrounous call, passing the configuration
    93.         // and this class' instance. Expect a response either in OnInitialized or OnInitializeFailed.
    94.         UnityPurchasing.Initialize(this, builder);
    95.     }
    96.  
    97.  
    98.     private bool IsInitialized()
    99.     {
    100.         // Only say we are initialized if both the Purchasing references are set.
    101.         return m_StoreController != null && m_StoreExtensionProvider != null;
    102.     }
    103.  
    104.  
    105.     public void BuyConsumable()
    106.     {
    107.         // Buy the consumable product using its general identifier. Expect a response either
    108.         // through ProcessPurchase or OnPurchaseFailed asynchronously.
    109.         BuyProductID(kProductIDConsumable);
    110.     }
    111.  
    112.  
    113.     public void Buy100000()
    114.     {
    115.         // Buy the consumable product using its general identifier. Expect a response either
    116.         // through ProcessPurchase or OnPurchaseFailed asynchronously.
    117.         BuyProductID(add100000);
    118.     }
    119.  
    120.  
    121.  
    122.  
    123.  
    124.  
    125.  
    126.  
    127.     public void BuyNonConsumable()
    128.     {
    129.         // Buy the non-consumable product using its general identifier. Expect a response either
    130.         // through ProcessPurchase or OnPurchaseFailed asynchronously.
    131.         BuyProductID(kProductIDNonConsumable);
    132.     }
    133.  
    134.  
    135.     public void BuySubscription()
    136.     {
    137.         // Buy the subscription product using its the general identifier. Expect a response either
    138.         // through ProcessPurchase or OnPurchaseFailed asynchronously.
    139.         // Notice how we use the general product identifier in spite of this ID being mapped to
    140.         // custom store-specific identifiers above.
    141.         BuyProductID(kProductIDSubscription);
    142.     }
    143.  
    144.  
    145.     void BuyProductID(string productId)
    146.     {
    147.         // If Purchasing has been initialized ...
    148.         if (IsInitialized())
    149.         {
    150.             // ... look up the Product reference with the general product identifier and the Purchasing
    151.             // system's products collection.
    152.             Product product = m_StoreController.products.WithID(productId);
    153.  
    154.             // If the look up found a product for this device's store and that product is ready to be sold ...
    155.             if (product != null && product.availableToPurchase)
    156.             {
    157.                 Debug.Log(string.Format("Purchasing product asychronously: '{0}'", product.definition.id));
    158.                 // ... buy the product. Expect a response either through ProcessPurchase or OnPurchaseFailed
    159.                 // asynchronously.
    160.                 m_StoreController.InitiatePurchase(product);
    161.             }
    162.             // Otherwise ...
    163.             else
    164.             {
    165.                 // ... report the product look-up failure situation
    166.                 Debug.Log("BuyProductID: FAIL. Not purchasing product, either is not found or is not available for purchase");
    167.             }
    168.         }
    169.         // Otherwise ...
    170.         else
    171.         {
    172.             // ... report the fact Purchasing has not succeeded initializing yet. Consider waiting longer or
    173.             // retrying initiailization.
    174.             Debug.Log("BuyProductID FAIL. Not initialized.");
    175.         }
    176.     }
    177.  
    178.  
    179.     // Restore purchases previously made by this customer. Some platforms automatically restore purchases, like Google.
    180.     // Apple currently requires explicit purchase restoration for IAP, conditionally displaying a password prompt.
    181.     public void RestorePurchases()
    182.     {
    183.         // If Purchasing has not yet been set up ...
    184.         if (!IsInitialized())
    185.         {
    186.             // ... report the situation and stop restoring. Consider either waiting longer, or retrying initialization.
    187.             Debug.Log("RestorePurchases FAIL. Not initialized.");
    188.             return;
    189.         }
    190.  
    191.         // If we are running on an Apple device ...
    192.         if (Application.platform == RuntimePlatform.IPhonePlayer ||
    193.             Application.platform == RuntimePlatform.OSXPlayer)
    194.         {
    195.             // ... begin restoring purchases
    196.             Debug.Log("RestorePurchases started ...");
    197.  
    198.             // Fetch the Apple store-specific subsystem.
    199.             var apple = m_StoreExtensionProvider.GetExtension<IAppleExtensions>();
    200.             // Begin the asynchronous process of restoring purchases. Expect a confirmation response in
    201.             // the Action<bool> below, and ProcessPurchase if there are previously purchased products to restore.
    202.             apple.RestoreTransactions((result) => {
    203.                 // The first phase of restoration. If no more responses are received on ProcessPurchase then
    204.                 // no purchases are available to be restored.
    205.                 Debug.Log("RestorePurchases continuing: " + result + ". If no further messages, no purchases available to restore.");
    206.             });
    207.         }
    208.         // Otherwise ...
    209.         else
    210.         {
    211.             // We are not running on an Apple device. No work is necessary to restore purchases.
    212.             Debug.Log("RestorePurchases FAIL. Not supported on this platform. Current = " + Application.platform);
    213.         }
    214.     }
    215.  
    216.  
    217.     //
    218.     // --- IStoreListener
    219.     //
    220.  
    221.     public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
    222.     {
    223.         // Purchasing has succeeded initializing. Collect our Purchasing references.
    224.         Debug.Log("OnInitialized: PASS");
    225.  
    226.         // Overall Purchasing system, configured with products for this application.
    227.         m_StoreController = controller;
    228.         // Store specific subsystem, for accessing device-specific store features.
    229.         m_StoreExtensionProvider = extensions;
    230.     }
    231.  
    232.  
    233.     public void OnInitializeFailed(InitializationFailureReason error)
    234.     {
    235.         // Purchasing set-up has not succeeded. Check error for reason. Consider sharing this reason with the user.
    236.         Debug.Log("OnInitializeFailed InitializationFailureReason:" + error);
    237.     }
    238.  
    239.  
    240.  
    241.  
    242.  
    243.     public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)
    244.     {
    245.         // A consumable product has been purchased by this user.
    246.  
    247.          if (String.Equals(args.purchasedProduct.definition.id, add100000, StringComparison.Ordinal))
    248.         {
    249.             int current_coins = PlayerPrefs.GetInt("money", 10000);
    250.             current_coins += 100000;
    251.             PlayerPrefs.SetInt("money", current_coins);
    252.             ui.UpdateUI();
    253.  
    254.             Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
    255.  
    256.         }
    257.  
    258.  
    259.         // Or ... a non-consumable product has been purchased by this user.
    260.         else if (String.Equals(args.purchasedProduct.definition.id, kProductIDNonConsumable, StringComparison.Ordinal))
    261.         {
    262.             Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
    263.             // TODO: The non-consumable item has been successfully purchased, grant this item to the player.
    264.         }
    265.         // Or ... a subscription product has been purchased by this user.
    266.         else if (String.Equals(args.purchasedProduct.definition.id, kProductIDSubscription, StringComparison.Ordinal))
    267.         {
    268.             Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
    269.             // TODO: The subscription item has been successfully purchased, grant this to the player.
    270.         }
    271.         // Or ... an unknown product has been purchased by this user. Fill in additional products here....
    272.         else
    273.         {
    274.             Debug.Log(string.Format("ProcessPurchase: FAIL. Unrecognized product: '{0}'", args.purchasedProduct.definition.id));
    275.         }
    276.  
    277.         // Return a flag indicating whether this product has completely been received, or if the application needs
    278.         // to be reminded of this purchase at next app launch. Use PurchaseProcessingResult.Pending when still
    279.         // saving purchased products to the cloud, and when that save is delayed.
    280.         return PurchaseProcessingResult.Complete;
    281.     }
    282.  
    283.  
    284.  
    285.  
    286.  
    287.  
    288.  
    289.  
    290.     public void OnPurchaseFailed(Product product, PurchaseFailureReason failureReason)
    291.     {
    292.         // A product purchase attempt did not succeed. Check failureReason for more detail. Consider sharing
    293.         // this reason with the user to guide their troubleshooting actions.
    294.         Debug.Log(string.Format("OnPurchaseFailed: FAIL. Product: '{0}', PurchaseFailureReason: {1}", product.definition.storeSpecificId, failureReason));
    295.     }
    296. }
    297.  
    298.  
    299.  
    300.  
    301.  
    302.  
    303.  
    304.  
    305.    
    306.  
    307.  
     
    AUEzzat likes this.
  2. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Yes, you can re-use the same productID across stores.
     
  3. nicky1998

    nicky1998

    Joined:
    Feb 11, 2018
    Posts:
    1
    Hello ,
    Can you please explain where can I get 'kProductNameAppleSubscription' for IOS and PlaySore. Is it same as the product ID ? or Do we need to get it some where ?
    Thanks.
     
    PortalFeather likes this.
  4. harsh792

    harsh792

    Joined:
    Feb 28, 2020
    Posts:
    2
    Do I need to define store specific id for all subscription products separately ?
     
  5. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    No, you are not required to use store specific ids at all. I never do, but some studios do. They have separate productIDs on Google and Apple, makes sense. But I just keep mine all the same, like "gold50" or "subMonthly" on both platforms.