In-App Purchasing not initialized
Hello everybody.
I Need your help with the internal Unity InApp Purchase. I used the code that unity provides in their site: https://unity3d.com/learn/tutorials/topics/analytics/integrating-unity-iap-your-game
Which works as expected in the editor. However, when I build the app and test it on the Android the store is never initialized so I can't buy the product. So in the Android it goes to BuyProductID and then it doesn't buy the element and debugs "BuyProductID FAILED. Not initialized.". Does any one have any idea about how to fix this problem? Here is the complete code I use in my app:
Thank you in advance for your help!
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Purchasing;
public class Purchaser: MonoBehaviour, IStoreListener
{
private static IStoreController m_StoreController; // The Unity Purchasing system.
private static IExtensionProvider m_StoreExtensionProvider; // The store-specific Purchasing subsystems.
public static string kProductIDNonConsumableGainsMultiplier = "nonconsumable";
//Google playID
private static string kPermanentGainsMultiplierGoogle = "multiplicateur2x";
//Apple playID
private static string kPermanentGainsMultiplierApple = "_____";
public static string kProductIDConsumableSmallMoney = "consumable1";
//Google playID
private static string kSmallMoneyGoogle = "smallmoney";
//Apple playID
private static string kSmallMoneyApple = "_____";
public static string kProductIDConsumableMediumMoney = "consumable4";
//Google playID
private static string kMediumMoneyGoogle = "mediummoney";
//Apple playID
private static string kMediumMoneyApple = "_____";
public static string kProductIDConsumableBigMoney = "consumable3";
//Google playID
private static string kBigMoneyGoogle = "bigmoney";
//Apple playID
private static string kBigMoneyApple = "_____";
public static string kProductIDConsumableWhaleMoney = "consumable2";
//Google playID
private static string kWhaleMoneyGoogle = "whalemoney";
//Apple playID
private static string kWhaleMoneyApple = "_____";
SetData sd;
public UILabel _labelDebug;
void Start()
{
_labelDebug = GameObject.Find ("UI_Root/DebugPanel/LabelDebug").GetComponent<UILabel>();
_labelDebug.text += "\n\n" + ("We haven't set up the Unity purchasing");
// If we haven't set up the Unity Purchasing reference
if (m_StoreController == null)
{
// Begin to configure our connection to Purchasing
_labelDebug.text += "\n\n" + ("Begin to configure our connection to Purchasing");
InitializePurchasing();
}
}
public void InitializePurchasing ()
{
// If we have already connected to Purchasing ...
if (IsInitialized())
{
// ... we are done here.
_labelDebug.text += "\n\n" + ("... we are done IsInitialized.");
return;
}
_labelDebug.text += "\n\n" + ("Create a builder, first passing in a suite of Unity provided stores.");
// Create a builder, first passing in a suite of Unity provided stores.
var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
builder.Configure<IGooglePlayConfiguration> ().SetPublicKey ("MIIB...");
// Add a product to sell / restore by way of its identifier, associating the general identifier with its store-specific identifiers.
//builder.AddProduct(kProduct_CompleteGame_NonConsumable, ProductType.NonConsumable, new IDs(){{ kProduct_CompleteGame_GooglePlayNonConsumable, GooglePlay.Name },});
builder.AddProduct(kProductIDNonConsumableGainsMultiplier, ProductType.NonConsumable, new IDs(){
//{ kPermanentGainsMultiplierApple, AppleAppStore.Name },
{ kPermanentGainsMultiplierGoogle, GooglePlay.Name },});
builder.AddProduct(kProductIDConsumableSmallMoney, ProductType.Consumable, new IDs(){
//{ kSmallMoneyGoogle, AppleAppStore.Name },
{ kSmallMoneyApple, GooglePlay.Name },});
builder.AddProduct(kProductIDConsumableMediumMoney, ProductType.Consumable, new IDs(){
//{ kMediumMoneyApple, AppleAppStore.Name },
{ kMediumMoneyGoogle, GooglePlay.Name },});
builder.AddProduct(kProductIDConsumableBigMoney, ProductType.Consumable, new IDs(){
//{ kBigMoneyGoogle, AppleAppStore.Name },
{ kBigMoneyApple, GooglePlay.Name },});
builder.AddProduct(kProductIDConsumableWhaleMoney, ProductType.Consumable, new IDs(){
//{ kWhaleMoneyGoogle, AppleAppStore.Name },
{ kWhaleMoneyGoogle, GooglePlay.Name },});
_labelDebug.text += "\n\n" + ("Added products to builder");
// Kick off the remainder of the set-up with an asynchrounous call, passing the configuration
// and this class' instance. Expect a response either in OnInitialized or OnInitializeFailed.
UnityPurchasing.Initialize(this, builder);
}
private bool IsInitialized()
{
// Only say we are initialized if both the Purchasing references are set.
_labelDebug.text += "\n\n" + ("Purchasing references set" /*+ m_StoreController.ToString() + m_StoreExtensionProvider.ToString()*/);
if (m_StoreController != null) {
_labelDebug.text += "\n\n" + ("Purchasing references set m_StoreController");
}
if (m_StoreExtensionProvider != null) {
_labelDebug.text += "\n\n" + ("Purchasing references set m_StoreExtensionProvider");
}
return m_StoreController != null && m_StoreExtensionProvider != null;
}
public void BuyGainsMultiplier()
{
BuyProductID (kProductIDNonConsumableGainsMultiplier);
}
public void BuySmallMoney()
{
BuyProductID (kProductIDConsumableSmallMoney);
}
public void BuyMediumMoney()
{
BuyProductID (kProductIDConsumableMediumMoney);
}
public void BuyBigMoney()
{
BuyProductID (kProductIDConsumableBigMoney);
}
public void BuyWhaleMoney()
{
BuyProductID (kProductIDConsumableWhaleMoney);
}
void BuyProductID(string productId)
{
_labelDebug.text += "\n\n" + ("Started To buy");
if (IsInitialized ()) {
Product product = m_StoreController.products.WithID(productId);
if (product != null && product.availableToPurchase) {
Debug.Log (string.Format ("Purchasing product asynchronously: '{0}'", product.definition.id));
_labelDebug.text += "\n\n" + (string.Format ("Purchasing product asynchronously: '{0}'", product.definition.id));
m_StoreController.InitiatePurchase(product);
} else {
Debug.Log ("BuyProduct: Fail. Not purchasing product, either is not found or is not available for purchase");
_labelDebug.text += "\n\n" + ("BuyProduct: Fail. Not purchasing product, either is not found or is not available for purchase");
}
} else {
Debug.Log ("BuyProductID FAILED. Not initialized.");
_labelDebug.text += "\n\n" + ("BuyProductID FAILED. Not initialized.");
}
}
public void RestorePurchase()
{
if (!IsInitialized ())
{
Debug.Log ("RestorePurchases FAILED. Not initialized.");
_labelDebug.text += "\n\n" + ("RestorePurchases FAILED. Not initialized.");
return;
}
if (Application.platform == RuntimePlatform.IPhonePlayer || Application.platform == RuntimePlatform.OSXPlayer) {
Debug.Log ("RestorePurchases started ...");
_labelDebug.text += "\n\n" + ("RestorePurchases started ...");
var apple = m_StoreExtensionProvider.GetExtension<IAppleExtensions> ();
apple.RestoreTransactions ((result) => {
Debug.Log ("RestorePurchases continuing: " + result + "; If no further messages, no purchases available to store.");
_labelDebug.text += "\n\n" + ("RestorePurchases continuing: " + result + "; If no further messages, no purchases available to store.");
});
} else {
Debug.Log ("RestorePurchases FAIL. Not supported on this platform. Current = " + Application.platform);
_labelDebug.text += "\n\n" + ("RestorePurchases FAIL. Not supported on this platform. Current = " + Application.platform);
}
}
//ISTORELISTENER
public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
{
Debug.Log ("OnInitialized: PASS");
_labelDebug.text += "\n\n" + ("OnInitialized: PASS");
// Overall Purchasing system, configured with products for this application.
m_StoreController = controller;
// Store specific subsystem, for accessing device-specific store features.
m_StoreExtensionProvider = extensions;
}
public void OnInitializeFailed(InitializationFailureReason error)
{
Debug.Log ("OnInitializeFailed InitializationFailureReason : " + error);
_labelDebug.text += "\n\n" + ("OnInitializeFailed InitializationFailureReason : " + error);
}
public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)
{
if(String.Equals(args.purchasedProduct.definition.id, kProductIDNonConsumableGainsMultiplier, StringComparison.Ordinal))
{
Debug.Log(string.Format("ProvessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
_labelDebug.text += "\n\n" + (string.Format("ProvessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
GameStat.boughtMultiplierXP = true;
SetData sd = GameObject.Find("DataHolder").GetComponent<DataHolder>().sd;
sd.reset ();
SaveLoad.Save ();
}else if(String.Equals(args.purchasedProduct.definition.id, kProductIDConsumableSmallMoney, StringComparison.Ordinal))
{
Debug.Log(string.Format("ProvessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
_labelDebug.text += "\n\n" + (string.Format("ProvessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
SetData sd = GameObject.Find("DataHolder").GetComponent<DataHolder>().sd;
sd.incGold (1500);
GameStat.incGold(sd.currentGold);
sd.reset ();
SaveLoad.Save ();
}else if(String.Equals(args.purchasedProduct.definition.id, kProductIDConsumableMediumMoney, StringComparison.Ordinal))
{
Debug.Log(string.Format("ProvessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
_labelDebug.text += "\n\n" + (string.Format("ProvessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
SetData sd = GameObject.Find("DataHolder").GetComponent<DataHolder>().sd;
sd.incGold (5000);
GameStat.incGold(sd.currentGold);
sd.reset ();
SaveLoad.Save ();
}else if(String.Equals(args.purchasedProduct.definition.id, kProductIDConsumableBigMoney, StringComparison.Ordinal))
{
Debug.Log(string.Format("ProvessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
_labelDebug.text += "\n\n" + (string.Format("ProvessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
SetData sd = GameObject.Find("DataHolder").GetComponent<DataHolder>().sd;
sd.incGold (20000);
GameStat.incGold(sd.currentGold);
sd.reset ();
SaveLoad.Save ();
}else if(String.Equals(args.purchasedProduct.definition.id, kProductIDConsumableWhaleMoney, StringComparison.Ordinal))
{
Debug.Log(string.Format("ProvessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
_labelDebug.text += "\n\n" + (string.Format("ProvessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
SetData sd = GameObject.Find("DataHolder").GetComponent<DataHolder>().sd;
sd.incGold (100000);
GameStat.incGold(sd.currentGold);
sd.reset ();
GameObject.Find ("DataHolder").GetComponent<DataHolder> ().sd.reset();
SaveLoad.Save ();
}else{
Debug.Log(string.Format("ProcessPurchase: FAIL. Unrecognized product '{0}'", args.purchasedProduct.definition.id));
_labelDebug.text += "\n\n" + (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));
_labelDebug.text += "\n\n" + (string.Format ("OnPurchaseFailed: FAIL. Product '{0}', PurchaseFAilureReason: {1}", product.definition.storeSpecificId, failureReason));
}
}
Adding infos here: - we test on Google Play (Beta, and products are active) - we test with tester account - we targeted PlayStore via the menu (Windows > Unity IAP > Android > Target to Google Play Store) - we are desperate (specially cause we already have a game on the store in which IAP are working with the SA$$anonymous$$E CODE)
Your answer
![](https://koobas.hobune.stream/wayback/20220612094009im_/https://answers.unity.com/themes/thub/images/avi.jpg)