예제 #1
0
        /// <summary>
        /// Grant non-consumables on the user's inventory on PlayFab. Consumables will be granted only
        /// locally to minimize requests - please call SetFunds or SetPlayerData afterwards if needed.
        /// </summary>
        public static IEnumerator SetPurchase(List <string> productIDs)
        {
            //create a separate list for non-consumables to request
            List <string> cloudProducts = new List <string>();

            for (int i = 0; i < productIDs.Count; i++)
            {
                if ((int)IAPManager.GetIAPObject(productIDs[i]).type > 0)
                {
                    cloudProducts.Add(productIDs[i]);
                }
            }

            bool commit = true;

            if (cloudProducts.Count > 0)
            {
                ExecuteCloudScriptRequest cloudRequest = new ExecuteCloudScriptRequest()
                {
                    FunctionName      = "grantItems",
                    FunctionParameter = new { itemIds = cloudProducts.ToArray() }
                };

                bool result = false;
                PlayFabClientAPI.ExecuteCloudScript(cloudRequest, (cloudResult) =>
                {
                    result = true;
                }, (error) =>
                {
                    OnPlayFabError(error);
                    commit = false;
                    result = true;
                });

                while (!result)
                {
                    yield return(null);
                }
            }

            //only grant products if the cloud request was successful
            if (commit == true)
            {
                for (int i = 0; i < productIDs.Count; i++)
                {
                    if (DBManager.GetPurchase(productIDs[i]) == 0)
                    {
                        IAPManager.GetInstance().PurchaseVerified(productIDs[i]);
                    }
                }
            }

            yield return(null);
        }
예제 #2
0
        /// <summary>
        /// Sets a product to purchased after successful verification (or without).
        /// This alters the database entry for non-consumable or products with usage as well.
        /// </summary>
        public void PurchaseVerified(string id)
        {
            if (!IAPObjects.ContainsKey(id))
            {
                id = GetIAPIdentifier(id);
            }
            if (!IAPObjects.ContainsKey(id))
            {
                return;
            }
            IAPObject obj = IAPObjects[id];

            switch (obj.editorType)
            {
            case IAPType.Currency:
                foreach (IAPCurrency cur in obj.virtualPrice)
                {
                    DBManager.IncreaseFunds(cur.name, cur.amount);
                }
                break;

            default:
                //for consumables, add the defined usage count to tracking in player data
                //on non-consumables, don't continue if the product is already purchased,
                //for example if we just want to verify an existing product again
                switch (obj.type)
                {
                case ProductType.Consumable:
                    if (obj.usageCount > 0)
                    {
                        DBManager.IncreasePlayerData(id, obj.usageCount);

                        //update server player data
                                #if PLAYFAB && !PLAYFAB_VALIDATION
                        PlayfabManager.SetPlayerData();
                                #endif
                    }
                    break;

                default:
                    if (DBManager.GetPurchase(id) > 0)
                    {
                        return;
                    }

                    DBManager.IncreasePurchase(id, 1);
                    break;
                }
                break;
            }

            purchaseSucceededEvent(id);
        }
예제 #3
0
        /// <summary>
        /// Refreshes the visual representation of a specific shop item.
        /// This is called automatically because of subscribing to the DBManager update event.
        /// It also means saving performance due to not refreshing all items every time.
        /// </summary>
        public void Refresh(string id)
        {
            //this method is based on data from the database,
            //so if we don't have a DBManager instance don't continue
            if (!DBManager.GetInstance())
            {
                return;
            }

            IAPObject obj  = IAPManager.GetIAPObject(id);
            IAPItem   item = instance.IAPItems.ContainsKey(id) ? instance.IAPItems[id] : null;

            if (obj == null || item == null || item.productId != id)
            {
                return;
            }

            bool isSelected  = DBManager.GetSelected(id);
            bool isPurchased = DBManager.GetPurchase(id) > 0;

            //double check that selected items are actually owned
            //if not, correct the entry by setting it to deselected
            if (isSelected && !isPurchased)
            {
                DBManager.SetDeselected(id);
                isSelected = false;
            }

            if (isPurchased)
            {
                item.Purchased(true);

                //in case the item has been selected before, but also auto-select one item per group
                //more items per group can be pre-selected manually e.g. on app launch
                if (isSelected || (item.selectButton && !item.deselectButton &&
                                   DBManager.GetSelectedGroup(IAPManager.GetIAPObjectGroupName(id)).Count == 0))
                {
                    item.IsSelected(true);
                }
            }
            else if (!string.IsNullOrEmpty(obj.req.entry) && DBManager.isRequirementMet(obj.req))
            {
                //check if a requirement is set up for this item,
                //then unlock if the requirement has been met
                if (IAPManager.isDebug)
                {
                    Debug.Log("requirement met for: " + obj.id);
                }
                item.Unlock();
            }
        }
예제 #4
0
        /// <summary>
        /// Returns the next unpurchased upgrade id of a product.
        /// </summary>
        public static string GetNextUpgrade(string productId)
        {
            string    id  = GetCurrentUpgrade(productId);
            IAPObject obj = GetIAPObject(id);

            if (DBManager.GetPurchase(id) == 0 || obj == null || string.IsNullOrEmpty(obj.req.nextId))
            {
                return(id);
            }
            else
            {
                return(obj.req.nextId);
            }
        }
예제 #5
0
        /// <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, this should not happen
            if (obj.type != ProductType.Consumable && DBManager.GetPurchase(productId) > 0)
            {
                OnPurchaseFailed("Product already owned.");
                return;
            }

            #if PLAYFAB && !PLAYFAB_VALIDATION
            new PlayfabStore().Purchase(obj);
            return;
            #endif

            //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.IncreasePlayerData(productId, obj.usageCount);
                    purchaseSucceededEvent(productId);
                }
                else
                {
                    DBManager.SetPurchase(obj.id);
                }
                purchaseSucceededEvent(productId);
            }
            else
            {
                OnPurchaseFailed("Insufficient funds.");
            }
        }
예제 #6
0
        /// <summary>
        /// Returns the last purchased upgrade id of a product,
        /// or the main product itself if it hasn't been purchased yet.
        /// </summary>
        public static string GetCurrentUpgrade(string productId)
        {
            if (DBManager.GetPurchase(productId) == 0)
            {
                return(productId);
            }

            string        id       = productId;
            List <string> upgrades = GetIAPUpgrades(productId);

            for (int i = upgrades.Count - 1; i >= 0; i--)
            {
                if (DBManager.GetPurchase(upgrades[i]) > 0)
                {
                    id = upgrades[i];
                    break;
                }
            }

            return(id);
        }
예제 #7
0
        //returning products retrieved by the billing system back to Unity IAP
        private void OnProductsRetrieved(BillingProduct[] list, string error)
        {
            if (!string.IsNullOrEmpty(error))
            {
                OnSetupFailed(error);
                return;
            }

            string itemId = null;

            for (int i = 0; i < list.Length; i++)
            {
                itemId = list[i].ProductIdentifier;

                if (!products.ContainsKey(itemId))
                {
                    products.Add(itemId, new ProductDescription(itemId, new ProductMetadata(list[i].LocalizedPrice,
                                                                                            list[i].Name, list[i].Description,
                                                                                            list[i].CurrencyCode, (decimal)list[i].Price)));
                }

                if (PlayerPrefs.HasKey(itemId))
                {
                    products[itemId] = new ProductDescription(itemId, products[itemId].metadata, DBManager.GetReceipt(itemId), "");
                }

                //auto restore products in case database does not match
                #if UNITY_ANDROID
                string globalId = IAPManager.GetIAPIdentifier(itemId);
                if (NPBinding.Billing.IsProductPurchased(list[i]) && DBManager.GetPurchase(globalId) == 0)
                {
                    DBManager.SetPurchase(globalId);
                }
                #endif
            }

            callback.OnProductsRetrieved(products.Values.ToList());
        }