/// <summary> /// Restore already purchased user's transactions for non consumable IAPs. /// For Android we use the received list for detecting previous purchases. /// </summary> public static void RestoreTransactions() { #if UNITY_IOS extensions.GetExtension <IAppleExtensions>().RestoreTransactions(OnTransactionsRestored); #else Product[] purchasedProducts = controller.products.all; foreach (Product product in purchasedProducts) { string id = product.definition.id; if (DBManager.isPurchased(id) || product.definition.type == ProductType.Consumable || !product.hasReceipt || String.IsNullOrEmpty(product.receipt)) { continue; } DBManager.SetToPurchased(id); } OnTransactionsRestored(true); #endif //update ShopManager GUI items if (ShopManager.GetInstance()) { ShopManager.SetItemState(); } }
/// <summary> /// Overload for purchasing virtual product based on its product identifier. /// </summary> public static void PurchaseProduct(IAPObject obj) { string productId = obj.id; //product is set to already owned, do nothing if (DBManager.isPurchased(productId)) { OnPurchaseFailed("Product already purchased."); return; } //check whether the player has enough funds bool didSucceed = DBManager.VerifyVirtualPurchase(obj); if (isDebug) { Debug.Log("Purchasing virtual product " + productId + ", result: " + didSucceed); } //on success, non-consumables are saved to the database. This automatically //saves the new substracted fund value, then and fire the succeeded event if (didSucceed) { if (obj.type != ProductType.Consumable) { DBManager.SetToPurchased(productId); } purchaseSucceededEvent(productId); } else { OnPurchaseFailed("Insufficient funds."); } }
// set product to purchased after successful verification (or without) // For non consumable IAPs or subscriptions, alter database entry public void PurchaseVerified(string id) { if (!IAPObjects.ContainsKey(id)) { id = GetIAPIdentifier(id); } if (!IAPObjects.ContainsKey(id)) { return; } IAPObject obj = IAPObjects[id]; //don't continue if the product is already purchased, //for example if we just want to verify an existing product again if (DBManager.isPurchased(id)) { return; } if (obj.type != ProductType.Consumable) { DBManager.SetToPurchased(id); } purchaseSucceededEvent(id); }
/// <summary> /// restore already purchased user's transactions for non consumable iaps. /// For Android/WP8 we use the received list for detecting previous purchases /// </summary> public static void RestoreTransactions() { #if UNITY_IPHONE OpenIAB.restoreTransactions(); #elif UNITY_ANDROID || UNITY_WP8 if (inventory == null) { RestoreFailed("Restoring transactions failed. Please try again."); return; } List <string> prods = inventory.GetAllOwnedSkus(); for (int i = 0; i < prods.Count; i++) { string id = GetIAPIdentifier(prods[i]); if (!DBManager.isPurchased(id)) { DBManager.SetToPurchased(id); } } RestoreSucceeded(); #endif //update ShopManager GUI items if (ShopManager.GetInstance()) { ShopManager.SetItemState(); } }
/// <summary> /// purchase non-consumable virtual product based on its product id /// </summary> public static void PurchaseNonconsumableVirtualProduct(string productId) { //if already owned, do nothing if (DBManager.isPurchased(productId)) { PurchaseFailed("Product already purchased."); return; } //check whether the player has enough funds bool didSucceed = DBManager.VerifyVirtualPurchase(GetIAPObject(productId)); if (instance.debug) { Debug.Log("purchasing non-consumable virtual product " + productId + " result: " + didSucceed); } //on success, non-consumables are being saved to the database //this automatically saves the new substracted fund value to the database //and fire the succeeded event if (didSucceed) { DBManager.SetToPurchased(productId); purchaseSucceededEvent(productId); } //otherwise show fail message else { PurchaseFailed("Insufficient funds."); } }
// set product to purchased after successful verification (or without) // Consumable IAPs must be consumed // For non consumable IAPs or subscriptions, alter database entry private void PurchaseVerified(string id) { if (!IAPObjects.ContainsKey(id)) { return; } IAPObject obj = IAPObjects[id]; if (obj.type == IAPType.consumable) { OpenIAB.consumeProduct(inventory.GetPurchase(obj.GetIdentifier())); //local id return; } //don't continue if the product is already purchased, //for example if we just want to verify an existing product again if (DBManager.isPurchased(id)) { return; } if (obj.type == IAPType.nonConsumable || obj.type == IAPType.subscription) { DBManager.SetToPurchased(id); } purchaseSucceededEvent(id); }
/// <summary> /// restore already purchased user's transactions for non consumable iaps. /// For Android we use the received list for detecting previous purchases /// </summary> public static void RestoreTransactions() { #if UNITY_IPHONE StoreKitBinding.restoreCompletedTransactions(); #elif UNITY_ANDROID if (prods == null) { RestoreFailed("Restoring transactions failed. Please try again."); return; } for (int i = 0; i < prods.Count; i++) { string id = GetIAPIdentifier(prods[i].productId); if (!DBManager.isPurchased(id)) { DBManager.SetToPurchased(id); } } RestoreSucceeded(); #endif //update ShopManager GUI items if (ShopManager.GetInstance()) { ShopManager.SetItemState(); } }
private void OnProductsRetrieved(BillingResult result) { if (!result.IsSuccess) { OnSetupFailed(result.Response + ", " + result.Message); return; } AndroidInventory inventory = AndroidInAppPurchaseManager.Client.Inventory; List <GoogleProductTemplate> list = inventory.Products; List <GooglePurchaseTemplate> purchases = inventory.Purchases; string globalId = null; string storeId = null; for (int i = 0; i < list.Count; i++) { storeId = list[i].SKU; globalId = IAPManager.GetIAPIdentifier(storeId); if (!products.ContainsKey(globalId)) { products.Add(globalId, new ProductDescription(storeId, new ProductMetadata(list[i].LocalizedPrice, list[i].Title, list[i].Description, list[i].PriceCurrencyCode, (decimal)list[i].Price))); } //check for non-consumed consumables if (storeId in purchases) { IAPObject obj = IAPManager.GetIAPObject(IAPManager.GetIAPIdentifier(purchases[i].SKU)); if (obj != null && obj.type == ProductType.Consumable) { AndroidInAppPurchaseManager.Client.Consume(purchases[i].SKU); continue; } } bool storeResult = inventory.IsProductPurchased(storeId); if (storeResult == true) { products[globalId] = new ProductDescription(storeId, products[globalId].metadata, inventory.GetPurchaseDetails(storeId).Token, inventory.GetPurchaseDetails(storeId).OrderId); } #if !UNITY_EDITOR //auto restore products in case database does not match if (storeResult != DBManager.isPurchased(globalId)) { if (storeResult) { DBManager.SetToPurchased(globalId); } else { DBManager.RemovePurchased(globalId); } } #endif } callback.OnProductsRetrieved(products.Values.ToList()); }