/// <summary> /// initialization called by IAP Manager in Awake() /// </summary> public void Init() { instance = this; InitShop(); SetItemState(); UnlockItems(); }
//when the window gets opened void OnEnable() { //reconnect reference if (iapEditor == null) iapEditor = this; //get reference to the shop and cache it shop = GameObject.FindObjectOfType(typeof(ShopManager)) as ShopManager; script = FindIAPManager(); //could not get prefab, non-existent? if (script == null) return; if (shop) RemoveContainerConnections(); }
//when the window gets opened void OnEnable() { //reconnect reference if (iapEditor == null) iapEditor = this; //get reference to the shop and cache it shop = GameObject.FindObjectOfType(typeof(ShopManager)) as ShopManager; script = FindIAPManager(); //could not get prefab, non-existent? if (script == null) return; if (shop) RemoveContainerConnections(); //set current currency index from -1 to first one, //if currencies were specified if (script.currency.Count > 0) currencyIndex = 0; }
/// <summary> /// Overriding the payment request for opening the PayPal website in the browser. /// </summary> public override void OnPurchaseResult(PayForPurchaseResult result) { ShopManager.ShowConfirmation(); Application.OpenURL(result.PurchaseConfirmationPageURL); }
/// <summary> /// Initializes all IAPItem in the scene and instantiates them with their correct state. /// Called by IAPManager. /// </summary> public void Init() { instance = this; IAPItems.Clear(); DBManager.updatedDataEvent += Refresh; //get manually placed items in the scene IAPItem[] sceneItems = Resources.FindObjectsOfTypeAll(typeof(IAPItem)) as IAPItem[]; for (int i = 0; i < sceneItems.Length; i++) { if (string.IsNullOrEmpty(sceneItems[i].productId)) { continue; } #if UNITY_EDITOR if (UnityEditor.EditorUtility.IsPersistent(sceneItems[i].gameObject)) { continue; } #endif IAPItems.Add(sceneItems[i].productId, sceneItems[i]); } //get list of all shop groups from IAPManager List <IAPGroup> list = IAPManager.GetInstance().IAPs; int index = 0; //loop over groups for (int i = 0; i < list.Count; i++) { //cache current group IAPGroup group = list[i]; ShopContainer container = GetContainer(group.id); //skip group if prefab or parent wasn't set if (container == null || container.prefab == null || container.parent == null) { continue; } //loop over items for (int j = 0; j < group.items.Count; j++) { //cache item IAPObject obj = group.items[j]; //the item has already been placed in the scene manually //dont instantiate it in a container then if (IAPItems.ContainsKey(obj.id)) { continue; } //instantiate shop item in the scene and attach it to the defined parent transform GameObject newItem = (GameObject)Instantiate(container.prefab); newItem.transform.SetParent(container.parent.transform, false); newItem.GetComponent <RectTransform>().anchoredPosition = Vector2.zero; //rename item to force ordering as set in the IAP Settings editor newItem.name = "IAPItem " + string.Format("{0:000}", index + j); //get IAPItem component of the instantiated item IAPItem item = newItem.GetComponent <IAPItem>(); if (item == null) { continue; } //add IAPItem to dictionary for later lookup IAPItems.Add(obj.id, item); //upgrades overwrite, an IAP Item gets replaced with its current level List <string> upgrades = IAPManager.GetIAPUpgrades(obj.id); if (upgrades != null && upgrades.Count > 0) { for (int k = 0; k < upgrades.Count; k++) { IAPItems.Add(upgrades[k], item); } string currentUpgrade = IAPManager.GetNextUpgrade(obj.id); if (!string.IsNullOrEmpty(currentUpgrade)) { obj = IAPManager.GetIAPObject(currentUpgrade); } } //initialize and set up item properties based on the associated IAPObject //they could get overwritten by online data later item.Init(obj); } index += group.items.Count; } //refresh all products initially RefreshAll(); }
/// <summary> /// handle purchases, for real money or ingame currency /// </summary> public void HandleSuccessfulPurchase(string id) { //differ between ids set in the IAP Settings editor if (debug) { Debug.Log("HandleSuccessfulPurchase: " + id); } //get instantiated shop item based on the IAP id IAPItem item = null; if (ShopManager.GetInstance()) { item = ShopManager.GetIAPItem(id); } //if the purchased item was non-consumable, //additionally block further purchase of the shop item if (item != null && (item.type == IAPType.nonConsumable || item.type == IAPType.nonConsumableVirtual || item.type == IAPType.subscription)) { item.Purchased(true); } switch (id) { //section for in app purchases case "bann_coins": gameParameters.currentCharacter = "Bann"; PlayerPrefs.SetString("currentCharacter", gameParameters.currentCharacter); ShowMessage("You can now play with Bann!"); break; case "bella_coins": gameParameters.currentCharacter = "Bella"; PlayerPrefs.SetString("currentCharacter", gameParameters.currentCharacter); ShowMessage("You can now play with Bella!"); break; case "blane_coins": gameParameters.currentCharacter = "Blane"; PlayerPrefs.SetString("currentCharacter", gameParameters.currentCharacter); ShowMessage("You can now play with Blane!"); break; case "damien_coins": gameParameters.currentCharacter = "Damien"; PlayerPrefs.SetString("currentCharacter", gameParameters.currentCharacter); ShowMessage("You can now play with Damien!"); break; case "finnikin_coins": gameParameters.currentCharacter = "Finnikin"; PlayerPrefs.SetString("currentCharacter", gameParameters.currentCharacter); ShowMessage("You can now play with Finnikin!"); break; case "gwyn_coins": gameParameters.currentCharacter = "Gwyn"; PlayerPrefs.SetString("currentCharacter", gameParameters.currentCharacter); ShowMessage("You can now play with Gwyn!"); break; case "hector_coins": gameParameters.currentCharacter = "Hector"; PlayerPrefs.SetString("currentCharacter", gameParameters.currentCharacter); ShowMessage("You can now play with Hector!"); break; case "katsa_coins": gameParameters.currentCharacter = "Katsa"; PlayerPrefs.SetString("currentCharacter", gameParameters.currentCharacter); ShowMessage("You can now play with Katsa!"); break; case "mather_coins": gameParameters.currentCharacter = "Mather"; PlayerPrefs.SetString("currentCharacter", gameParameters.currentCharacter); ShowMessage("You can now play with Mather!"); break; case "pifoo_coins": gameParameters.currentCharacter = "Pifoo"; PlayerPrefs.SetString("currentCharacter", gameParameters.currentCharacter); ShowMessage("You can now play with Pifoo!"); break; case "rylan_coins": gameParameters.currentCharacter = "Rylan"; PlayerPrefs.SetString("currentCharacter", gameParameters.currentCharacter); ShowMessage("You can now play with Rylan!"); break; case "sothe_coins": gameParameters.currentCharacter = "Sothe"; PlayerPrefs.SetString("currentCharacter", gameParameters.currentCharacter); ShowMessage("You can now play with Sothe!"); break; case "wesker_coins": gameParameters.currentCharacter = "Wesker"; PlayerPrefs.SetString("currentCharacter", gameParameters.currentCharacter); ShowMessage("You can now play with Wesker!"); break; case "yuki_coins": gameParameters.currentCharacter = "Yuki"; PlayerPrefs.SetString("currentCharacter", gameParameters.currentCharacter); ShowMessage("You can now play with Yuki!"); break; } }
/// <summary> /// handle purchases, for real money or ingame currency /// </summary> public void HandleSuccessfulPurchase(string id) { //differ between ids set in the IAP Settings editor if (IAPManager.isDebug) { Debug.Log("HandleSuccessfulPurchase: " + id); } IAPObject obj = IAPManager.GetIAPObject(id); //get instantiated shop item based on the IAP id IAPItem item = null; if (ShopManager.GetInstance()) { item = ShopManager.GetIAPItem(id); } //if the purchased item was non-consumable, //additionally block further purchase of the shop item if (item != null && obj != null && obj.type != ProductType.Consumable) { item.Purchased(true); } switch (id) { //section for in app purchases case "coins": //the user bought the item "coins", //increase coins by 1000 and show appropriate feedback DBManager.IncreaseFunds("coins", 1000); ShowMessage("1000 coins were added to your balance!"); break; case "coin_pack": DBManager.IncreaseFunds("coins", 2500); ShowMessage("2500 coins were added to your balance!"); break; case "big_coin_pack": DBManager.IncreaseFunds("coins", 6000); ShowMessage("6000 coins were added to your balance!"); break; case "huge_coin_pack": DBManager.IncreaseFunds("coins", 12000); ShowMessage("12000 coins were added to your balance!"); break; case "no_ads": //no_ads purchased. You can now check DBManager.isPurchased("no_ads") //before showing ads and block them ShowMessage("Ads disabled!"); break; case "abo_monthly": //same here - your code to unlock subscription content ShowMessage("Subscribed to monthly abo!"); break; case "restore": //nothing else to call here, //the actual restore is handled by IAPManager ShowMessage("Restored transactions!"); break; //section for in game content case "bullets": //for virtual items, you could use DBManager's custom data option in order //to save amounts of virtual products. E.g. increasing bullets by 100: //int bullets = DBManager.GetPlayerData("bullets").AsInt; //DBManager.SetPlayerData("bullets", new SimpleJSON.JSONData(bullets + 100)); ShowMessage("Bullets were added to your inventory!"); break; case "health": ShowMessage("Medikits were added to your inventory!"); break; case "energy": ShowMessage("Energy was added to your inventory!"); break; case "speed": ShowMessage("Speed boost unlocked!"); break; case "speed_1": case "speed_2": case "speed_3": ShowMessage("Speed boost upgraded!"); break; case "bonus": ShowMessage("Bonus level unlocked!"); break; case "uzi": ShowMessage("Uzi unlocked!"); break; case "ak47": ShowMessage("AK47 unlocked!"); break; case "m4": ShowMessage("M4 unlocked!"); break; case "hat": ShowMessage("Hat unlocked!"); break; case "backpack": ShowMessage("Backpack unlocked!"); break; case "belt": ShowMessage("Ammo belt unlocked!"); break; case "jetpack": ShowMessage("Jetpack unlocked!"); break; case "booster": ShowMessage("Double XP unlocked!"); break; } }
// handles an online verification request and response from // our external server. www.text can returns true or false. // true: purchase verified, false: not verified (fake?) purchase IEnumerator WaitForRequest(Dictionary <string, string> dic) { //cache requested product id string id = dic["pid"]; //build POST request with transaction data WWWForm form = new WWWForm(); foreach (string key in dic.Keys) { form.AddField(key, dic[key]); } //create URL and execute until we have a respone WWW www = new WWW(serverUrl + verificationFileName, form); yield return(www); //check for URL errors if (www.error == null) { //we have a successful response from our server, //but it returned false (fake purchase) if (!bool.Parse(www.text)) { inventory.ErasePurchase(id); if (debug) { Debug.Log("The receipt for '" + id + "' could not be verified: " + www.text); } //PurchaseFailed("The receipt for '" + id + "' could not be verified."); id = GetIAPIdentifier(id); //remove purchase from the database and update item state if (DBManager.isPurchased(id)) { IAPItem item = null; if (ShopManager.GetInstance()) { item = ShopManager.GetIAPItem(id); } if (item) { item.Purchased(false); } DBManager.RemovePurchased(id); } yield break; } else { //successful response, verified transaction if (debug) { Debug.Log(dic["pid"] + " verification success."); } } } else { //we can't reach our external server, do nothing: //in this case we handle the purchase as without verification if (debug) { Debug.Log("Verification URL error: " + www.text); } } id = GetIAPIdentifier(id); PurchaseVerified(id); }
// check for purchases on online servers at billing initialization. // If a purchase is not registered, set local purchase state back to false private void VerifyReceipts() { //get list of old purchases: on iOS the saved and filtered transactions (avoiding duplicates), //on Android we use the old purchases list received from Google #if UNITY_IPHONE List <StoreKitTransaction> prods = FilterTransactions(StoreKitBinding.getAllSavedTransactions()); #endif if (prods == null || prods.Count == 0) { return; } //loop over all IAP items to check if a valid receipt exists for (int i = 0; i < ids.Length; i++) { //cache IAP id, //only verify purchased items string localId = ids[i]; string globalId = GetIAPIdentifier(localId); if (DBManager.isPurchased(globalId)) { //initialize item as faked and loop over receipts bool faked = true; for (int j = 0; j < prods.Count; j++) { //find corresponding transaction class string identifier = ""; #if UNITY_IPHONE StoreKitTransaction purchase = prods[j]; identifier = purchase.productIdentifier; #elif UNITY_ANDROID GooglePurchase purchase = prods[j]; identifier = purchase.productId; #endif if (identifier == localId) { //we found a receipt for this product on the device, //unset fake purchase and let our external //server decide what happens with this transaction faked = false; MakeRequest(purchase); break; } } //we haven't found a receipt for this item, yet it is //set to purchased. This can't be, maybe our external server //response or the database has been hacked with fake data if (faked) { IAPItem item = null; if (ShopManager.GetInstance()) { item = ShopManager.GetIAPItem(globalId); } if (item) { item.Purchased(false); } DBManager.RemovePurchased(globalId); } } } }