using System; using System.Collections; using System.Collections.Generic; using SUISS.Storage; using UnityEngine; using UnityEngine.Purchasing; namespace CIG { public class IAPCatalog where T : StoreProduct { public IAPCatalog(CIGWebService webService, Func, T> storeProductFactory) { this._webService = webService; this._storeProductFactory = storeProductFactory; this.LoadFromStorage(); this.LoadDefaultPricePoints(); } private static string DEFAULT_PRICEPOINTS_ASSET_NAME { get { return "defaultpricepoints-android"; } } public IEnumerator UpdatePricePoints() { if (this.AreCachedPricePointsOutDated() && this._webService != null) { yield return this._webService.WWWWithTimeout(this._webService.PricePoints(), delegate (CIGWebService.WWWResponse response) { if (!response.TimedOut) { if (string.IsNullOrEmpty(response.Error) && !string.IsNullOrEmpty(response.Text)) { List> productMetadata; int num; if (this.ValidatePricePoints(response.Text, out productMetadata, out num)) { this.UpdateRemoteProducts(productMetadata); } else { UnityEngine.Debug.LogError("Invalid pricepoints received. - Not using them."); } } else { UnityEngine.Debug.LogErrorFormat("Error downloading pricepoints. {0}", new object[] { response.Text }); } } else { UnityEngine.Debug.LogErrorFormat("Error downloading pricepoints: Timedout", new object[0]); } }, 5f); } yield break; } public void UpdateProducts(Product[] products) { int num = products.Length; for (int i = 0; i < num; i++) { Product product = products[i]; T t = this.FindProduct(product.definition.id); if (t != null) { Dictionary dictionary = t.Serialize(); dictionary["ProductTitle"] = product.metadata.localizedTitle; dictionary["ProductDescription"] = product.metadata.localizedDescription; dictionary["ProductCurrencyCode"] = product.metadata.isoCurrencyCode; dictionary["ProductFormattedPrice"] = "99"; dictionary["ProductPrice"] = product.metadata.localizedPrice; this.AddOrUpdateProduct(dictionary); } } this.SaveToStorage(); } public T FindProduct(string identifier) { return this._products.Find((T x) => x.Identifier == identifier); } public T FindProduct(Predicate predicate) { T[] availableProducts = this.GetAvailableProducts(predicate); return (availableProducts.Length <= 0) ? ((T)((object)null)) : availableProducts[0]; } public T[] GetAvailableProducts(Predicate predicate) { List list = new List(); int count = this._products.Count; for (int i = 0; i < count; i++) { T t = this._products[i]; if (t.Available && predicate(t)) { list.Add(t); } } list.Sort(); return list.ToArray(); } public T[] AvailableProducts { get { return this._products.FindAll((T x) => x.Available).ToArray(); } } private T AddOrUpdateProduct(Dictionary productMetadata) { T t = this.FindProduct((string)productMetadata["ProductIdentifier"]); if (t != null) { t.Update(productMetadata); } else { t = this._storeProductFactory(productMetadata); this._products.Add(t); } return t; } private void LoadDefaultPricePoints() { int num = -1; object obj; if (this.storage.TryGetValue("DefaultPricePointsVersionKey", out obj) && obj is int) { num = (int)obj; } TextAsset textAsset = Resources.Load(IAPCatalog.DEFAULT_PRICEPOINTS_ASSET_NAME); if (textAsset == null) { UnityEngine.Debug.LogErrorFormat("Unable to open TextAsset {0}.", new object[] { IAPCatalog.DEFAULT_PRICEPOINTS_ASSET_NAME }); return; } List> productMetadata; int num2; if (!this.ValidatePricePoints(textAsset.text, out productMetadata, out num2)) { UnityEngine.Debug.LogWarningFormat("Invalid default pricepoints. - Not using them.", new object[0]); return; } if (num != -1 && num2 <= num) { return; } this.UpdateProducts(productMetadata); if (!this.storage.ContainsKey("DefaultPricePointsVersionKey")) { this.storage.Add("DefaultPricePointsVersionKey", -1); } this.storage["DefaultPricePointsVersionKey"] = num2; this.SaveToStorage(); } private void UpdateRemoteProducts(List> productMetadata) { this.UpdateProducts(productMetadata); if (!this.storage.ContainsKey("GameVersionKey")) { this.storage.Add("GameVersionKey", string.Empty); } if (!this.storage.ContainsKey("CacheDateTimeKey")) { this.storage.Add("CacheDateTimeKey", 0L); } this.storage["GameVersionKey"] = "3.0.6"; this.storage["CacheDateTimeKey"] = DateTime.UtcNow.ToBinary(); this.SaveToStorage(); } private void UpdateProducts(List> productMetadata) { int count = this._products.Count; for (int i = 0; i < count; i++) { T t = this._products[i]; t.Available = false; } count = productMetadata.Count; for (int j = 0; j < count; j++) { this.AddOrUpdateProduct(productMetadata[j]); } } private bool AreCachedPricePointsOutDated() { object obj; if (!this.storage.TryGetValue("GameVersionKey", out obj)) { return true; } if (string.IsNullOrEmpty(obj as string)) { return true; } if ((string)obj != "3.0.6") { return true; } if (!this.storage.TryGetValue("CacheDateTimeKey", out obj)) { return true; } if (!(obj is long)) { return true; } DateTime d = DateTime.FromBinary((long)obj); return DateTime.UtcNow - d > IAPCatalog.PRICEPOINTS_EXPIRATIONTIME; } private bool ValidatePricePoints(string pricepointsRawText, out List> productMetadata, out int version) { productMetadata = IAPCatalog.ParsePricePoints(pricepointsRawText, out version); if (productMetadata.Count == 0) { return false; } Dictionary dictionary = productMetadata[0]; return dictionary.ContainsKey("ProductIdentifier") && dictionary.ContainsKey("ProductPrice") && dictionary.ContainsKey("CustomProperties"); } private static List> ParsePricePoints(string pricePoints, out int version) { version = -1; List> list = new List>(); if (string.IsNullOrEmpty(pricePoints)) { return list; } Dictionary dictionary = new Dictionary(); foreach (string text in pricePoints.Split(new char[] { '\n' })) { int num = text.IndexOf('='); if (num >= 0) { string text2 = text.Substring(0, num).Trim(); string value = text.Substring(num + 1).Trim(); if (dictionary.ContainsKey(text2)) { UnityEngine.Debug.LogWarningFormat("Result dictionary already contains key '{0}'", new object[] { text2 }); } dictionary[text2] = value; } } string objA = null; foreach (KeyValuePair keyValuePair in dictionary) { if (keyValuePair.Key == "version") { if (!int.TryParse(keyValuePair.Value, out version)) { UnityEngine.Debug.LogWarningFormat("Failed to parse pricepoints version '{0}' to int.", new object[] { keyValuePair.Value }); } } else { int num2 = keyValuePair.Key.LastIndexOf('.'); if (num2 >= 0) { string text3 = keyValuePair.Key.Substring(0, num2); string text4 = keyValuePair.Key.Substring(num2 + 1, keyValuePair.Key.Length - num2 - 1); Dictionary dictionary2; Dictionary dictionary3; if (!object.Equals(objA, text3)) { dictionary2 = new Dictionary(); dictionary3 = new Dictionary(); dictionary2.Add("CustomProperties", dictionary3); list.Add(dictionary2); objA = text3; } else { dictionary2 = list[list.Count - 1]; dictionary3 = (Dictionary)dictionary2["CustomProperties"]; } if (text4.Equals("name")) { dictionary2["ProductIdentifier"] = keyValuePair.Value; } else if (text4.Equals("dollar")) { decimal num3; if (decimal.TryParse(keyValuePair.Value, out num3)) { dictionary2["ProductPrice"] = num3; dictionary2["ProductDollarPrice"] = num3; dictionary2["ProductFormattedPrice"] = num3.ToString("0.00") + "元";//TODODO 价格在defaultpricepoints-android这个文件里 dictionary2["ProductCurrencyCode"] = "USD"; } } else if (text4.Equals("euro")) { decimal num4; if (decimal.TryParse(keyValuePair.Value, out num4)) { dictionary2["ProductPrice"] = num4; dictionary2["ProductEuroPrice"] = num4; dictionary2["ProductFormattedPrice"] = num4.ToString("0.00") + "元";//TODODO 价格在defaultpricepoints-android这个文件里 dictionary2["ProductCurrencyCode"] = "EUR"; } } else if (text4.Equals("description")) { dictionary2["ProductDescription"] = keyValuePair.Value; } else if (text4.Equals("available")) { bool flag; if (bool.TryParse(keyValuePair.Value, out flag)) { dictionary2["Available"] = flag; } } else { dictionary3.Add(text4, keyValuePair.Value); } } } } return list; } private void SaveToStorage() { List list = new List(); for (int i = 0; i < this._products.Count; i++) { List list2 = list; T t = this._products[i]; list2.Add(t.Serialize()); } if (!this.storage.ContainsKey("StoreProductsKey")) { this.storage.Add("StoreProductsKey", list); } else { this.storage["StoreProductsKey"] = list; } Storage.SaveLifecycle(StorageLifecycle.Purchases, false); } private void LoadFromStorage() { if (this.storage.ContainsKey("StoreProductsKey")) { List list = (List)this.storage["StoreProductsKey"]; for (int i = 0; i < list.Count; i++) { this.AddOrUpdateProduct((Dictionary)list[i]); } } } private Dictionary storage { get { return Storage.Get(StorageLifecycle.Purchases).GetDictionary("IAPCatalogStorage"); } } private const string STORE_PRODUCTS_KEY = "StoreProductsKey"; private const string GAME_VERSION_KEY = "GameVersionKey"; private const string CACHE_DATETIME_KEY = "CacheDateTimeKey"; private const string DEFAULT_PRICEPOINTS_VERSION_KEY = "DefaultPricePointsVersionKey"; private const StorageLifecycle IAPCATALOG_LIFECYCLE = StorageLifecycle.Purchases; private const string IAPCATALOG_KEY = "IAPCatalogStorage"; private static readonly TimeSpan PRICEPOINTS_EXPIRATIONTIME = new TimeSpan(1, 0, 0, 0); private const string PRICE_POINTS_VERSION_KEY = "version"; private Func, T> _storeProductFactory; private CIGWebService _webService; private List _products = new List(); } }