123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276 |
- using System;
- using System.Collections.Generic;
- using System.Reflection;
- using UnityEngine.Purchasing.Extension;
-
- namespace UnityEngine.Purchasing
- {
- static class SerializationExtensions
- {
- public static string TryGetString(this Dictionary<string, object> dic, string key)
- {
- if (dic.ContainsKey(key))
- {
- if (dic[key] != null)
- {
- return dic[key].ToString();
- }
- }
-
- return null;
- }
- }
-
- internal class JSONSerializer
- {
- public static string SerializeProductDef(ProductDefinition product)
- {
- return MiniJson.JsonEncode(EncodeProductDef(product));
- }
-
- public static string SerializeProductDefs(IEnumerable<ProductDefinition> products)
- {
- var result = new List<object>();
- foreach (var product in products)
- {
- result.Add(EncodeProductDef(product));
- }
-
- return MiniJson.JsonEncode(result);
- }
-
- public static string SerializeProductDescs(ProductDescription product)
- {
- return MiniJson.JsonEncode(EncodeProductDesc(product));
- }
-
- public static string SerializeProductDescs(IEnumerable<ProductDescription> products)
- {
- var result = new List<object>();
- foreach (var product in products)
- {
- result.Add(EncodeProductDesc(product));
- }
-
- return MiniJson.JsonEncode(result);
- }
-
- public static Dictionary<string, string> DeserializeSubscriptionDescriptions(string json)
- {
- var objects = (List<object>)MiniJson.JsonDecode(json);
- var result = new Dictionary<string, string>();
- foreach (Dictionary<string, object> obj in objects)
- {
- var subscription = new Dictionary<string, string>();
- if (obj.TryGetValue("metadata", out var metadata))
- {
- var metadataDict = (Dictionary<string, object>)metadata;
- subscription["introductoryPrice"] = metadataDict.TryGetString("introductoryPrice");
- subscription["introductoryPriceLocale"] = metadataDict.TryGetString("introductoryPriceLocale");
- subscription["introductoryPriceNumberOfPeriods"] = metadataDict.TryGetString("introductoryPriceNumberOfPeriods");
- subscription["numberOfUnits"] = metadataDict.TryGetString("numberOfUnits");
- subscription["unit"] = metadataDict.TryGetString("unit");
-
- // this is a double check for Apple side's bug
- if (!string.IsNullOrEmpty(subscription["numberOfUnits"]) && string.IsNullOrEmpty(subscription["unit"]))
- {
- subscription["unit"] = "0";
- }
- }
- else
- {
- Debug.LogWarning("metadata key not found in subscription description json");
- }
-
- if (obj.TryGetValue("storeSpecificId", out var id))
- {
- var idStr = (string)id;
- result.Add(idStr, MiniJson.JsonEncode(subscription));
- }
- else
- {
- Debug.LogWarning("storeSpecificId key not found in subscription description json");
- }
- }
-
- return result;
- }
-
- public static Dictionary<string, string> DeserializeProductDetails(string json)
- {
- var objects = (List<object>)MiniJson.JsonDecode(json);
- var result = new Dictionary<string, string>();
- foreach (Dictionary<string, object> obj in objects)
- {
- var details = new Dictionary<string, string>();
- if (obj.TryGetValue("metadata", out var metadata))
- {
- var metadataStr = (Dictionary<string, object>)metadata;
- details["subscriptionNumberOfUnits"] = metadataStr.TryGetString("subscriptionNumberOfUnits");
- details["subscriptionPeriodUnit"] = metadataStr.TryGetString("subscriptionPeriodUnit");
- details["localizedPrice"] = metadataStr.TryGetString("localizedPrice");
- details["isoCurrencyCode"] = metadataStr.TryGetString("isoCurrencyCode");
- details["localizedPriceString"] = metadataStr.TryGetString("localizedPriceString");
- details["localizedTitle"] = metadataStr.TryGetString("localizedTitle");
- details["localizedDescription"] = metadataStr.TryGetString("localizedDescription");
- details["introductoryPrice"] = metadataStr.TryGetString("introductoryPrice");
- details["introductoryPriceLocale"] = metadataStr.TryGetString("introductoryPriceLocale");
- details["introductoryPriceNumberOfPeriods"] = metadataStr.TryGetString("introductoryPriceNumberOfPeriods");
- details["numberOfUnits"] = metadataStr.TryGetString("numberOfUnits");
- details["unit"] = metadataStr.TryGetString("unit");
-
- // this is a double check for Apple side's bug
- if (!string.IsNullOrEmpty(details["subscriptionNumberOfUnits"]) && string.IsNullOrEmpty(details["subscriptionPeriodUnit"]))
- {
- details["subscriptionPeriodUnit"] = "0";
- }
-
- // this is a double check for Apple side's bug
- if (!string.IsNullOrEmpty(details["numberOfUnits"]) && string.IsNullOrEmpty(details["unit"]))
- {
- details["unit"] = "0";
- }
- }
- else
- {
- Debug.LogWarning("metadata key not found in product details json");
- }
-
- if (obj.TryGetValue("storeSpecificId", out var id))
- {
- var idStr = (string)id;
- result.Add(idStr, MiniJson.JsonEncode(details));
- }
- else
- {
- Debug.LogWarning("storeSpecificId key not found in product details json");
- }
- }
-
- return result;
- }
-
- public static PurchaseFailureDescription DeserializeFailureReason(string json)
- {
- var dic = (Dictionary<string, object>)MiniJson.JsonDecode(json);
- var reason = PurchaseFailureReason.Unknown;
-
- if (dic.TryGetValue("reason", out var reasonStr))
- {
- if (Enum.IsDefined(typeof(PurchaseFailureReason), (string)reasonStr))
- {
- reason = (PurchaseFailureReason)Enum.Parse(typeof(PurchaseFailureReason), (string)reasonStr);
- }
-
- if (dic.TryGetValue("productId", out var productId))
- {
- return new PurchaseFailureDescription((string)productId, reason, BuildPurchaseFailureDescriptionMessage(dic));
- }
- }
- else
- {
- Debug.LogWarning("Reason key not found in purchase failure json: " + json);
- }
-
- return new PurchaseFailureDescription("Unknown ProductID", reason, BuildPurchaseFailureDescriptionMessage(dic));
- }
-
- static string BuildPurchaseFailureDescriptionMessage(Dictionary<string, object> dic)
- {
- var message = dic.TryGetString("message");
- var storeSpecificErrorCode = dic.TryGetString("storeSpecificErrorCode");
-
- if (message == null && storeSpecificErrorCode == null)
- {
- return null;
- }
-
- if (storeSpecificErrorCode != null)
- {
- storeSpecificErrorCode = " storeSpecificErrorCode: " + storeSpecificErrorCode;
- }
-
- return message + storeSpecificErrorCode;
- }
-
- private static Dictionary<string, object> EncodeProductDef(ProductDefinition product)
- {
- var prod = new Dictionary<string, object> { { "id", product.id }, { "storeSpecificId", product.storeSpecificId }, { "type", product.type.ToString() } };
-
- var 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);
- var payouts = payoutsObject as Array;
- if (payouts != null)
- {
- foreach (var 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;
- }
-
- private static Dictionary<string, object> EncodeProductDesc(ProductDescription product)
- {
- var prod = new Dictionary<string, object> { { "storeSpecificId", product.storeSpecificId } };
-
- // ProductDescription.type field available in Unity 5.4+. Access by reflection here.
- var pdClassType = typeof(ProductDescription);
- var pdClassFieldType = pdClassType.GetField("type");
- if (pdClassFieldType != null)
- {
- var typeValue = pdClassFieldType.GetValue(product);
- prod.Add("type", typeValue.ToString());
- }
-
- prod.Add("metadata", EncodeProductMeta(product.metadata));
- prod.Add("receipt", product.receipt);
- prod.Add("transactionId", product.transactionId);
-
- return prod;
- }
-
- private static Dictionary<string, object> EncodeProductMeta(ProductMetadata product)
- {
- var prod = new Dictionary<string, object>
- {
- { "localizedPriceString", product.localizedPriceString },
- { "localizedTitle", product.localizedTitle },
- { "localizedDescription", product.localizedDescription },
- { "isoCurrencyCode", product.isoCurrencyCode },
- { "localizedPrice", Convert.ToDouble(product.localizedPrice) }
- };
-
- return prod;
- }
- }
- }
|