123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- using System;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using UnityEngine.Purchasing.Extension;
- using UnityEngine.Purchasing.MiniJSON;
-
- namespace UnityEngine.Purchasing
- {
- internal class UDPImpl : JSONStore, IUDPExtensions
- {
- private INativeUDPStore m_Bindings;
- private object m_UserInfo = null; //UDP UserInfo via Reflection
- private string m_LastInitError;
- private const string k_Unknown = "Unknown"; // From PurchaseFailureReason
- private bool m_Initialized = false;
- private const int PURCHASE_PENDING_CODE = -303;
- private Action<Product> m_DeferredCallback;
- private const string k_Errorcode = "errorCode"; // From UDP sdk purchase pending state
-
- public void SetNativeStore(INativeUDPStore nativeUdpStore)
- {
- m_Bindings = nativeUdpStore;
- }
-
- #region IStore
-
- /// <summary>
- /// This function only save the IStoreCallback.
- /// The initialization of UDP is put into <see cref="RetrieveProducts"/>,
- /// because in <see cref="PurchasingManager"/>, <see cref="Initialize"/> and <see cref="RetrieveProducts"/>
- /// will be called together.
- /// However, for UDP, <see cref="RetrieveProducts"/> must been done AFTER <see cref="Initialize"/> succeeds.
- /// If the <see cref="Initialize"/> involves login, it may take a long time and <see cref="RetrieveProducts"/>
- /// will fail.
- /// </summary>
- /// <param name="callback"></param>
- public override void Initialize(IStoreCallback callback)
- {
- unity = callback;
- }
-
- public override void RetrieveProducts(ReadOnlyCollection<ProductDefinition> products)
- {
- void retrieveCallback(bool success, string json)
- {
- if (success && !string.IsNullOrEmpty(json))
- {
- OnProductsRetrieved(json);
- }
- else
- {
- m_Logger.LogIAPWarning("RetrieveProducts failed: " + json);
- }
- }
-
- if (!m_Initialized)
- {
- m_Bindings.Initialize((success, message) =>
- {
- // Clear the message and userInfo when an Initialized is called successfully.
- m_LastInitError = "";
- m_UserInfo = null;
-
- if (success)
- {
- if (!string.IsNullOrEmpty(message))
- {
- var dic = message.HashtableFromJson();
- if (dic.ContainsKey("Channel"))
- {
- var udpUserInfo = UserInfoInterface.GetClassType();
- if (udpUserInfo != null)
- {
- m_UserInfo = Activator.CreateInstance(udpUserInfo);
- DictionaryToStringProperty(dic, m_UserInfo);
- }
- }
- }
-
- m_Initialized = true;
- // IStoreCallback do not have initialize success callback.
- m_Bindings.RetrieveProducts(products, retrieveCallback);
- }
- else
- {
- m_LastInitError = message;
- unity.OnSetupFailed(InitializationFailureReason.AppNotKnown, null);
- }
- });
- }
- else
- {
- m_Bindings.RetrieveProducts(products, retrieveCallback);
- }
- }
-
- 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;
- }
-
- var 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);
- }
-
- private void OnPurchaseDeferred(string productId)
- {
- if (null == productId || productId == "")
- {
- return;
- }
-
- var product = unity.products?.WithStoreSpecificID(productId);
-
- if (null != product)
- {
- m_DeferredCallback(product);
- }
- }
-
- public override void FinishTransaction(ProductDefinition product, string transactionId)
- {
- if (product == null || transactionId == null)
- {
- return;
- }
-
- if (product.type == ProductType.Consumable)
- {
- m_Bindings.FinishTransaction(product, transactionId);
- }
- }
-
- #endregion
-
- #region extension
-
- public string GetLastInitializationError()
- {
- return m_LastInitError;
- }
-
- public object GetUserInfo()
- {
- return m_UserInfo;
- }
-
- public void RegisterPurchaseDeferredListener(Action<Product> callback)
- {
- m_DeferredCallback = callback;
- }
-
- public void EnableDebugLog(bool enable)
- {
- var storeServiceInfo = StoreServiceInterface.GetClassType();
- if (storeServiceInfo != null)
- {
- var enableDebugLogging = StoreServiceInterface.GetEnableDebugLoggingMethod();
- enableDebugLogging.Invoke(null, new object[] { enable });
- }
- else
- {
- Debug.LogError("Failed to access StoreService for UDP, cannot enable logging");
- }
- }
-
- #endregion
-
- #region helper functions
-
- private static void DictionaryToStringProperty(Dictionary<string, object> dic, object info)
- {
- var properties = info.GetType().GetProperties();
-
- foreach (var property in properties)
- {
- if (property.PropertyType == typeof(string))
- {
- property.SetValue(info, dic.GetString(property.Name), null);
- }
- }
- }
-
- #endregion
- }
- }
|