Nessuna descrizione
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

JSONSerializer.cs 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Reflection;
  4. using UnityEngine.Purchasing.Extension;
  5. namespace UnityEngine.Purchasing
  6. {
  7. static class SerializationExtensions
  8. {
  9. public static string TryGetString(this Dictionary<string, object> dic, string key)
  10. {
  11. if (dic.ContainsKey(key))
  12. {
  13. if (dic[key] != null)
  14. {
  15. return dic[key].ToString();
  16. }
  17. }
  18. return null;
  19. }
  20. }
  21. internal class JSONSerializer
  22. {
  23. public static string SerializeProductDef(ProductDefinition product)
  24. {
  25. return MiniJson.JsonEncode(EncodeProductDef(product));
  26. }
  27. public static string SerializeProductDefs(IEnumerable<ProductDefinition> products)
  28. {
  29. var result = new List<object>();
  30. foreach (var product in products)
  31. {
  32. result.Add(EncodeProductDef(product));
  33. }
  34. return MiniJson.JsonEncode(result);
  35. }
  36. public static string SerializeProductDescs(ProductDescription product)
  37. {
  38. return MiniJson.JsonEncode(EncodeProductDesc(product));
  39. }
  40. public static string SerializeProductDescs(IEnumerable<ProductDescription> products)
  41. {
  42. var result = new List<object>();
  43. foreach (var product in products)
  44. {
  45. result.Add(EncodeProductDesc(product));
  46. }
  47. return MiniJson.JsonEncode(result);
  48. }
  49. public static Dictionary<string, string> DeserializeSubscriptionDescriptions(string json)
  50. {
  51. var objects = (List<object>)MiniJson.JsonDecode(json);
  52. var result = new Dictionary<string, string>();
  53. foreach (Dictionary<string, object> obj in objects)
  54. {
  55. var subscription = new Dictionary<string, string>();
  56. if (obj.TryGetValue("metadata", out var metadata))
  57. {
  58. var metadataDict = (Dictionary<string, object>)metadata;
  59. subscription["introductoryPrice"] = metadataDict.TryGetString("introductoryPrice");
  60. subscription["introductoryPriceLocale"] = metadataDict.TryGetString("introductoryPriceLocale");
  61. subscription["introductoryPriceNumberOfPeriods"] = metadataDict.TryGetString("introductoryPriceNumberOfPeriods");
  62. subscription["numberOfUnits"] = metadataDict.TryGetString("numberOfUnits");
  63. subscription["unit"] = metadataDict.TryGetString("unit");
  64. // this is a double check for Apple side's bug
  65. if (!string.IsNullOrEmpty(subscription["numberOfUnits"]) && string.IsNullOrEmpty(subscription["unit"]))
  66. {
  67. subscription["unit"] = "0";
  68. }
  69. }
  70. else
  71. {
  72. Debug.LogWarning("metadata key not found in subscription description json");
  73. }
  74. if (obj.TryGetValue("storeSpecificId", out var id))
  75. {
  76. var idStr = (string)id;
  77. result.Add(idStr, MiniJson.JsonEncode(subscription));
  78. }
  79. else
  80. {
  81. Debug.LogWarning("storeSpecificId key not found in subscription description json");
  82. }
  83. }
  84. return result;
  85. }
  86. public static Dictionary<string, string> DeserializeProductDetails(string json)
  87. {
  88. var objects = (List<object>)MiniJson.JsonDecode(json);
  89. var result = new Dictionary<string, string>();
  90. foreach (Dictionary<string, object> obj in objects)
  91. {
  92. var details = new Dictionary<string, string>();
  93. if (obj.TryGetValue("metadata", out var metadata))
  94. {
  95. var metadataStr = (Dictionary<string, object>)metadata;
  96. details["subscriptionNumberOfUnits"] = metadataStr.TryGetString("subscriptionNumberOfUnits");
  97. details["subscriptionPeriodUnit"] = metadataStr.TryGetString("subscriptionPeriodUnit");
  98. details["localizedPrice"] = metadataStr.TryGetString("localizedPrice");
  99. details["isoCurrencyCode"] = metadataStr.TryGetString("isoCurrencyCode");
  100. details["localizedPriceString"] = metadataStr.TryGetString("localizedPriceString");
  101. details["localizedTitle"] = metadataStr.TryGetString("localizedTitle");
  102. details["localizedDescription"] = metadataStr.TryGetString("localizedDescription");
  103. details["introductoryPrice"] = metadataStr.TryGetString("introductoryPrice");
  104. details["introductoryPriceLocale"] = metadataStr.TryGetString("introductoryPriceLocale");
  105. details["introductoryPriceNumberOfPeriods"] = metadataStr.TryGetString("introductoryPriceNumberOfPeriods");
  106. details["numberOfUnits"] = metadataStr.TryGetString("numberOfUnits");
  107. details["unit"] = metadataStr.TryGetString("unit");
  108. // this is a double check for Apple side's bug
  109. if (!string.IsNullOrEmpty(details["subscriptionNumberOfUnits"]) && string.IsNullOrEmpty(details["subscriptionPeriodUnit"]))
  110. {
  111. details["subscriptionPeriodUnit"] = "0";
  112. }
  113. // this is a double check for Apple side's bug
  114. if (!string.IsNullOrEmpty(details["numberOfUnits"]) && string.IsNullOrEmpty(details["unit"]))
  115. {
  116. details["unit"] = "0";
  117. }
  118. }
  119. else
  120. {
  121. Debug.LogWarning("metadata key not found in product details json");
  122. }
  123. if (obj.TryGetValue("storeSpecificId", out var id))
  124. {
  125. var idStr = (string)id;
  126. result.Add(idStr, MiniJson.JsonEncode(details));
  127. }
  128. else
  129. {
  130. Debug.LogWarning("storeSpecificId key not found in product details json");
  131. }
  132. }
  133. return result;
  134. }
  135. public static PurchaseFailureDescription DeserializeFailureReason(string json)
  136. {
  137. var dic = (Dictionary<string, object>)MiniJson.JsonDecode(json);
  138. var reason = PurchaseFailureReason.Unknown;
  139. if (dic.TryGetValue("reason", out var reasonStr))
  140. {
  141. if (Enum.IsDefined(typeof(PurchaseFailureReason), (string)reasonStr))
  142. {
  143. reason = (PurchaseFailureReason)Enum.Parse(typeof(PurchaseFailureReason), (string)reasonStr);
  144. }
  145. if (dic.TryGetValue("productId", out var productId))
  146. {
  147. return new PurchaseFailureDescription((string)productId, reason, BuildPurchaseFailureDescriptionMessage(dic));
  148. }
  149. }
  150. else
  151. {
  152. Debug.LogWarning("Reason key not found in purchase failure json: " + json);
  153. }
  154. return new PurchaseFailureDescription("Unknown ProductID", reason, BuildPurchaseFailureDescriptionMessage(dic));
  155. }
  156. static string BuildPurchaseFailureDescriptionMessage(Dictionary<string, object> dic)
  157. {
  158. var message = dic.TryGetString("message");
  159. var storeSpecificErrorCode = dic.TryGetString("storeSpecificErrorCode");
  160. if (message == null && storeSpecificErrorCode == null)
  161. {
  162. return null;
  163. }
  164. if (storeSpecificErrorCode != null)
  165. {
  166. storeSpecificErrorCode = " storeSpecificErrorCode: " + storeSpecificErrorCode;
  167. }
  168. return message + storeSpecificErrorCode;
  169. }
  170. private static Dictionary<string, object> EncodeProductDef(ProductDefinition product)
  171. {
  172. var prod = new Dictionary<string, object> { { "id", product.id }, { "storeSpecificId", product.storeSpecificId }, { "type", product.type.ToString() } };
  173. var enabled = true;
  174. var enabledProp = typeof(ProductDefinition).GetProperty("enabled");
  175. if (enabledProp != null)
  176. {
  177. try
  178. {
  179. enabled = Convert.ToBoolean(enabledProp.GetValue(product, null));
  180. }
  181. catch
  182. {
  183. enabled = true;
  184. }
  185. }
  186. prod.Add("enabled", enabled);
  187. var payoutsArray = new List<object>();
  188. var payoutsProp = typeof(ProductDefinition).GetProperty("payouts");
  189. if (payoutsProp != null)
  190. {
  191. var payoutsObject = payoutsProp.GetValue(product, null);
  192. var payouts = payoutsObject as Array;
  193. if (payouts != null)
  194. {
  195. foreach (var payout in payouts)
  196. {
  197. var payoutDict = new Dictionary<string, object>();
  198. var payoutType = payout.GetType();
  199. payoutDict["t"] = payoutType.GetField("typeString").GetValue(payout);
  200. payoutDict["st"] = payoutType.GetField("subtype").GetValue(payout);
  201. payoutDict["q"] = payoutType.GetField("quantity").GetValue(payout);
  202. payoutDict["d"] = payoutType.GetField("data").GetValue(payout);
  203. payoutsArray.Add(payoutDict);
  204. }
  205. }
  206. }
  207. prod.Add("payouts", payoutsArray);
  208. return prod;
  209. }
  210. private static Dictionary<string, object> EncodeProductDesc(ProductDescription product)
  211. {
  212. var prod = new Dictionary<string, object> { { "storeSpecificId", product.storeSpecificId } };
  213. // ProductDescription.type field available in Unity 5.4+. Access by reflection here.
  214. var pdClassType = typeof(ProductDescription);
  215. var pdClassFieldType = pdClassType.GetField("type");
  216. if (pdClassFieldType != null)
  217. {
  218. var typeValue = pdClassFieldType.GetValue(product);
  219. prod.Add("type", typeValue.ToString());
  220. }
  221. prod.Add("metadata", EncodeProductMeta(product.metadata));
  222. prod.Add("receipt", product.receipt);
  223. prod.Add("transactionId", product.transactionId);
  224. return prod;
  225. }
  226. private static Dictionary<string, object> EncodeProductMeta(ProductMetadata product)
  227. {
  228. var prod = new Dictionary<string, object>
  229. {
  230. { "localizedPriceString", product.localizedPriceString },
  231. { "localizedTitle", product.localizedTitle },
  232. { "localizedDescription", product.localizedDescription },
  233. { "isoCurrencyCode", product.isoCurrencyCode },
  234. { "localizedPrice", Convert.ToDouble(product.localizedPrice) }
  235. };
  236. return prod;
  237. }
  238. }
  239. }