using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using UnityEngine.Purchasing.Extension; using UnityEngine.Purchasing.MiniJSON; namespace UnityEngine.Purchasing { internal class UDPBindings : INativeUDPStore { private readonly object m_Bridge; private Action m_RetrieveProductsCallbackCache; public UDPBindings() { var udpIapBridge = UdpIapBridgeInterface.GetClassType(); if (udpIapBridge != null) { m_Bridge = Activator.CreateInstance(udpIapBridge); } else { Debug.LogError("Failed to access UDP. Please make sure your UDP package is installed and up-to-date"); throw new NotImplementedException(); } } public void Initialize(Action callback) { if (m_Bridge != null) { var initMethod = UdpIapBridgeInterface.GetInitMethod(); initMethod.Invoke(m_Bridge, new object[] { callback }); } else { Debug.LogError("Cannot Initialize UDP store module. Please make sure your UDP package is installed and up-to-date"); throw new NotImplementedException(); } } public void Purchase(string productId, Action callback, string developerPayload = null) { if (m_Bridge != null) { var purchaseMethod = UdpIapBridgeInterface.GetPurchaseMethod(); purchaseMethod.Invoke(m_Bridge, new object[] { productId, callback, developerPayload }); } else { Debug.LogError("Cannot Purchase via UDP. Please make sure your UDP package is installed and up-to-date"); throw new NotImplementedException(); } } public void RetrieveProducts(ReadOnlyCollection products, Action callback) { if (m_Bridge != null) { if (m_RetrieveProductsCallbackCache != null) { callback(false, /*lang=json,strict*/ "{ \"error\" : \"already retrieving products\" }"); return; } m_RetrieveProductsCallbackCache = callback; Action retrieveCallback = OnInventoryQueried; var retrieveProductsMethod = UdpIapBridgeInterface.GetRetrieveProductsMethod(); var ids = new List(); foreach (var product in products) { ids.Add(product.storeSpecificId); } retrieveProductsMethod.Invoke(m_Bridge, new object[] { new ReadOnlyCollection(ids), retrieveCallback }); } else { Debug.LogError("Cannot Retrieve Products from UDP. Please make sure your UDP package is installed and up-to-date"); throw new NotImplementedException(); } } 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(); } } private void OnInventoryQueried(bool success, object payload) { var actualSuccess = success; string parsedPayload; var inventoryType = InventoryInterface.GetClassType(); if (success) { if (inventoryType != null) { var inventory = payload; if (inventory != null && inventory.GetType() == inventoryType) { var fetchedProducts = new HashSet(); var getProductList = InventoryInterface.GetProductListMethod(); var products = (IEnumerable)getProductList.Invoke(inventory, null); var productList = products.Cast().ToList(); foreach (var productInfo in productList) { var priceProp = ProductInfoInterface.GetPriceProp(); var titleProp = ProductInfoInterface.GetTitleProp(); var descProp = ProductInfoInterface.GetDescriptionProp(); var currencyProp = ProductInfoInterface.GetCurrencyProp(); var microsProp = ProductInfoInterface.GetPriceAmountMicrosProp(); var metadata = new ProductMetadata( (string)priceProp.GetValue(productInfo, null), (string)titleProp.GetValue(productInfo, null), (string)descProp.GetValue(productInfo, null), (string)currencyProp.GetValue(productInfo, null), Convert.ToDecimal((long)microsProp.GetValue(productInfo, null)) / 1000000); var idProp = ProductInfoInterface.GetProductIdProp(); var productId = (string)idProp.GetValue(productInfo, null); var desc = new ProductDescription(productId, metadata); var hasPurchase = InventoryInterface.HasPurchaseMethod(); if ((bool)hasPurchase.Invoke(inventory, new object[] { productId })) { var getPurchaseInfo = InventoryInterface.GetPurchaseInfoMethod(); var purchase = getPurchaseInfo.Invoke(inventory, new object[] { productId }); var dic = StringPropertyToDictionary(purchase); var transactionId = dic["GameOrderId"]; var storeSpecificId = dic["ProductId"]; if (!string.IsNullOrEmpty(transactionId)) { dic["transactionId"] = transactionId; } if (!string.IsNullOrEmpty(storeSpecificId)) { dic["storeSpecificId"] = storeSpecificId; } desc = new ProductDescription(productId, metadata, dic.toJson(), transactionId); } fetchedProducts.Add(desc); } parsedPayload = JSONSerializer.SerializeProductDescs(fetchedProducts); } else { actualSuccess = false; parsedPayload = /*lang=json,strict*/ "{ \"error\" : \"Cannot load inventory from UDP. Please make sure your UDP package is installed and up-to-date\" }"; } } else { actualSuccess = false; parsedPayload = /*lang=json,strict*/ "{ \"error\" : \"Cannot parse inventory type for UDP. Please make sure your UDP package is installed and up-to-date\" }"; } } else { parsedPayload = (string)payload; } m_RetrieveProductsCallbackCache(actualSuccess, parsedPayload); m_RetrieveProductsCallbackCache = null; } #region INativeStore - Unused public void RetrieveProducts(string json) { throw new NotImplementedException(); } public void Purchase(string productJSON, string developerPayload) { throw new NotImplementedException(); } public void FinishTransaction(string productJSON, string transactionID) { throw new NotImplementedException(); } #endregion #region helper functions /// /// Put the string property of into a dictionary if the property is not empty string. /// /// Model object, namely or /// internal static Dictionary StringPropertyToDictionary(object info) { var dictionary = new Dictionary(); if (info == null) { return dictionary; } var properties = info.GetType().GetProperties(); foreach (var property in properties) { if (property.PropertyType == typeof(string)) { var value = (string)property.GetValue(info, null); if (!string.IsNullOrEmpty(value)) { dictionary[property.Name] = value; } } } return dictionary; } #endregion } }