示例#1
0
    private void OnEnable()
    {
        string logoPath = "Assets/FuseSDK/logo.png";

        //Fix logo import settings
        TextureImporter importer = AssetImporter.GetAtPath(logoPath) as TextureImporter;

        if (importer != null)
        {
            importer.textureType = TextureImporterType.GUI;
            AssetDatabase.WriteImportSettingsIfDirty(logoPath);
        }

        _self        = (FuseSDK)target;
        _logo        = LoadAsset <Texture2D>(logoPath);
        _icon        = null;
        _error       = null;
        _newIconPath = null;
        _guiDrawn    = false;

        _p31Android = DoClassesExist("GoogleIABManager", "GoogleIAB", "GooglePurchase");
        _p31iOS     = DoClassesExist("StoreKitManager", "StoreKitTransaction");
        _unibill    = DoClassesExist("Unibiller");
        _soomla     = DoClassesExist("SoomlaStore", "StoreEvents");

        _idRegex    = new Regex(API_KEY_PATTERN);
        _stripRegex = new Regex(API_STRIP_PATTERN);

        _self.AndroidAppID = string.IsNullOrEmpty(_self.AndroidAppID) ? string.Empty : _self.AndroidAppID;
        _self.iOSAppID     = string.IsNullOrEmpty(_self.iOSAppID) ? string.Empty : _self.iOSAppID;
        _self.GCM_SenderID = string.IsNullOrEmpty(_self.GCM_SenderID) ? string.Empty : _self.GCM_SenderID;

        _needReimport = DoSettingsNeedUpdate();
    }
示例#2
0
 public static void ManualRegisterForPushNotifications(string _)
 {
     if (_instance != null && !_instance.registerForPushNotifications)
     {
         FuseSDK me = GameObject.FindObjectOfType <FuseSDK>();
         me.StartCoroutine(me.SetupPushNotifications());
     }
 }
 void purchaseCancelled(PurchasableItem item)
 {
     if (item != null)
     {
         byte[] receipt = { 0 };
         FuseSDK.RegisterIOSInAppPurchase(item.Id, "", receipt, FuseMisc.IAPState.FAILED);
     }
 }
 void purchaseSuccessful(PurchaseEvent e)
 {
     if (e != null)
     {
         byte[] receipt = GetBytes(e.Receipt);
         FuseLog(e.PurchasedItem.description + " " + e.PurchasedItem.localizedPriceString);
         FuseSDK.RegisterUnibillPurchase(e.PurchasedItem.Id, receipt);
     }
 }
示例#5
0
 void purchaseCancelled(string error)
 {
     //FuseLog( "purchase cancelled with error: " + error );
     if (currentTransaction != null)
     {
         byte[] receipt = readReceiptData();
         FuseSDK.RegisterIOSInAppPurchase(currentTransaction.productIdentifier, currentTransaction.transactionIdentifier, receipt, FuseMisc.IAPState.FAILED);
         currentTransaction = null;
     }
 }
示例#6
0
    public void ShowBonusCoinAd()
    {
        bcAd = true;

        int index = (int)ZoneOffset.zoneBonusCoin;

        FuseSDK.PreloadAdForZoneID(zoneIDS[index]);

        FuseSDK.ShowAdForZoneID(zoneIDS[index]);
    }
 void purchaseCancelled(string error)
 {
     //FuseLog( "purchase cancelled with error: " + error );
     if (currentTransaction != null)
     {
         byte[] reciept = Convert.FromBase64String(currentTransaction.base64EncodedTransactionReceipt);
         FuseSDK.RegisterIOSInAppPurchase(currentTransaction.productIdentifier, currentTransaction.transactionIdentifier, reciept, FuseMisc.IAPState.FAILED);
         currentTransaction = null;
     }
 }
示例#8
0
    private void GetSkuInfo(List <GooglePurchase> purchaseInfo, List <GoogleSkuInfo> skuInfo)
    {
        GoogleIABManager.queryInventorySucceededEvent -= GetSkuInfo;
        if (savedPurchase == null)
        {
            //Debug.LogError("FuseSDK_Prime31_IAB::GetSkuInfo - savedPurchase was null!");
            return;
        }

        string priceString = skuInfo[0].price;
        double price       = 0;

        try
        {
            price = double.Parse(priceString, NumberStyles.Currency);
        }
        catch
        {
            var re    = new System.Text.RegularExpressions.Regex(@"\D*(?<num>[\d\s\.,]+?)(?<dec>([\.,]\s*\d?\d?)?)\D*$");
            var match = re.Match(priceString);
            if (match.Success)
            {
                string stripped = "";
                try
                {
                    var dec = System.Text.RegularExpressions.Regex.Replace(match.Groups["dec"].Value, @"\s", "");
                    stripped = System.Text.RegularExpressions.Regex.Replace(match.Groups["num"].Value, @"[^\d]", "") + dec;
                    price    = double.Parse(stripped, NumberStyles.Currency);

                    //Just in case the culture info is broken and double.Parse can't parse the decimal part properly
                    if (price % 1 == 0 && dec.Length > 1)
                    {
                        price /= 100;
                    }
                }
                catch
                {
                    Debug.LogError("FuseSDK_Prime31_IAB::GetSkuInfo: Error parsing " + priceString + " >> Unable to parse " + stripped);
                }
            }
            else
            {
                Debug.LogError("FuseSDK_Prime31_IAB::GetSkuInfo: Error parsing " + priceString + " >> String did not match regex");
            }
        }

        GooglePurchase purchase = savedPurchase;
        // purchaseTime from GoogleIAB is milliseconds since unix epoch
        DateTime time = new DateTime(purchase.purchaseTime * TimeSpan.TicksPerMillisecond, DateTimeKind.Utc);

        FuseSDK.RegisterAndroidInAppPurchase((FuseMisc.IAPState)purchase.purchaseState, purchase.purchaseToken, purchase.productId, purchase.orderId, time, purchase.developerPayload, price, null);

        savedPurchase = null;
    }
示例#9
0
    public void ShowDoubleCoinAd()
    {
        dcAd = true;
        target.StopRun();

        int index = (int)ZoneOffset.zoneDoubleCoin;

        FuseSDK.PreloadAdForZoneID(zoneIDS[index]);

        FuseSDK.ShowAdForZoneID(zoneIDS[index]);
    }
示例#10
0
    public void ShowExtraLifeAd()
    {
        extraAd = true;
        target.StopRun();

        int index = (int)ZoneOffset.zoneExtraAd;

        FuseSDK.PreloadAdForZoneID(zoneIDS[index]);

        FuseSDK.ShowAdForZoneID(zoneIDS[index]);
    }
示例#11
0
    private void onProductUpdated(List <MarketItem> items)
    {
#if UNITY_IOS
        FuseMisc.Product[] products = new FuseMisc.Product[items.Count];
        for (int i = 0; i < products.Length; i++)
        {
            products[i] = new FuseMisc.Product()
            {
                ProductId = items[i].ProductId, Price = (float)items[i].Price, PriceLocale = items[i].MarketCurrencyCode
            };
        }
        FuseSDK.RegisterIOSInAppPurchaseList(products);
#endif
    }
    void productPurchaseAwaitingConfirmationEvent(StoreKitTransaction transaction)
    {
        //FuseLog( "productPurchaseAwaitingConfirmationEvent: " + transaction );

        if (transactionIDPurchasing == transaction.transactionIdentifier)
        {
            FuseLog("Duplicate transaction " + transactionIDPurchasing);
            return;
        }
        transactionIDPurchasing = transaction.transactionIdentifier;
        currentTransaction      = transaction;
        byte[] reciept = Convert.FromBase64String(transaction.base64EncodedTransactionReceipt);
        FuseSDK.RegisterIOSInAppPurchase(transaction.productIdentifier, transaction.transactionIdentifier, reciept, FuseMisc.IAPState.PURCHASING);
    }
示例#13
0
    /// <summary>Records an in-app purchase in the Fuse system made using the Unity IAP plugin.</summary>
    /// <remarks>
    /// This function is meant to be called from Unity's IStoreListener.ProcessPurchase function passing in the
    /// purchasedProduct property of the PurchaseEventArgs parameter.
    /// </remarks>
    /// <param name="product">The product that was purchased.</param>
    public static void RegisterUnityInAppPurchase(Product product)
    {
        if (product == null)
        {
            return;
        }
#if UNITY_ANDROID
        FuseSDK.RegisterAndroidInAppPurchase(FuseMisc.IAPState.PURCHASED, product.receipt,
                                             product.definition.storeSpecificId, product.transactionID, System.DateTime.Now,
                                             string.Empty, (double)product.metadata.localizedPrice, product.metadata.isoCurrencyCode);
#elif UNITY_IOS
        FuseSDK.RegisterIOSInAppPurchase(product.definition.storeSpecificId, product.transactionID, System.Text.Encoding.UTF8.GetBytes(product.receipt), FuseMisc.IAPState.PURCHASED);
#endif
    }
    void purchaseSuccessful(StoreKitTransaction transaction)
    {
        if (transactionIDPurchased == transaction.transactionIdentifier)
        {
            FuseLog("Duplicate transaction " + transactionIDPurchased);
            return;
        }
        transactionIDPurchased = transaction.transactionIdentifier;

        //FuseLog( "purchased product: " + transaction );

        currentTransaction = null;
        byte[] reciept = Convert.FromBase64String(transaction.base64EncodedTransactionReceipt);
        FuseSDK.RegisterIOSInAppPurchase(transaction.productIdentifier, transaction.transactionIdentifier, reciept, FuseMisc.IAPState.PURCHASED);
    }
示例#15
0
    void purchaseSuccessful(StoreKitTransaction transaction)
    {
        if (transactionIDPurchased == transaction.transactionIdentifier)
        {
            FuseLog("Duplicate transaction " + transactionIDPurchased);
            return;
        }
        transactionIDPurchased = transaction.transactionIdentifier;

        //FuseLog( "purchased product: " + transaction );

        currentTransaction = null;
        byte[] receipt = readReceiptData();
        FuseSDK.RegisterIOSInAppPurchase(transaction.productIdentifier, transaction.transactionIdentifier, receipt, FuseMisc.IAPState.PURCHASED);
    }
    void productListReceivedEvent(List <StoreKitProduct> productList)
    {
        FuseLog("productListReceivedEvent. total products received: " + productList.Count);

        // create an array of product info to pass into the Fuse API
        FuseMisc.Product[] products = new FuseMisc.Product[productList.Count];
        int numItems = 0;

        foreach (StoreKitProduct product in productList)
        {
            FuseMisc.Product currentProduct = new FuseMisc.Product();
            currentProduct.ProductId   = product.productIdentifier;
            currentProduct.PriceLocale = product.currencyCode;
            currentProduct.Price       = float.Parse(product.price);
            products.SetValue(currentProduct, numItems++);
            FuseLog(product.ToString() + "\n");
        }
        FuseSDK.RegisterIOSInAppPurchaseList(products);
    }
示例#17
0
    private void onMarketPurchase(PurchasableVirtualItem pvi, string payload, Dictionary <string, string> extra)
    {
        // pvi is the PurchasableVirtualItem that was just purchased
        // payload is a text that you can give when you initiate the purchase operation and you want to receive back upon completion
        // extra will contain platform specific information about the market purchase.
        //      Android: The "extra" dictionary will contain "orderId" and "purchaseToken".
        //      iOS: The "extra" dictionary will contain "receipt" and "token".

#if UNITY_ANDROID
        string purchaseToken, orderId;
        if (!extra.TryGetValue("purchaseToken", out purchaseToken))
        {
            purchaseToken = string.Empty;
        }
        if (!extra.TryGetValue("orderId", out orderId))
        {
            orderId = string.Empty;
        }
        var item = ((PurchaseWithMarket)pvi.PurchaseType).MarketItem;

        FuseSDK.RegisterAndroidInAppPurchase(FuseMisc.IAPState.PURCHASED, purchaseToken, item.ProductId, orderId,
                                             DateTime.Now, payload, item.Price, item.MarketCurrencyCode);
#elif UNITY_IOS
        string token, receipt;
        if (!extra.TryGetValue("token", out token))
        {
            token = string.Empty;
        }
        if (!extra.TryGetValue("receipt", out receipt))
        {
            receipt = string.Empty;
        }
        var item = ((PurchaseWithMarket)pvi.PurchaseType).MarketItem;

        FuseSDK.RegisterIOSInAppPurchase(item.ProductId, token, System.Text.Encoding.UTF8.GetBytes(receipt), FuseMisc.IAPState.PURCHASED);
#endif
    }
示例#18
0
    private static void _StartSession(string gameId, bool registerForPush, bool handleAdURLs, bool enableCrashDetection)
    {
        if (_sessionStarted)
        {
            Debug.LogWarning("FuseSDK: Duplicate StartSession call. Ignoring.");
            return;
        }

        if (string.IsNullOrEmpty(gameId))
        {
            Debug.LogError("FuseSDK: Null or empty App ID. Make sure your App ID is entered in the FuseSDK prefab");
            return;
        }

        if (registerForPush)
        {
            FuseSDK me = GameObject.FindObjectOfType <FuseSDK>();
            me.StartCoroutine(me.SetupPushNotifications());
        }

        _sessionStarted = true;
        FuseLog("StartSession(" + gameId + ")");
        Native_StartSession(gameId, registerForPush, handleAdURLs, enableCrashDetection);
    }
示例#19
0
    private void OnEnable()
    {
        string logoPath = "Assets/FuseSDK/logo.png";

        //Fix logo import settings
        TextureImporter importer = AssetImporter.GetAtPath(logoPath) as TextureImporter;

        if (importer != null)
        {
            importer.textureType = TextureImporterType.GUI;
            AssetDatabase.WriteImportSettingsIfDirty(logoPath);
        }

        _self        = (FuseSDK)target;
        _logo        = LoadAsset <Texture2D>(logoPath);
        _icon        = null;
        _error       = null;
        _newIconPath = null;
        _guiDrawn    = false;

        _p31Android = DoClassesExist("GoogleIABManager", "GoogleIAB", "GooglePurchase");
        _p31iOS     = DoClassesExist("StoreKitManager", "StoreKitTransaction");
        _unibill    = DoClassesExist("Unibiller");
        _soomla     = DoClassesExist("SoomlaStore", "StoreEvents");

        _idRegex    = new Regex(API_KEY_PATTERN);
        _stripRegex = new Regex(API_STRIP_PATTERN);

        _self.AndroidAppID = string.IsNullOrEmpty(_self.AndroidAppID) ? string.Empty : _self.AndroidAppID;
        _self.iOSAppID     = string.IsNullOrEmpty(_self.iOSAppID) ? string.Empty : _self.iOSAppID;
        _self.GCM_SenderID = string.IsNullOrEmpty(_self.GCM_SenderID) ? string.Empty : _self.GCM_SenderID;

        _needReimport = DoSettingsNeedUpdate();

        //Read Manifest permissions
        if (!File.Exists(Application.dataPath + MANIFEST_PATH))
        {
            Debug.LogError("Fuse SDK: Fuse AndroidManifest.xml does not exist.");
            return;
        }

        Regex coarseLocPermissionsRegex = new Regex(MANIFEST_PERMISSION_COARSE_LOCATION_REGEX, RegexOptions.Singleline);
        Regex fineLocPermissionsRegex   = new Regex(MANIFEST_PERMISSION_FINE_LOCATION_REGEX, RegexOptions.Singleline);

        string[] manifest = File.ReadAllLines(Application.dataPath + MANIFEST_PATH);

        if (manifest.Length > 0)
        {
            foreach (string manifestLine in manifest)
            {
                Match match;
                if ((match = coarseLocPermissionsRegex.Match(manifestLine)).Success)
                {
                    androidPermissionCoarseLocation = !match.Groups["comment"].Success;
                }
                else if ((match = fineLocPermissionsRegex.Match(manifestLine)).Success)
                {
                    androidPermissionFineLocation = !match.Groups["comment"].Success;
                }
            }
        }
        else
        {
            Debug.LogError("Fuse SDK: Unable to read AndroidManifest.xml");
            return;
        }
    }
示例#20
0
    public override void OnInspectorGUI()
    {
        if (_needReimport && _guiDrawn)
        {
            UpdateAllSettings();
            _needReimport = false;
        }

#if !(UNITY_4_0 || UNITY_4_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_4 || UNITY_4_5 || UNITY_4_6 || UNITY_4_7)
        Undo.RecordObject(target, "FuseSDK modified");
#endif
        _self = (FuseSDK)target;

        GUILayout.Space(8);
        if (_logo != null)
        {
            GUILayout.Label(_logo);
        }
        GUILayout.Space(4);

        if (_needReimport)
        {
            var oldGUIColor = GUI.color;
            var newStyle    = new GUIStyle(EditorStyles.boldLabel);
            newStyle.fontStyle = FontStyle.Bold;
            newStyle.fontSize  = 24;
            GUI.color          = Color.yellow;
            GUILayout.Label("Updating Unity settings for Fuse...", newStyle);
            GUI.color = oldGUIColor;

            if (Event.current.type == EventType.Repaint)
            {
                _guiDrawn = true;
                EditorUtility.SetDirty(target);
            }
            return;
        }

        GUILayout.Space(4);

        _self.AndroidAppID = _stripRegex.Replace(EditorGUILayout.TextField("Android App ID", _self.AndroidAppID), "");
#if UNITY_ANDROID
        int idVer = CheckGameID(_self.AndroidAppID);
        if (idVer < -99)
        {
            EditorGUILayout.HelpBox("Invalid App ID: Valid form is XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX where X is a haxadecimal character", MessageType.Error);
        }
        else if (idVer < 0)
        {
            EditorGUILayout.HelpBox("Invalid App ID: Too short", MessageType.Error);
        }
        else if (idVer > 0)
        {
            EditorGUILayout.HelpBox("Invalid App ID: Too long", MessageType.Error);
        }
#endif
        _self.iOSAppID = _stripRegex.Replace(EditorGUILayout.TextField("iOS App ID", _self.iOSAppID), "");
#if UNITY_IOS
        int idVer = CheckGameID(_self.iOSAppID);
        if (idVer < -99)
        {
            EditorGUILayout.HelpBox("Invalid App ID: Valid form is XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX where X is a haxadecimal character", MessageType.Error);
        }
        else if (idVer < 0)
        {
            EditorGUILayout.HelpBox("Invalid App ID: Too short", MessageType.Error);
        }
        else if (idVer > 0)
        {
            EditorGUILayout.HelpBox("Invalid App ID: Too long", MessageType.Error);
        }
#endif

        GUILayout.Space(8);

        _self.GCM_SenderID = EditorGUILayout.TextField("GCM Sender ID", _self.GCM_SenderID);
        _self.registerForPushNotifications = EditorGUILayout.Toggle("Push Notifications", _self.registerForPushNotifications);

        if (_self.registerForPushNotifications && !string.IsNullOrEmpty(_self.AndroidAppID) && string.IsNullOrEmpty(_self.GCM_SenderID))
        {
            EditorGUILayout.HelpBox("GCM Sender ID is required for Push Notifications on Android", MessageType.Warning);
        }

        GUILayout.Space(8);

        EditorGUILayout.BeginHorizontal();
        _self.logging = EditorGUILayout.Toggle("Logging", _self.logging);
        GUILayout.Space(12);
        _self.StartAutomatically = EditorGUILayout.Toggle("Start Session Automatically", _self.StartAutomatically);
        EditorGUILayout.EndHorizontal();

        GUILayout.Space(16);

        bool oldEditorSession     = _self.editorSessions;
        bool oldStandaloneSession = _self.standaloneSessions;

        EditorGUILayout.BeginHorizontal();
        _self.editorSessions = EditorGUILayout.Toggle("Start Fuse in Editor", _self.editorSessions);
        GUILayout.Space(12);
        _self.standaloneSessions = EditorGUILayout.Toggle("Start Fuse in Standalone", _self.standaloneSessions);
        EditorGUILayout.EndHorizontal();

        GUILayout.Space(16);

        bool oldAndroidIAB     = _self.androidIAB;
        bool oldandroidUnibill = _self.androidUnibill;
        bool oldiosStoreKit    = _self.iosStoreKit;
        bool oldiosUnibill     = _self.iosUnibill;
        bool oldSoomlaStore    = _self.soomlaStore;


        EditorGUILayout.BeginHorizontal();

        EditorGUILayout.BeginVertical();
        GUI.enabled      = _p31Android || _self.androidIAB;
        _self.androidIAB = EditorGUILayout.Toggle("Android Prime31 Billing", _self.androidIAB);

        GUI.enabled          = _unibill || _self.androidUnibill;
        _self.androidUnibill = EditorGUILayout.Toggle("Android Unibill Billing", _self.androidUnibill);
        EditorGUILayout.EndVertical();

        GUILayout.Space(12);

        EditorGUILayout.BeginVertical();
        GUI.enabled       = _p31iOS || _self.iosStoreKit;
        _self.iosStoreKit = EditorGUILayout.Toggle("iOS Prime31 Billing", _self.iosStoreKit);

        GUI.enabled      = _unibill || _self.iosUnibill;
        _self.iosUnibill = EditorGUILayout.Toggle("iOS Unibill Billing", _self.iosUnibill);
        EditorGUILayout.EndVertical();

        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();

        GUI.enabled       = _soomla || _self.soomlaStore;
        _self.soomlaStore = EditorGUILayout.Toggle("Soomla Store", _self.soomlaStore);

        EditorGUILayout.EndHorizontal();

        GUI.enabled = true;

        CheckToggle(_self.editorSessions, oldEditorSession, EditorUserBuildSettings.selectedBuildTargetGroup, "FUSE_SESSION_IN_EDITOR");
        CheckToggle(_self.editorSessions, oldEditorSession, BuildTargetGroup.Standalone, "FUSE_SESSION_IN_EDITOR");
        CheckToggle(_self.standaloneSessions, oldStandaloneSession, BuildTargetGroup.Standalone, "FUSE_SESSION_IN_STANDALONE");

        CheckToggle(_self.editorSessions, oldEditorSession, BuildTargetGroup.Android, "FUSE_SESSION_IN_EDITOR");
        CheckToggle(_self.androidIAB, oldAndroidIAB, BuildTargetGroup.Android, "USING_PRIME31_ANDROID");
        CheckToggle(_self.androidUnibill, oldandroidUnibill, BuildTargetGroup.Android, "USING_UNIBILL_ANDROID");
        CheckToggle(_self.soomlaStore, oldSoomlaStore, BuildTargetGroup.Android, "USING_SOOMLA_IAP");
#if UNITY_5
        CheckToggle(_self.editorSessions, oldEditorSession, BuildTargetGroup.iOS, "FUSE_SESSION_IN_EDITOR");
        CheckToggle(_self.iosStoreKit, oldiosStoreKit, BuildTargetGroup.iOS, "USING_PRIME31_IOS");
        CheckToggle(_self.iosUnibill, oldiosUnibill, BuildTargetGroup.iOS, "USING_UNIBILL_IOS");
        CheckToggle(_self.soomlaStore, oldSoomlaStore, BuildTargetGroup.iOS, "USING_SOOMLA_IAP");
#else
        CheckToggle(_self.editorSessions, oldEditorSession, BuildTargetGroup.iPhone, "FUSE_SESSION_IN_EDITOR");
        CheckToggle(_self.iosStoreKit, oldiosStoreKit, BuildTargetGroup.iPhone, "USING_PRIME31_IOS");
        CheckToggle(_self.iosUnibill, oldiosUnibill, BuildTargetGroup.iPhone, "USING_UNIBILL_IOS");
        CheckToggle(_self.soomlaStore, oldSoomlaStore, BuildTargetGroup.iPhone, "USING_SOOMLA_IAP");
#endif

        GUILayout.Space(4);

        if (_iconFoldout = EditorGUILayout.Foldout(_iconFoldout, "Android notification icon"))
        {
            if (_icon == null)
            {
                _icon = new Texture2D(ICON_WIDTH, ICON_HEIGHT);
                _icon.LoadImage(File.ReadAllBytes(LoadIcon()));
            }

            GUILayout.Space(10);

            if (GUILayout.Button("Click to select icon:", EditorStyles.label))
            {
                _newIconPath = EditorUtility.OpenFilePanel("Choose icon", Application.dataPath, "png");
            }

            GUILayout.BeginHorizontal();
            if (GUILayout.Button(_icon, EditorStyles.objectFieldThumb, GUILayout.Height(75), GUILayout.Width(75)))
            {
                _newIconPath = EditorUtility.OpenFilePanel("Choose icon", Application.dataPath, "png");
            }

            if (_error == null)
            {
                EditorGUILayout.HelpBox("Your texture must be " + ICON_WIDTH + "x" + ICON_HEIGHT + " pixels", MessageType.None);
            }
            else
            {
                EditorGUILayout.HelpBox(_error, MessageType.Error);
            }

            GUILayout.EndHorizontal();

            if (!string.IsNullOrEmpty(_newIconPath) && _newIconPath != (Application.dataPath + ICON_PATH))
            {
                UpdateIcon();
            }
            else
            {
                _newIconPath = null;
                _error       = null;
            }
        }
        else if (_icon != null)
        {
            DestroyImmediate(_icon);
            _icon = null;
#if UNITY_5
            string path = LoadIcon(true);
            if (File.Exists(path))
            {
                File.Delete(path);
            }

            path += ".meta";
            if (File.Exists(path))
            {
                File.Delete(path);
            }
#endif
        }

        GUILayout.BeginVertical();

        GUILayout.BeginHorizontal();
        GUILayout.FlexibleSpace();
        if (GUILayout.Button("Open Preferences"))
        {
            FuseSDKPrefs.Init();
        }
        GUILayout.FlexibleSpace();
        GUILayout.EndHorizontal();

        //GUILayout.BeginHorizontal();
        //GUILayout.FlexibleSpace();
        //Color oldColor = GUI.color;
        //GUI.color = Color.green;
        //GUILayout.Label("Ready to build!", EditorStyles.boldLabel);
        //GUI.color = oldColor;
        //GUILayout.FlexibleSpace();
        //GUILayout.EndHorizontal();

        GUILayout.EndVertical();

        if (GUI.changed)
        {
            EditorUtility.SetDirty(target);
        }
    }
    void purchaseSuccessful(PurchaseEvent e)
    {
        if (e != null)
        {
            //The Recipt is a json with the contents we need to pass in, parse it here
            JSONObject jObj   = new JSONObject(e.Receipt);
            JSONObject json   = new JSONObject(jObj.GetField("json").ToString().Replace("\\\"", "\"").Trim('"'));
            JSONObject sig    = jObj.GetField("signature");
            string     sigstr = sig.ToString();


            FuseLog("json = " + json.Print(true));
            FuseLog("sig = " + sigstr);

            int    purchaseState = 0;
            string purchaseToken = "";
            string productId     = "";
            string orderId       = "";
            double purchaseTime  = 0;

            json.GetField(ref purchaseState, "purchaseState");
            json.GetField(ref purchaseToken, "purchaseToken");
            json.GetField(ref orderId, "orderId");
            json.GetField(ref productId, "productId");
            json.GetField(ref purchaseTime, "purchaseTime");

            double price = 0;
            try
            {
                price = double.Parse(e.PurchasedItem.localizedPriceString, NumberStyles.Currency);
            }
            catch
            {
                var re    = new System.Text.RegularExpressions.Regex(@"\D*(?<num>[\d\s\.,]+?)(?<dec>([\.,]\s*\d?\d?)?)\D*$");
                var match = re.Match(e.PurchasedItem.localizedPriceString);
                if (match.Success)
                {
                    string stripped = "";
                    try
                    {
                        var dec = System.Text.RegularExpressions.Regex.Replace(match.Groups["dec"].Value, @"\s", "");
                        stripped = System.Text.RegularExpressions.Regex.Replace(match.Groups["num"].Value, @"[^\d]", "") + dec;
                        price    = double.Parse(stripped, NumberStyles.Currency);

                        //Just in case the culture info is broken and double.Parse can't parse the decimal part properly
                        if (price % 1 == 0 && dec.Length > 1)
                        {
                            price /= 100;
                        }
                    }
                    catch
                    {
                        Debug.LogError("Fuse Unibill Tracking: Error parsing " + e.PurchasedItem.localizedPriceString + " >> Unable to parse " + stripped);
                    }
                }
                else
                {
                    Debug.LogError("Fuse Unibill Tracking: Error parsing " + e.PurchasedItem.localizedPriceString + " >> String did not match regex");
                }
            }

            FuseSDK.RegisterAndroidInAppPurchase((FuseMisc.IAPState)purchaseState, purchaseToken,
                                                 productId, orderId, (long)purchaseTime,
                                                 sigstr, price, null);
        }
    }