//#if UNITY_ANDROID || UNITY_IPHONE || UNITY_STANDALONE_OSX || UNITY_TVOS
//// You must obfuscate your secrets using Window > Unity IAP > Receipt Validation Obfuscator
//// before receipt validation will compile in this sample.
//// #define RECEIPT_VALIDATION
//#endif
////#define DELAY_CONFIRMATION // Returns PurchaseProcessingResult.Pending from ProcessPurchase, then calls ConfirmPendingPurchase after a delay
////#define USE_PAYOUTS // Enables use of PayoutDefinitions to specify what the player should receive when a product is purchased
//using System;
//using System.Collections;
//using System.Collections.Generic;
//using UnityEngine;
//using UnityEngine.Purchasing;
//using UnityEngine.Store; // UnityChannel
//using UnityEngine.UI;
//#if RECEIPT_VALIDATION
//using UnityEngine.Purchasing.Security;
//#endif
/////
///// An example of Unity IAP functionality.
///// To use with your account, configure the product ids (AddProduct).
/////
//[AddComponentMenu("Unity IAP/Demo")]
//public class IAPDemo : MonoBehaviour, IStoreListener
//{
// // Unity IAP objects
// private IStoreController m_Controller;
// private IAppleExtensions m_AppleExtensions;
// private IMoolahExtension m_MoolahExtensions;
// private ISamsungAppsExtensions m_SamsungExtensions;
// private IMicrosoftExtensions m_MicrosoftExtensions;
// private IUnityChannelExtensions m_UnityChannelExtensions;
// #pragma warning disable 0414
// private bool m_IsGooglePlayStoreSelected;
// #pragma warning restore 0414
// private bool m_IsSamsungAppsStoreSelected;
// private bool m_IsCloudMoolahStoreSelected;
// private bool m_IsUnityChannelSelected;
// private string m_LastTransationID;
// private string m_LastReceipt;
// private string m_CloudMoolahUserName;
// private bool m_IsLoggedIn = false;
// private UnityChannelLoginHandler unityChannelLoginHandler; // Helper for interfacing with UnityChannel API
// private bool m_FetchReceiptPayloadOnPurchase = false;
// private int m_SelectedItemIndex = -1; // -1 == no product
// private bool m_PurchaseInProgress;
// private Selectable m_InteractableSelectable; // Optimization used for UI state management
// #if RECEIPT_VALIDATION
// private CrossPlatformValidator validator;
// #endif
// ///
// /// This will be called when Unity IAP has finished initialising.
// ///
// public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
// {
// m_Controller = controller;
// m_AppleExtensions = extensions.GetExtension ();
// m_SamsungExtensions = extensions.GetExtension ();
// m_MoolahExtensions = extensions.GetExtension ();
// m_MicrosoftExtensions = extensions.GetExtension ();
// m_UnityChannelExtensions = extensions.GetExtension ();
// InitUI(controller.products.all);
// // On Apple platforms we need to handle deferred purchases caused by Apple's Ask to Buy feature.
// // On non-Apple platforms this will have no effect; OnDeferred will never be called.
// m_AppleExtensions.RegisterPurchaseDeferredListener(OnDeferred);
// Debug.Log("Available items:");
// foreach (var item in controller.products.all)
// {
// if (item.availableToPurchase)
// {
// Debug.Log(string.Join(" - ",
// new[]
// {
// item.metadata.localizedTitle,
// item.metadata.localizedDescription,
// item.metadata.isoCurrencyCode,
// item.metadata.localizedPrice.ToString(),
// item.metadata.localizedPriceString,
// item.transactionID,
// item.receipt
// }));
// }
// }
// // Prepare model for purchasing
// if (m_Controller.products.all.Length > 0)
// {
// m_SelectedItemIndex = 0;
// }
// // Populate the product menu now that we have Products
// for (int t = 0; t < m_Controller.products.all.Length; t++)
// {
// var item = m_Controller.products.all[t];
// var description = string.Format("{0} | {1} => {2}", item.metadata.localizedTitle, item.metadata.localizedPriceString, item.metadata.localizedPrice);
// // NOTE: my options list is created in InitUI
// GetDropdown().options[t] = new Dropdown.OptionData(description);
// }
// // Ensure I render the selected list element
// GetDropdown().RefreshShownValue();
// // Now that I have real products, begin showing product purchase history
// UpdateHistoryUI();
// LogProductDefinitions();
// }
// ///
// /// This will be called when a purchase completes.
// ///
// public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs e)
// {
// Debug.Log("Purchase OK: " + e.purchasedProduct.definition.id);
// Debug.Log("Receipt: " + e.purchasedProduct.receipt);
// m_LastTransationID = e.purchasedProduct.transactionID;
// m_LastReceipt = e.purchasedProduct.receipt;
// m_PurchaseInProgress = false;
// // Decode the UnityChannelPurchaseReceipt, extracting the gameOrderId
// if (m_IsUnityChannelSelected)
// {
// var unifiedReceipt = JsonUtility.FromJson(e.purchasedProduct.receipt);
// if (unifiedReceipt != null && !string.IsNullOrEmpty(unifiedReceipt.Payload))
// {
// var purchaseReceipt = JsonUtility.FromJson(unifiedReceipt.Payload);
// Debug.LogFormat("UnityChannel receipt: storeSpecificId = {0}, transactionId = {1}, orderQueryToken = {2}",
// purchaseReceipt.storeSpecificId, purchaseReceipt.transactionId, purchaseReceipt.orderQueryToken);
// }
// }
// #if RECEIPT_VALIDATION
// // Local validation is available for GooglePlay, Apple, and UnityChannel stores
// if (m_IsGooglePlayStoreSelected ||
// (m_IsUnityChannelSelected && m_FetchReceiptPayloadOnPurchase) ||
// Application.platform == RuntimePlatform.IPhonePlayer ||
// Application.platform == RuntimePlatform.OSXPlayer ||
// Application.platform == RuntimePlatform.tvOS) {
// try {
// var result = validator.Validate(e.purchasedProduct.receipt);
// Debug.Log("Receipt is valid. Contents:");
// foreach (IPurchaseReceipt productReceipt in result) {
// Debug.Log(productReceipt.productID);
// Debug.Log(productReceipt.purchaseDate);
// Debug.Log(productReceipt.transactionID);
// GooglePlayReceipt google = productReceipt as GooglePlayReceipt;
// if (null != google) {
// Debug.Log(google.purchaseState);
// Debug.Log(google.purchaseToken);
// }
// UnityChannelReceipt unityChannel = productReceipt as UnityChannelReceipt;
// if (null != unityChannel) {
// Debug.Log(unityChannel.productID);
// Debug.Log(unityChannel.purchaseDate);
// Debug.Log(unityChannel.transactionID);
// }
// AppleInAppPurchaseReceipt apple = productReceipt as AppleInAppPurchaseReceipt;
// if (null != apple) {
// Debug.Log(apple.originalTransactionIdentifier);
// Debug.Log(apple.subscriptionExpirationDate);
// Debug.Log(apple.cancellationDate);
// Debug.Log(apple.quantity);
// }
// // For improved security, consider comparing the signed
// // IPurchaseReceipt.productId, IPurchaseReceipt.transactionID, and other data
// // embedded in the signed receipt objects to the data which the game is using
// // to make this purchase.
// }
// } catch (IAPSecurityException ex) {
// Debug.Log("Invalid receipt, not unlocking content. " + ex);
// return PurchaseProcessingResult.Complete;
// }
// }
// #endif
// // Unlock content from purchases here.
//#if USE_PAYOUTS
// if (e.purchasedProduct.definition.payouts != null) {
// Debug.Log("Purchase complete, paying out based on defined payouts");
// foreach (var payout in e.purchasedProduct.definition.payouts) {
// Debug.Log(string.Format("Granting {0} {1} {2} {3}", payout.quantity, payout.typeString, payout.subtype, payout.data));
// }
// }
//#endif
// // Indicate if we have handled this purchase.
// // PurchaseProcessingResult.Complete: ProcessPurchase will not be called
// // with this product again, until next purchase.
// // PurchaseProcessingResult.Pending: ProcessPurchase will be called
// // again with this product at next app launch. Later, call
// // m_Controller.ConfirmPendingPurchase(Product) to complete handling
// // this purchase. Use to transactionally save purchases to a cloud
// // game service.
//#if DELAY_CONFIRMATION
// StartCoroutine(ConfirmPendingPurchaseAfterDelay(e.purchasedProduct));
// return PurchaseProcessingResult.Pending;
//#else
// UpdateHistoryUI();
// return PurchaseProcessingResult.Complete;
//#endif
// }
//#if DELAY_CONFIRMATION
// private HashSet m_PendingProducts = new HashSet();
// private IEnumerator ConfirmPendingPurchaseAfterDelay(Product p)
// {
// m_PendingProducts.Add(p.definition.id);
// Debug.Log("Delaying confirmation of " + p.definition.id + " for 5 seconds.");
// UpdateHistoryUI();
// yield return new WaitForSeconds(5f);
// Debug.Log("Confirming purchase of " + p.definition.id);
// m_Controller.ConfirmPendingPurchase(p);
// m_PendingProducts.Remove(p.definition.id);
// UpdateHistoryUI();
// }
//#endif
// ///
// /// This will be called is an attempted purchase fails.
// ///
// public void OnPurchaseFailed(Product item, PurchaseFailureReason r)
// {
// Debug.Log("Purchase failed: " + item.definition.id);
// Debug.Log(r);
// if (m_IsUnityChannelSelected)
// {
// var extra = m_UnityChannelExtensions.GetLastPurchaseError();
// var purchaseError = JsonUtility.FromJson(extra);
// if (purchaseError != null && purchaseError.purchaseInfo != null)
// {
// // Additional information about purchase failure.
// var purchaseInfo = purchaseError.purchaseInfo;
// Debug.LogFormat("UnityChannel purchaseInfo: productCode = {0}, gameOrderId = {1}, orderQueryToken = {2}",
// purchaseInfo.productCode, purchaseInfo.gameOrderId, purchaseInfo.orderQueryToken);
// }
// // Determine if the user already owns this item and that it can be added to
// // their inventory, if not already present.
//#if UNITY_5_6_OR_NEWER
// if (r == PurchaseFailureReason.DuplicateTransaction)
// {
// // Unlock `item` in inventory if not already present.
// Debug.Log("Duplicate transaction detected, unlock this item");
// }
//#else // Building using Unity strictly less than 5.6; e.g 5.3-5.5.
// // In Unity 5.3 the enum PurchaseFailureReason.DuplicateTransaction
// // may not be available (is available in 5.6 ... specifically
// // 5.5.1p1+, 5.4.4p2+) and can be substituted with this call.
// if (r == PurchaseFailureReason.Unknown)
// {
// if (purchaseError != null && purchaseError.error != null && purchaseError.error.Equals("DuplicateTransaction"))
// {
// // Unlock `item` in inventory if not already present.
// Debug.Log("Duplicate transaction detected, unlock this item");
// }
// }
//#endif
// }
// m_PurchaseInProgress = false;
// }
// public void OnInitializeFailed(InitializationFailureReason error)
// {
// Debug.Log("Billing failed to initialize!");
// switch (error)
// {
// case InitializationFailureReason.AppNotKnown:
// Debug.LogError("Is your App correctly uploaded on the relevant publisher console?");
// break;
// case InitializationFailureReason.PurchasingUnavailable:
// // Ask the user if billing is disabled in device settings.
// Debug.Log("Billing disabled!");
// break;
// case InitializationFailureReason.NoProductsAvailable:
// // Developer configuration error; check product metadata.
// Debug.Log("No products available for purchase!");
// break;
// }
// }
// [Serializable]
// public class UnityChannelPurchaseError
// {
// public string error;
// public UnityChannelPurchaseInfo purchaseInfo;
// }
// [Serializable]
// public class UnityChannelPurchaseInfo
// {
// public string productCode; // Corresponds to storeSpecificId
// public string gameOrderId; // Corresponds to transactionId
// public string orderQueryToken;
// }
// public void Awake()
// {
// var module = StandardPurchasingModule.Instance();
// // The FakeStore supports: no-ui (always succeeding), basic ui (purchase pass/fail), and
// // developer ui (initialization, purchase, failure code setting). These correspond to
// // the FakeStoreUIMode Enum values passed into StandardPurchasingModule.useFakeStoreUIMode.
// module.useFakeStoreUIMode = FakeStoreUIMode.StandardUser;
// var builder = ConfigurationBuilder.Instance(module);
// // This enables the Microsoft IAP simulator for local testing.
// // You would remove this before building your release package.
// builder.Configure().useMockBillingSystem = true;
// m_IsGooglePlayStoreSelected = Application.platform == RuntimePlatform.Android && module.appStore == AppStore.GooglePlay;
// // CloudMoolah Configuration setings
// // All games must set the configuration. the configuration need to apply on the CloudMoolah Portal.
// // CloudMoolah APP Key
// builder.Configure().appKey = "d93f4564c41d463ed3d3cd207594ee1b";
// // CloudMoolah Hash Key
// builder.Configure().hashKey = "cc";
// // This enables the CloudMoolah test mode for local testing.
// // You would remove this, or set to CloudMoolahMode.Production, before building your release package.
// builder.Configure().SetMode(CloudMoolahMode.AlwaysSucceed);
// // This records whether we are using Cloud Moolah IAP.
// // Cloud Moolah requires logging in to access your Digital Wallet, so:
// // A) IAPDemo (this) displays the Cloud Moolah GUI button for Cloud Moolah
// m_IsCloudMoolahStoreSelected = Application.platform == RuntimePlatform.Android && module.appStore == AppStore.CloudMoolah;
// // UnityChannel, provides access to Xiaomi MiPay.
// // Products are required to be set in the IAP Catalog window. The file "MiProductCatalog.prop"
// // is required to be generated into the project's
// // Assets/Plugins/Android/assets folder, based off the contents of the
// // IAP Catalog window, for MiPay.
// m_IsUnityChannelSelected = Application.platform == RuntimePlatform.Android && module.appStore == AppStore.XiaomiMiPay;
// // UnityChannel supports receipt validation through a backend fetch.
// builder.Configure().fetchReceiptPayloadOnPurchase = m_FetchReceiptPayloadOnPurchase;
// // Define our products.
// // Either use the Unity IAP Catalog, or manually use the ConfigurationBuilder.AddProduct API.
// // Use IDs from both the Unity IAP Catalog and hardcoded IDs via the ConfigurationBuilder.AddProduct API.
// // Use the products defined in the IAP Catalog GUI.
// // E.g. Menu: "Window" > "Unity IAP" > "IAP Catalog", then add products, then click "App Store Export".
// var catalog = ProductCatalog.LoadDefaultCatalog();
// foreach (var product in catalog.allProducts) {
// if (product.allStoreIDs.Count > 0) {
// var ids = new IDs();
// foreach (var storeID in product.allStoreIDs) {
// ids.Add(storeID.id, storeID.store);
// }
// builder.AddProduct(product.id, product.type, ids);
// } else {
// builder.AddProduct(product.id, product.type);
// }
// }
// // In this case our products have the same identifier across all the App stores,
// // except on the Mac App store where product IDs cannot be reused across both Mac and
// // iOS stores.
// // So on the Mac App store our products have different identifiers,
// // and we tell Unity IAP this by using the IDs class.
// builder.AddProduct("100.gold.coins", ProductType.Consumable, new IDs
// {
// {"100.gold.coins.mac", MacAppStore.Name},
// {"000000596586", TizenStore.Name},
// {"com.ff", MoolahAppStore.Name},
// }
//#if USE_PAYOUTS
// , new PayoutDefinition(PayoutType.Currency, "gold", 100)
//#endif //USE_PAYOUTS
// );
// builder.AddProduct("500.gold.coins", ProductType.Consumable, new IDs
// {
// {"500.gold.coins.mac", MacAppStore.Name},
// {"000000596581", TizenStore.Name},
// {"com.ee", MoolahAppStore.Name},
// }
//#if USE_PAYOUTS
// , new PayoutDefinition(PayoutType.Currency, "gold", 500)
//#endif //USE_PAYOUTS
// );
// builder.AddProduct("sword", ProductType.NonConsumable, new IDs
// {
// {"sword.mac", MacAppStore.Name},
// {"000000596583", TizenStore.Name},
// }
//#if USE_PAYOUTS
// , new List {
// new PayoutDefinition(PayoutType.Item, "", 1, "item_id:76543"),
// new PayoutDefinition(PayoutType.Currency, "gold", 50)
// }
//#endif //USE_PAYOUTS
// );
// builder.AddProduct("subscription", ProductType.Subscription, new IDs
// {
// {"subscription.mac", MacAppStore.Name}
// });
// // Write Amazon's JSON description of our products to storage when using Amazon's local sandbox.
// // This should be removed from a production build.
// builder.Configure().WriteSandboxJSON(builder.products);
// // This enables simulated purchase success for Samsung IAP.
// // You would remove this, or set to SamsungAppsMode.Production, before building your release package.
// builder.Configure().SetMode(SamsungAppsMode.AlwaysSucceed);
// // This records whether we are using Samsung IAP. Currently ISamsungAppsExtensions.RestoreTransactions
// // displays a blocking Android Activity, so:
// // A) Unity IAP does not automatically restore purchases on Samsung Galaxy Apps
// // B) IAPDemo (this) displays the "Restore" GUI button for Samsung Galaxy Apps
// m_IsSamsungAppsStoreSelected = Application.platform == RuntimePlatform.Android && module.appStore == AppStore.SamsungApps;
// // This selects the GroupId that was created in the Tizen Store for this set of products
// // An empty or non-matching GroupId here will result in no products available for purchase
// builder.Configure().SetGroupId("100000085616");
// #if RECEIPT_VALIDATION
// string appIdentifier;
// #if UNITY_5_6_OR_NEWER
// appIdentifier = Application.identifier;
// #else
// appIdentifier = Application.bundleIdentifier;
// #endif
// validator = new CrossPlatformValidator(GooglePlayTangle.Data(), AppleTangle.Data(),
// UnityChannelTangle.Data(), appIdentifier);
// #endif
// Action initializeUnityIap = () =>
// {
// // Now we're ready to initialize Unity IAP.
// UnityPurchasing.Initialize(this, builder);
// };
// bool needExternalLogin = m_IsUnityChannelSelected;
// if (!needExternalLogin)
// {
// initializeUnityIap();
// }
// else
// {
// // Call UnityChannel initialize and (later) login asynchronously
// // UnityChannel configuration settings. Required for Xiaomi MiPay.
// // Collect this app configuration from the Unity Developer website at
// // [2017-04-17 PENDING - Contact support representative]
// // https://developer.cloud.unity3d.com/ providing your Xiaomi MiPay App
// // ID, App Key, and App Secret. This permits Unity to proxy from the
// // user's device into the MiPay system.
// // IMPORTANT PRE-BUILD STEP: For mandatory Chinese Government app auditing
// // and for MiPay testing, enable debug mode (test mode)
// // using the `AppInfo.debug = true;` when initializing Unity Channel.
// AppInfo unityChannelAppInfo = new AppInfo();
// unityChannelAppInfo.appId = "abc123appId";
// unityChannelAppInfo.appKey = "efg456appKey";
// unityChannelAppInfo.clientId = "hij789clientId";
// unityChannelAppInfo.clientKey = "klm012clientKey";
// unityChannelAppInfo.debug = false;
// // Shared handler for Unity Channel initialization, here, and login, later
// unityChannelLoginHandler = new UnityChannelLoginHandler();
// unityChannelLoginHandler.initializeFailedAction = (string message) =>
// {
// Debug.LogError("Failed to initialize and login to UnityChannel: " + message);
// };
// unityChannelLoginHandler.initializeSucceededAction = () =>
// {
// initializeUnityIap();
// };
// StoreService.Initialize(unityChannelAppInfo, unityChannelLoginHandler);
// }
// }
// // For handling initialization and login of UnityChannel, returning control to our store after.
// class UnityChannelLoginHandler : ILoginListener
// {
// internal Action initializeSucceededAction;
// internal Action initializeFailedAction;
// internal Action loginSucceededAction;
// internal Action loginFailedAction;
// public void OnInitialized()
// {
// initializeSucceededAction();
// }
// public void OnInitializeFailed(string message)
// {
// initializeFailedAction(message);
// }
// public void OnLogin(UserInfo userInfo)
// {
// loginSucceededAction(userInfo);
// }
// public void OnLoginFailed(string message)
// {
// loginFailedAction(message);
// }
// }
// ///
// /// This will be called after a call to IAppleExtensions.RestoreTransactions().
// ///
// private void OnTransactionsRestored(bool success)
// {
// Debug.Log("Transactions restored.");
// }
// ///
// /// iOS Specific.
// /// This is called as part of Apple's 'Ask to buy' functionality,
// /// when a purchase is requested by a minor and referred to a parent
// /// for approval.
// ///
// /// When the purchase is approved or rejected, the normal purchase events
// /// will fire.
// ///
// /// Item.
// private void OnDeferred(Product item)
// {
// Debug.Log("Purchase deferred: " + item.definition.id);
// }
// private void InitUI(IEnumerable items)
// {
// // Disable the UI while IAP is initializing
// // See also UpdateInteractable()
// m_InteractableSelectable = GetDropdown(); // References any one of the disabled components
// // Show Restore button on supported platforms
// if (! (NeedRestoreButton()) )
// {
// GetRestoreButton().gameObject.SetActive(false);
// }
// // Show Register, Login, and Validate buttons on supported platform
// GetRegisterButton().gameObject.SetActive(NeedRegisterButton());
// GetLoginButton().gameObject.SetActive(NeedLoginButton());
// GetValidateButton().gameObject.SetActive(NeedValidateButton());
// foreach (var item in items)
// {
// // Add initial pre-IAP-initialization content. Update later in OnInitialized.
// var description = string.Format("{0} - {1}", item.definition.id, item.definition.type);
// GetDropdown().options.Add(new Dropdown.OptionData(description));
// }
// // Ensure I render the selected list element
// GetDropdown().RefreshShownValue();
// GetDropdown().onValueChanged.AddListener((int selectedItem) => {
// Debug.Log("OnClickDropdown item " + selectedItem);
// m_SelectedItemIndex = selectedItem;
// });
// // Initialize my button event handling
// GetBuyButton().onClick.AddListener(() => {
// if (m_PurchaseInProgress == true) {
// Debug.Log("Please wait, purchasing ...");
// return;
// }
// // For platforms needing Login, games utilizing a connected backend
// // game server may wish to login.
// // Standalone games may not need to login.
// if (NeedLoginButton() && m_IsLoggedIn == false)
// {
// Debug.LogWarning("Purchase notifications will not be forwarded server-to-server. Login incomplete.");
// }
// // Don't need to draw our UI whilst a purchase is in progress.
// // This is not a requirement for IAP Applications but makes the demo
// // scene tidier whilst the fake purchase dialog is showing.
// m_PurchaseInProgress = true;
// m_Controller.InitiatePurchase(m_Controller.products.all[m_SelectedItemIndex], "aDemoDeveloperPayload");
// });
// if (GetRestoreButton() != null)
// {
// GetRestoreButton().onClick.AddListener(() => {
// if (m_IsCloudMoolahStoreSelected)
// {
// if (m_IsLoggedIn == false)
// {
// Debug.LogError("CloudMoolah purchase restoration aborted. Login incomplete.");
// }
// else
// {
// // Restore abnornal transaction identifer, if Client don't receive transaction identifer.
// m_MoolahExtensions.RestoreTransactionID((RestoreTransactionIDState restoreTransactionIDState) => {
// Debug.Log("restoreTransactionIDState = " + restoreTransactionIDState.ToString());
// bool success =
// restoreTransactionIDState != RestoreTransactionIDState.RestoreFailed &&
// restoreTransactionIDState != RestoreTransactionIDState.NotKnown;
// OnTransactionsRestored(success);
// });
// }
// }
// else if (m_IsSamsungAppsStoreSelected)
// {
// m_SamsungExtensions.RestoreTransactions(OnTransactionsRestored);
// }
// else if (Application.platform == RuntimePlatform.WSAPlayerX86 ||
// Application.platform == RuntimePlatform.WSAPlayerX64 ||
// Application.platform == RuntimePlatform.WSAPlayerARM)
// {
// m_MicrosoftExtensions.RestoreTransactions();
// }
// else
// {
// m_AppleExtensions.RestoreTransactions(OnTransactionsRestored);
// }
// });
// }
// if (GetLoginButton() != null)
// {
// if (m_IsUnityChannelSelected)
// {
// GetLoginButton().onClick.AddListener(() =>
// {
// unityChannelLoginHandler.loginSucceededAction = (UserInfo userInfo) =>
// {
// m_IsLoggedIn = true;
// Debug.LogFormat("Succeeded logging into UnityChannel. channel {0}, userId {1}, userLoginToken {2} ",
// userInfo.channel, userInfo.userId, userInfo.userLoginToken);
// };
// unityChannelLoginHandler.loginFailedAction = (string message) =>
// {
// m_IsLoggedIn = false;
// Debug.LogError("Failed logging into UnityChannel. " + message);
// };
// StoreService.Login(unityChannelLoginHandler);
// });
// }
// }
// // For local validation, see ProcessPurchase.
// if (GetValidateButton() != null)
// {
// if (m_IsUnityChannelSelected)
// {
// GetValidateButton()
// .onClick.AddListener(() =>
// {
// string txId = m_LastTransationID;
// m_UnityChannelExtensions.ValidateReceipt(txId, (bool success, string signData, string signature) =>
// {
// Debug.LogFormat("ValidateReceipt transactionId {0}, success {1}, signData {2}, signature {3}",
// txId, success, signData, signature);
// // May use signData and signature results to validate server-to-server
// });
// });
// }
// }
// }
// public void UpdateHistoryUI()
// {
// if (m_Controller == null)
// {
// return;
// }
// var itemText = "Item\n\n";
// var countText = "Purchased\n\n";
// foreach (var item in m_Controller.products.all) {
// // Collect history status report
// itemText += "\n\n" + item.definition.id;
// countText += "\n\n";
//#if DELAY_CONFIRMATION
// if (m_PendingProducts.Contains(item.definition.id))
// countText += "(Pending) ";
//#endif
// countText += item.hasReceipt.ToString();
// }
// // Show history
// GetText(false).text = itemText;
// GetText(true).text = countText;
// }
// protected void UpdateInteractable()
// {
// if (m_InteractableSelectable == null)
// {
// return;
// }
// bool interactable = m_Controller != null;
// if (interactable != m_InteractableSelectable.interactable)
// {
// if (GetRestoreButton() != null)
// {
// GetRestoreButton().interactable = interactable;
// }
// GetBuyButton().interactable = interactable;
// GetDropdown().interactable = interactable;
// GetRegisterButton().interactable = interactable;
// GetLoginButton().interactable = interactable;
// }
// }
// public void Update()
// {
// UpdateInteractable();
// }
// private bool NeedRestoreButton()
// {
// return Application.platform == RuntimePlatform.IPhonePlayer ||
// Application.platform == RuntimePlatform.OSXPlayer ||
// Application.platform == RuntimePlatform.tvOS ||
// Application.platform == RuntimePlatform.WSAPlayerX86 ||
// Application.platform == RuntimePlatform.WSAPlayerX64 ||
// Application.platform == RuntimePlatform.WSAPlayerARM ||
// m_IsSamsungAppsStoreSelected ||
// m_IsCloudMoolahStoreSelected;
// }
// private bool NeedRegisterButton()
// {
// // Deprecated
// return false;
// }
// private bool NeedLoginButton()
// {
// return m_IsUnityChannelSelected;
// }
// private bool NeedValidateButton()
// {
// return m_IsUnityChannelSelected;
// }
// private Text GetText(bool right)
// {
// var which = right ? "TextR" : "TextL";
// return GameObject.Find(which).GetComponent();
// }
// private Dropdown GetDropdown()
// {
// return GameObject.Find("Dropdown").GetComponent();
// }
// private Button GetBuyButton()
// {
// return GameObject.Find("Buy").GetComponent