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); }
internal GoogleConsumeResponseListener(ProductDefinition product, GooglePurchase purchase, Action <ProductDefinition, GooglePurchase, IGoogleBillingResult, string> onConsumeResponseAction) : base(k_AndroidConsumeResponseListenerClassName) { m_Product = product; m_Purchase = purchase; m_OnConsumeResponse = onConsumeResponseAction; }
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}" ) ); } } }
/// <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(); }
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); }
void CallPurchaseSucceededUpdateReceipt(ProductDefinition product, GooglePurchase googlePurchase, string purchaseToken) { m_StoreCallback?.OnPurchaseSucceeded( product.storeSpecificId, googlePurchase.receipt, purchaseToken ); }
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)); } }); }
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); } }
/// <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); }
/// <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); } } }
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")); } }
public void OnConsume(ProductDefinition product, GooglePurchase googlePurchase, GoogleBillingResult billingResult, string purchaseToken) { HandleFinishTransaction(product, googlePurchase, billingResult, purchaseToken); }
public override void FinishTransaction(ProductDefinition product, string transactionId) { }
public void Purchase(ProductDefinition product) { m_GooglePlayStoreService.Purchase(product); }
public static string SerializeProductDef(ProductDefinition product) { return(MiniJson.JsonEncode(EncodeProductDef(product))); }
/// <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); } }
/// <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); }
private string CreatePurchaseQuestion(ProductDefinition definition) { return("Do you want to Purchase " + definition.id + "?" + EnvironmentDescriptionPostfix); }
public void FinishTransaction(ProductDefinition product, string purchaseToken) { m_GooglePlayStoreService.FinishTransaction(product, purchaseToken, OnConsume, OnAcknowledge); }
public void OnAcknowledge(ProductDefinition product, GooglePurchase googlePurchase, GoogleBillingResult billingResult) { HandleFinishTransaction(product, googlePurchase, billingResult, googlePurchase.purchaseToken); }