internal GoogleAcknowledgePurchaseListener(ProductDefinition product, GooglePurchase purchase, Action <ProductDefinition, GooglePurchase, GoogleBillingResult> onAcknowledgePurchaseResponseAction)
     : base(k_AndroidAcknowledgePurchaseResponseListenerClassName)
 {
     m_Product  = product;
     m_Purchase = purchase;
     m_OnAcknowledgePurchaseResponse = onAcknowledgePurchaseResponseAction;
 }
        // INativeStore
        public void Purchase(string productJSON, string developerPayload)
        {
            var         dic = (Dictionary <string, object>)MiniJson.JsonDecode(productJSON);
            object      obj;
            string      id, storeId, type;
            ProductType itemType;

            dic.TryGetValue("id", out obj);
            id = obj.ToString();
            dic.TryGetValue("storeSpecificId", out obj);
            storeId = obj.ToString();
            dic.TryGetValue("type", out obj);
            type = obj.ToString();
            if (Enum.IsDefined(typeof(ProductType), type))
            {
                itemType = (ProductType)Enum.Parse(typeof(ProductType), type);
            }
            else
            {
                itemType = ProductType.Consumable;
            }

            // This doesn't currently deal with "enabled" and "payouts" that could be included in the JSON
            var product = new ProductDefinition(id, storeId, itemType);

            FakePurchase(product, developerPayload);
        }
 public void QueryAsyncSku(ProductDefinition product, Action <List <AndroidJavaObject> > onSkuDetailsResponse)
 {
     QueryAsyncSku(new List <ProductDefinition>
     {
         product
     }.AsReadOnly(), onSkuDetailsResponse);
 }
Example #4
0
 internal GoogleConsumeResponseListener(ProductDefinition product, GooglePurchase purchase, Action <ProductDefinition, GooglePurchase, IGoogleBillingResult, string> onConsumeResponseAction)
     : base(k_AndroidConsumeResponseListenerClassName)
 {
     m_Product           = product;
     m_Purchase          = purchase;
     m_OnConsumeResponse = onConsumeResponseAction;
 }
Example #5
0
 public void HandleFinishTransaction(ProductDefinition product, GooglePurchase googlePurchase, GoogleBillingResult billingResult, string purchaseToken)
 {
     if (!m_ProcessedPurchaseToken.Contains(purchaseToken))
     {
         if (billingResult.responseCode == GoogleBillingResponseCode.k_Ok)
         {
             m_ProcessedPurchaseToken.Add(purchaseToken);
             CallPurchaseSucceededUpdateReceipt(product, googlePurchase, purchaseToken);
         }
         else if (IsResponseCodeInRecoverableState(billingResult))
         {
             FinishTransaction(product, purchaseToken);
         }
         else
         {
             m_StoreCallback?.OnPurchaseFailed(
                 new PurchaseFailureDescription(
                     product.storeSpecificId,
                     PurchaseFailureReason.Unknown,
                     billingResult.debugMessage + " {code: " + billingResult.responseCode + ", M: GPSFTS.HFT}"
                     )
                 );
         }
     }
 }
Example #6
0
        /// <summary>
        /// Called back by our IStore when it has fetched the latest product data.
        /// </summary>
        public void OnProductsRetrieved(List <ProductDescription> products)
        {
            var unknownProducts = new HashSet <Product>();

            foreach (var product in products)
            {
                var matchedProduct = this.products.WithStoreSpecificID(product.storeSpecificId);
                if (null == matchedProduct)
                {
                    var definition = new ProductDefinition(product.storeSpecificId,
                                                           product.storeSpecificId, product.type);
                    matchedProduct = new Product(definition, product.metadata);
                    unknownProducts.Add(matchedProduct);
                }
                matchedProduct.availableToPurchase = true;
                matchedProduct.metadata            = product.metadata;
                matchedProduct.transactionID       = product.transactionId;

                if (!string.IsNullOrEmpty(product.receipt))
                {
                    matchedProduct.receipt = FormatUnifiedReceipt(product.receipt, product.transactionId);
                }
            }

            if (unknownProducts.Count > 0)
            {
                this.products.AddProducts(unknownProducts);
            }

            // Fire our initialisation events if this is a first poll.
            CheckForInitialization();

            ProcessPurchaseOnStart();
        }
Example #7
0
        public override void Purchase(ProductDefinition product, string developerPayload)
        {
            m_Bindings.Purchase(product.storeSpecificId, (success, message) =>
            {
                var dic = message.HashtableFromJson();
                if (success)
                {
                    var transactionId   = dic.GetString("GameOrderId");
                    var storeSpecificId = dic.GetString("ProductId");
                    if (!string.IsNullOrEmpty(transactionId))
                    {
                        dic["transactionId"] = transactionId;
                    }

                    if (!string.IsNullOrEmpty(storeSpecificId))
                    {
                        dic["storeSpecificId"] = storeSpecificId;
                    }

                    if (!product.storeSpecificId.Equals(storeSpecificId))
                    {
                        m_Logger.LogFormat(LogType.Error,
                                           "UDPImpl received mismatching product Id for purchase. Expected {0}, received {1}",
                                           product.storeSpecificId, storeSpecificId);
                    }

                    var data = dic.toJson();
                    unity.OnPurchaseSucceeded(product.storeSpecificId, data, transactionId);
                }
                else
                {
                    if (dic.ContainsKey(k_Errorcode) && Convert.ToInt32(dic[k_Errorcode]) == PURCHASE_PENDING_CODE)
                    {
                        if (null != m_DeferredCallback)
                        {
                            OnPurchaseDeferred(product.storeSpecificId);
                        }
                        return;
                    }

                    PurchaseFailureReason reason = (PurchaseFailureReason)Enum.Parse(typeof(PurchaseFailureReason),
                                                                                     k_Unknown);

                    var reasonString = reason.ToString();
                    var errDic       = new Dictionary <string, object> {
                        ["error"] = reasonString
                    };

                    if (dic.ContainsKey("purchaseInfo"))
                    {
                        errDic["purchaseInfo"] = dic["purchaseInfo"];
                    }

                    var errData = errDic.toJson();
                    var pfd     = new PurchaseFailureDescription(product.storeSpecificId, reason, message);
                    unity.OnPurchaseFailed(pfd);
                }
            }, developerPayload);
        }
Example #8
0
 void CallPurchaseSucceededUpdateReceipt(ProductDefinition product, GooglePurchase googlePurchase, string purchaseToken)
 {
     m_StoreCallback?.OnPurchaseSucceeded(
         product.storeSpecificId,
         googlePurchase.receipt,
         purchaseToken
         );
 }
Example #9
0
 public void Purchase(ProductDefinition product, Product oldProduct, int desiredProrationMode)
 {
     m_QuerySkuDetailsService.QueryAsyncSku(product,
                                            skus =>
     {
         OnQuerySkuDetailsResponse(skus, product, oldProduct, desiredProrationMode);
     });
 }
 public void PriceChange(ProductDefinition product, Action <IGoogleBillingResult> onPriceChangedListener)
 {
     m_QuerySkuDetailsService.QueryAsyncSku(product, skuDetailsList =>
     {
         foreach (var skuDetails in skuDetailsList)
         {
             m_BillingClient.LaunchPriceChangeConfirmationFlow(skuDetails, new GooglePriceChangeConfirmationListener(onPriceChangedListener));
         }
     });
 }
Example #11
0
        public override void FinishTransaction(ProductDefinition product, string transactionId)
        {
            if (product == null || transactionId == null)
            {
                return;
            }

            if (product.type == ProductType.Consumable)
            {
                m_Bindings.FinishTransaction(product, transactionId);
            }
        }
 public void FinishTransaction(ProductDefinition productDefinition, string transactionID)
 {
     if (m_Bridge != null)
     {
         var finishTransactionMethod = UdpIapBridgeInterface.GetFinishTransactionMethod();
         finishTransactionMethod.Invoke(m_Bridge, new object[] { transactionID });
     }
     else
     {
         Debug.LogError("Cannot Complete transaction for UDP. Please make sure your UDP package is installed and up-to-date");
         throw new NotImplementedException();
     }
 }
        /// <summary>
        /// Decodes the list of json objects for a storename.
        /// </summary>
        /// <returns>Hashset of ProductDefinitions</returns>
        /// <param name="productsList">Products list.</param>
        /// <param name="storeName">Store name.</param>
        internal static List <ProductDefinition> DecodeJSON(this List <object> productsList, string storeName)
        {
            var result = new List <ProductDefinition>();

            try
            {
                foreach (object product in productsList)
                {
                    var    productDict = (Dictionary <string, object>)product;
                    object id, storeIDs, typeString;
                    productDict.TryGetValue("id", out id);
                    productDict.TryGetValue("store_ids", out storeIDs);
                    productDict.TryGetValue("type", out typeString);
                    var    idHash          = storeIDs as Dictionary <string, object>;
                    string storeSpecificId = (string)id;
                    if (idHash != null)
                    {
                        foreach (var storeInfo in idHash)
                        {
                            var storeKey   = storeInfo.Key.ToLower();
                            var storeValue = (string)storeInfo.Value;
                            if (!String.IsNullOrEmpty(storeValue) && storeName.ToLower() == storeKey)
                            {
                                storeSpecificId = storeValue;
                            }
                        }
                    }
                    else
                    {
                        // Handles scenario where developer creates a single storeSpecificID via ProductDefinition
                        // and through FakeStore within editor adds ProductDefinition to ConfigurationBuilder
                        object singleStoreSpecificID;
                        productDict.TryGetValue("storeSpecificId", out singleStoreSpecificID);
                        string generalStoreSpecificStringID = (string)singleStoreSpecificID;
                        if (generalStoreSpecificStringID != null)
                        {
                            storeSpecificId = generalStoreSpecificStringID;
                        }
                    }
                    var type       = (ProductType)Enum.Parse(typeof(ProductType), (string)typeString);
                    var definition = new ProductDefinition((string)id, storeSpecificId, type);
                    result.Add(definition);
                }
                return(result);
            }
            catch
            {
                return(null);
            }
        }
Example #14
0
        /// <summary>
        /// Called by our IStore when a purchase succeeds.
        /// </summary>
        public void OnPurchaseSucceeded(string id, string receipt, string transactionId)
        {
            var product = products.WithStoreSpecificID(id);

            if (null == product)
            {
                // If is possible for stores to tell us about products we have not yet
                // requested details of.
                // We should still tell the App in this scenario, albeit with incomplete information.
                var definition = new ProductDefinition(id, ProductType.NonConsumable);
                product = new Product(definition, new ProductMetadata());
            }
            UpdateProductReceipt(product, receipt, transactionId);
            ProcessPurchaseIfNew(product);
        }
        public ConfigurationBuilder AddProduct(string id, ProductType type, IDs storeIDs, IEnumerable <PayoutDefinition> payouts)
        {
            var specificId = id;

            // Extract our store specific ID if present, according to the current store.
            if (storeIDs != null)
            {
                specificId = storeIDs.SpecificIDForStore(factory.storeName, id);
            }
            var product = new ProductDefinition(id, specificId, type);

            product.SetPayouts(payouts);
            m_Products.Add(product);

            return(this);
        }
        public override bool Equals(object obj)
        {
            if (obj == null)
            {
                return(false);
            }

            ProductDefinition p = obj as ProductDefinition;

            if (p == null)
            {
                return(false);
            }

            return(id == p.id);
        }
 public void FinishTransaction(ProductDefinition product, string purchaseToken, Action <ProductDefinition, GooglePurchase, IGoogleBillingResult, string> onConsume, Action <ProductDefinition, GooglePurchase, IGoogleBillingResult> onAcknowledge)
 {
     m_GoogleQueryPurchasesService.QueryPurchases(purchases =>
     {
         foreach (var purchase in purchases.Where(PurchaseToFinishTransaction(product)))
         {
             if (product.type == ProductType.Consumable)
             {
                 m_BillingClient.ConsumeAsync(purchaseToken, product, purchase, onConsume);
             }
             else if (!purchase.IsAcknowledged())
             {
                 m_BillingClient.AcknowledgePurchase(purchaseToken, product, purchase, onAcknowledge);
             }
         }
     });
 }
        private static Dictionary <string, object> EncodeProductDef(ProductDefinition product)
        {
            var prod = new Dictionary <string, object>
            {
                { "id", product.id }, { "storeSpecificId", product.storeSpecificId }, { "type", product.type.ToString() }
            };

            bool enabled     = true;
            var  enabledProp = typeof(ProductDefinition).GetProperty("enabled");

            if (enabledProp != null)
            {
                try {
                    enabled = Convert.ToBoolean(enabledProp.GetValue(product, null));
                } catch {
                    enabled = true;
                }
            }
            prod.Add("enabled", enabled);

            var payoutsArray = new List <object>();
            var payoutsProp  = typeof(ProductDefinition).GetProperty("payouts");

            if (payoutsProp != null)
            {
                var   payoutsObject = payoutsProp.GetValue(product, null);
                Array payouts       = payoutsObject as Array;
                if (payouts != null)
                {
                    foreach (object payout in payouts)
                    {
                        var payoutDict = new Dictionary <string, object>();
                        var payoutType = payout.GetType();
                        payoutDict["t"]  = payoutType.GetField("typeString").GetValue(payout);
                        payoutDict["st"] = payoutType.GetField("subtype").GetValue(payout);
                        payoutDict["q"]  = payoutType.GetField("quantity").GetValue(payout);
                        payoutDict["d"]  = payoutType.GetField("data").GetValue(payout);
                        payoutsArray.Add(payoutDict);
                    }
                }
            }
            prod.Add("payouts", payoutsArray);

            return(prod);
        }
Example #19
0
        /// <summary>
        /// Called back by our IStore when it has fetched the latest product data.
        /// </summary>
        public void OnProductsRetrieved(List <ProductDescription> products)
        {
            var unknownProducts = new HashSet <Product>();

            foreach (var product in products)
            {
                var matchedProduct = this.products.WithStoreSpecificID(product.storeSpecificId);
                if (null == matchedProduct)
                {
                    var definition = new ProductDefinition(product.storeSpecificId,
                                                           product.storeSpecificId, product.type);
                    matchedProduct = new Product(definition, product.metadata);
                    unknownProducts.Add(matchedProduct);
                }
                matchedProduct.availableToPurchase = true;
                matchedProduct.metadata            = product.metadata;
                matchedProduct.transactionID       = product.transactionId;

                if (!string.IsNullOrEmpty(product.receipt))
                {
                    matchedProduct.receipt = FormatUnifiedReceipt(product.receipt, product.transactionId);
                }
            }

            if (unknownProducts.Count > 0)
            {
                this.products.AddProducts(unknownProducts);
            }

            // Fire our initialisation events if this is a first poll.
            CheckForInitialization();

            // Notify the application of any purchases it
            // has not yet processed.
            // Note that this must be done *after* initialisation, above.
            foreach (var product in this.products.set)
            {
                if (!string.IsNullOrEmpty(product.receipt) && !string.IsNullOrEmpty(product.transactionID))
                {
                    ProcessPurchaseIfNew(product);
                }
            }
        }
Example #20
0
 void OnQuerySkuDetailsResponse(List <AndroidJavaObject> skus, ProductDefinition productToBuy, Product oldProduct, int desiredProrationMode)
 {
     if (skus?.Count > 0)
     {
         AndroidJavaObject sku = skus[0];
         VerifyAndWarnIfMoreThanOneSku(skus, sku);
         AndroidJavaObject billingResult = m_BillingClient.LaunchBillingFlow(sku, oldProduct?.definition?.storeSpecificId, oldProduct?.transactionID, desiredProrationMode);
         HandleBillingFlowResult(new GoogleBillingResult(billingResult), sku);
     }
     else
     {
         m_GooglePurchaseCallback.OnPurchaseFailed(
             new PurchaseFailureDescription(
                 productToBuy.id,
                 PurchaseFailureReason.ProductUnavailable,
                 "SKU does not exist in the store."
                 )
             );
     }
 }
        void FakePurchase(ProductDefinition product, string developerPayload)
        {
            purchaseCalled = true;
            // Our billing systems should only keep track of non consumables.
            if (product.type != ProductType.Consumable)
            {
                m_PurchasedProducts.Add(product.storeSpecificId);
            }

            Action <bool, PurchaseFailureReason> handleAllowPurchase =
                (bool allow, PurchaseFailureReason failureReason) =>
            {
                if (allow)
                {
                    base.OnPurchaseSucceeded(product.storeSpecificId, "{ \"this\" : \"is a fake receipt\" }", Guid.NewGuid().ToString());
                }
                else
                {
                    if (failureReason == (PurchaseFailureReason)Enum.Parse(typeof(PurchaseFailureReason), "Unknown"))
                    {
                        failureReason = PurchaseFailureReason.UserCancelled;
                    }

                    PurchaseFailureDescription failureDescription =
                        new PurchaseFailureDescription(product.storeSpecificId, failureReason, "failed a fake store purchase");

                    base.OnPurchaseFailed(failureDescription);
                }
            };

            if (!(StartUI <PurchaseFailureReason> (product, DialogType.Purchase, handleAllowPurchase)))
            {
                // Default non-UI FakeStore purchase behavior is to succeed
                handleAllowPurchase(true, (PurchaseFailureReason)Enum.Parse(typeof(PurchaseFailureReason), "Unknown"));
            }
        }
Example #22
0
 public void OnConsume(ProductDefinition product, GooglePurchase googlePurchase, GoogleBillingResult billingResult, string purchaseToken)
 {
     HandleFinishTransaction(product, googlePurchase, billingResult, purchaseToken);
 }
 public override void FinishTransaction(ProductDefinition product, string transactionId)
 {
 }
Example #24
0
 public void Purchase(ProductDefinition product)
 {
     m_GooglePlayStoreService.Purchase(product);
 }
 public static string SerializeProductDef(ProductDefinition product)
 {
     return(MiniJson.JsonEncode(EncodeProductDef(product)));
 }
Example #26
0
        /// <summary>
        /// Parse product definitions from JSON, selecting store specific identifiers
        /// for the specified store name.
        /// </summary>
        internal static HashSet <ProductDefinition> ParseProductsFromJSON(string json, string storeName)
        {
            var result = new HashSet <ProductDefinition>();

            try
            {
                var    container = (Dictionary <string, object>)MiniJson.JsonDecode(json);
                object products;
                container.TryGetValue("products", out products);
                var productsList = products as List <object>;

                var snakeCaseStoreName = CamelCaseToSnakeCase(storeName);
                foreach (object product in productsList)
                {
                    var    productDict = (Dictionary <string, object>)product;
                    object id, storeIDs, typeString;
                    // Remove payouts and enabled references for 1.13.0.
                    //object enabled, payoutsJson;
                    productDict.TryGetValue("id", out id);
                    productDict.TryGetValue("store_ids", out storeIDs);
                    productDict.TryGetValue("type", out typeString);
                    // Remove payouts and enabled references for 1.13.0.
                    //productDict.TryGetValue("enabled", out enabled);
                    //productDict.TryGetValue("payouts", out payoutsJson);

                    var    idHash          = storeIDs as Dictionary <string, object>;
                    string storeSpecificId = (string)id;
                    if (null != idHash && idHash.ContainsKey(snakeCaseStoreName))
                    {
                        object storeId = null;
                        idHash.TryGetValue(snakeCaseStoreName, out storeId);
                        if (null != storeId)
                        {
                            storeSpecificId = (string)storeId;
                        }
                    }

                    var type = (ProductType)Enum.Parse(typeof(ProductType), (string)typeString);

                    // Remove payouts and enabled references for 1.13.0.
                    //bool enabledBool = true;
                    //if (enabled != null && (enabled is bool || enabled is Boolean)) {
                    //    enabledBool = (bool)enabled;
                    //}
                    //var definition = new ProductDefinition((string)id, storeSpecificId, type, enabledBool);
                    var definition = new ProductDefinition((string)id, storeSpecificId, type);

                    // Remove payouts and enabled references for 1.13.0.
                    //List<object> payoutsJsonArray = payoutsJson as List<object>;
                    //if (payoutsJsonArray != null) {
                    //    var payouts = new List<PayoutDefinition>();
                    //    foreach (object payoutJson in payoutsJsonArray) {
                    //        Dictionary<string, object> payoutJsonDict = payoutJson as Dictionary<string, object>;
                    //        object payoutTypeString, subtype, quantity, data;
                    //        payoutJsonDict.TryGetValue("t", out payoutTypeString);
                    //        payoutJsonDict.TryGetValue("st", out subtype);
                    //        payoutJsonDict.TryGetValue("q", out quantity);
                    //        payoutJsonDict.TryGetValue("d", out data);
                    //
                    //        double q = quantity == null ? 0 : Convert.ToDouble (quantity);
                    //
                    //        payouts.Add(new PayoutDefinition((string)payoutTypeString, (string)subtype, q, (string)data));
                    //    }
                    //    definition.SetPayouts(payouts);
                    //}

                    result.Add(definition);
                }
                return(result);
            }
            catch (Exception e)
            {
                throw new SerializationException("Error parsing JSON", e);
            }
        }
Example #27
0
 /// <summary>
 /// Call the Google Play Store to consume a product.
 /// </summary>
 /// <param name="product">Product to consume</param>
 /// <param name="transactionId">Transaction / order id</param>
 public override void FinishTransaction(ProductDefinition product, string transactionId)
 {
     m_FinishTransactionService.FinishTransaction(product, transactionId);
 }
Example #28
0
 private string CreatePurchaseQuestion(ProductDefinition definition)
 {
     return("Do you want to Purchase " + definition.id + "?" + EnvironmentDescriptionPostfix);
 }
Example #29
0
 public void FinishTransaction(ProductDefinition product, string purchaseToken)
 {
     m_GooglePlayStoreService.FinishTransaction(product, purchaseToken, OnConsume, OnAcknowledge);
 }
Example #30
0
 public void OnAcknowledge(ProductDefinition product, GooglePurchase googlePurchase, GoogleBillingResult billingResult)
 {
     HandleFinishTransaction(product, googlePurchase, billingResult, googlePurchase.purchaseToken);
 }