using System; #if UNITY_IOS || UNITY_ANDROID //using UnityEngine.Advertisements; // only compile Ads code on supported platforms #endif using UnityEngine; using UnityEngine.Purchasing; // Placing the Purchaser class in the CompleteProject namespace allows it to interact with ScoreManager, // one of the existing Survival Shooter scripts. // Deriving the Purchaser class from IStoreListener enables it to receive messages from Unity Purchasing. public class Purchaser : MonoBehaviour, IStoreListener { private static IStoreController m_StoreController; // The Unity Purchasing system. private static IExtensionProvider m_StoreExtensionProvider; // The store-specific Purchasing subsystems. private int m_additionalCoins = 0; void Start() { //if (m_StoreController == null) //InitializePurchasing(); } public void InitializePurchasing() { // If we have already connected to Purchasing ... if (IsInitialized()) { // ... we are done here. return; } Debug.Log( "IAP version: " + StandardPurchasingModule.k_PackageVersion ); // Create a builder, first passing in a suite of Unity provided stores. var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance()); // Add a product to sell / restore by way of its identifier, associating the general identifier // with its store-specific identifiers. foreach (string key in GlobalsVar.gStoreOffersInfo.Keys) { ProductType type = ProductType.Consumable; builder.AddProduct(key, type); } // Kick off the remainder of the set-up with an asynchrounous call, passing the configuration // and this class' instance. Expect a response either in OnInitialized or OnInitializeFailed. UnityPurchasing.Initialize(this, builder); } private void TargetAndroidStore(AndroidStore amazonAppStore) { throw new NotImplementedException(); } private bool IsInitialized() { // Only say we are initialized if both the Purchasing references are set. return m_StoreController != null && m_StoreExtensionProvider != null; } public void BuyConsumable( string productName) { GlobalsVar.gBoard.StartNoInternetDialogIfNeed(); BuyProductID(productName); } void BuyProductID(string productId) { // If Purchasing has been initialized ... if (IsInitialized()) { DevToDevRealization.CustomEventWithParams( "start_real_purchase", "item", productId ); // ... look up the Product reference with the general product identifier and the Purchasing // system's products collection. Product product = m_StoreController.products.WithID( productId); // If the look up found a product for this device's store and that product is ready to be sold ... if (product != null && product.availableToPurchase) { GlobalsVar.gBoard.StartDialog("WaitDialog"); Debug.Log(string.Format("Purchasing product asychronously: '{0}'", product.definition.id)); // ... buy the product. Expect a response either through ProcessPurchase or OnPurchaseFailed // asynchronously. m_StoreController.InitiatePurchase(product); } // Otherwise ... else { // ... report the product look-up failure situation Debug.Log("BuyProductID: FAIL. Not purchasing product, either is not found or is not available for purchase"); } } // Otherwise ... else { // ... report the fact Purchasing has not succeeded initializing yet. Consider waiting longer or // retrying initiailization. Debug.Log("BuyProductID FAIL. Not initialized."); } } // Restore purchases previously made by this customer. Some platforms automatically restore purchases, like Google. // Apple currently requires explicit purchase restoration for IAP, conditionally displaying a password prompt. public void RestorePurchases() { // If Purchasing has not yet been set up ... if (!IsInitialized()) { // ... report the situation and stop restoring. Consider either waiting longer, or retrying initialization. Debug.Log("RestorePurchases FAIL. Not initialized."); return; } // If we are running on an Apple device ... if (Application.platform == RuntimePlatform.IPhonePlayer || Application.platform == RuntimePlatform.OSXPlayer) { // ... begin restoring purchases Debug.Log("RestorePurchases started ..."); // Fetch the Apple store-specific subsystem. var apple = m_StoreExtensionProvider.GetExtension(); // Begin the asynchronous process of restoring purchases. Expect a confirmation response in // the Action below, and ProcessPurchase if there are previously purchased products to restore. apple.RestoreTransactions((result) => { // The first phase of restoration. If no more responses are received on ProcessPurchase then // no purchases are available to be restored. Debug.Log("RestorePurchases continuing: " + result + ". If no further messages, no purchases available to restore."); }); } // Otherwise ... else { // We are not running on an Apple device. No work is necessary to restore purchases. Debug.Log("RestorePurchases FAIL. Not supported on this platform. Current = " + Application.platform); } } // // --- IStoreListener // public void OnInitialized(IStoreController controller, IExtensionProvider extensions) { // Purchasing has succeeded initializing. Collect our Purchasing references. //Debug.Log("OnInitialized: PASS"); GlobalsVar.gRealPurchasesWasInitialized = true; // Overall Purchasing system, configured with products for this application. m_StoreController = controller; // Store specific subsystem, for accessing device-specific store features. m_StoreExtensionProvider = extensions; foreach (var product in controller.products.all) { string realPurchaseSKU = product.definition.id; StoreOffersInfo realPurchase = CommonFunctions.GetRealPurchaseBySKU(realPurchaseSKU); if (realPurchase != null) { realPurchase.m_price = product.metadata.localizedPriceString; realPurchase.m_isoCurrencyCode = product.metadata.isoCurrencyCode; realPurchase.m_isoPrice = product.metadata.localizedPrice; } else CommonFunctions.myassert( false ); //Debug.Log(product.definition.id); //Debug.Log(product.metadata.localizedTitle); //Debug.Log(product.metadata.localizedDescription); //Debug.Log(product.metadata.localizedPriceString); } /*GameObject dialog = Globals.gGameApp.GetDialog( DialogTypes.STORE_DIALOG ); if ( dialog != null ) { StoreDialog storeDialog = dialog.GetComponent; if (storeDialog != null) storeDialog.SetCostTextOnButtons(); else CommonFunctions.myassert(false); }*/ } public void OnInitializeFailed(InitializationFailureReason error) { // Purchasing set-up has not succeeded. Check error for reason. Consider sharing this reason with the user. Debug.Log("OnInitializeFailed InitializationFailureReason:" + error); } public void ValidatePurchaseAndSendFBEvent(PurchaseEventArgs args) { #if UNITY_IOS || UNITY_ANDROID /*if (Globals.gAmazonBuild) return; bool validPurchase = true; var validator = new CrossPlatformValidator(GooglePlayTangle.Data(), AppleTangle.Data(), Application.identifier); try { // On Google Play, result will have a single product Id. // On Apple stores receipts contain multiple products. var result = validator.Validate(args.purchasedProduct.receipt); Debug.Log("Receipt is valid. Contents:"); // For informational purposes, we list the receipt(s) //foreach (IPurchaseReceipt productReceipt in result) //{ //Debug.Log(productReceipt.productID); //Debug.Log(productReceipt.purchaseDate); //Debug.Log(productReceipt.transactionID); //} } catch (IAPSecurityException) { Debug.Log("Invalid receipt, not unlocking content"); validPurchase = false; } if (validPurchase) { float localizedPrice = (float)(args.purchasedProduct.metadata.localizedPrice); string isoCode = args.purchasedProduct.metadata.isoCurrencyCode; FB.LogPurchase(localizedPrice, isoCode); Debug.Log(string.Format("FB.LogPurchase '{0}' '{1}'", localizedPrice, isoCode)); DevToDevRealization.CustomEvent("valid_receipt"); } else { Debug.Log(string.Format("Invalid purchase")); DevToDevRealization.CustomEvent( "invalid_receipt"); }*/ #endif } public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args) { GlobalsVar.gBoard.CloseWaitDlg(); // A consumable product has been purchased by this user. //if (String.Equals(args.purchasedProduct.definition.id, kProductIDConsumable, StringComparison.Ordinal)) { Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id)); string purchaseSku = args.purchasedProduct.definition.storeSpecificId; CommonFunctions.WasRealPurchase(purchaseSku, args.purchasedProduct.transactionID); float localizedPrice = (float)(args.purchasedProduct.metadata.localizedPrice); string isoCode = args.purchasedProduct.metadata.isoCurrencyCode; string purchaseSkuForDevToDev = purchaseSku;; DevToDevRealization.RealPayment(localizedPrice, purchaseSkuForDevToDev, isoCode, args.purchasedProduct.transactionID); ValidatePurchaseAndSendFBEvent(args); // The consumable item has been successfully purchased, add 100 coins to the player's in-game score. } // Or ... a non-consumable product has been purchased by this user. //else //{ // Debug.Log(string.Format("ProcessPurchase: FAIL. Unrecognized product: '{0}'", args.purchasedProduct.definition.id)); // } // Return a flag indicating whether this product has completely been received, or if the application needs // to be reminded of this purchase at next app launch. Use PurchaseProcessingResult.Pending when still // saving purchased products to the cloud, and when that save is delayed. return PurchaseProcessingResult.Complete; } public void OnPurchaseFailed(Product product, PurchaseFailureReason failureReason) { GlobalsVar.gBoard.CloseWaitDlg(); // A product purchase attempt did not succeed. Check failureReason for more detail. Consider sharing // this reason with the user to guide their troubleshooting actions. Debug.Log(string.Format("OnPurchaseFailed: FAIL. Product: '{0}', PurchaseFailureReason: {1}", product.definition.storeSpecificId, failureReason)); } }