public void OnPurchaseSucceeded(IOSStoreKitResult item) { switch (item.State) { case InAppPurchaseState.Deferred: return; case InAppPurchaseState.Restored: ProductDefinition definition = definitions.FirstOrDefault(x => x.storeSpecificId == item.ProductIdentifier); if (definition == null || definition.type == ProductType.Subscription || DBManager.isPurchased(definition.id)) { return; } break; case InAppPurchaseState.Failed: OnPurchaseFailed(item.Error.Message, item.Error.Code); return; } string transactionId = item.TransactionIdentifier; #if UNITY_EDITOR //allow for multiple test purchases with unique transactions transactionId = (System.DateTime.UtcNow - new System.DateTime(1970, 1, 1, 0, 0, 0, System.DateTimeKind.Utc)).TotalSeconds.ToString(); #endif callback.OnPurchaseSucceeded(item.ProductIdentifier, item.Receipt, transactionId); }
private void OnProductsRetrieved(Result result) { this.products = new Dictionary <string, ProductDescription>(); if (!result.IsSucceeded) { OnSetupFailed(result.Error.Code + ", " + result.Error.Message); return; } List <IOSProductTemplate> list = IOSInAppPurchaseManager.Instance.Products; string globalId = null; string storeId = null; for (int i = 0; i < list.Count; i++) { storeId = list[i].Id; globalId = IAPManager.GetIAPIdentifier(storeId); if (!products.ContainsKey(globalId)) { products.Add(globalId, new ProductDescription(storeId, new ProductMetadata(list[i].LocalizedPrice, list[i].DisplayName, list[i].Description, list[i].CurrencyCode, (decimal)list[i].Price))); } if (PlayerPrefs.HasKey(globalId)) { products[globalId] = new ProductDescription(storeId, products[globalId].metadata, DBManager.GetReceipt(globalId), ""); } } callback.OnProductsRetrieved(products.Values.ToList()); }
/// <summary> /// initialization called by IAPManager in Awake() /// </summary> public void Init() { instance = this; InitDB(); }
/// <summary> /// initialization called by IAPManager in Awake() /// </summary> public void Init() { instance = this; InitDB(); PlayerPrefs.SetString("blurb", "moreblurbs"); PlayerPrefs.Save(); }
// 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); } } } }
/// <summary> /// Initialization called by IAPManager in Awake(). /// </summary> public void Init() { instance = this; InitDB(); }