|
- /*
- ==============================================================================
-
- This file is part of the JUCE library.
- Copyright (c) 2017 - ROLI Ltd.
-
- JUCE is an open source library subject to commercial or open-source
- licensing.
-
- By using JUCE, you agree to the terms of both the JUCE 5 End-User License
- Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
- 27th April 2017).
-
- End User License Agreement: www.juce.com/juce-5-licence
- Privacy Policy: www.juce.com/juce-5-privacy-policy
-
- Or: You may also use this code under the terms of the GPL v3 (see
- www.gnu.org/licenses).
-
- JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
- EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
- DISCLAIMED.
-
- ==============================================================================
- */
-
- //==============================================================================
- class VoicePurchases : private InAppPurchases::Listener
- {
- public:
- //==============================================================================
- struct VoiceProduct
- {
- const char* identifier;
- const char* humanReadable;
- bool isPurchased, priceIsKnown, purchaseInProgress;
- String purchasePrice;
- };
-
- //==============================================================================
- VoicePurchases (AsyncUpdater& asyncUpdater)
- : guiUpdater (asyncUpdater)
- {
- voiceProducts = Array<VoiceProduct>(
- {VoiceProduct {"robot", "Robot", true, true, false, "Free" },
- VoiceProduct {"jules", "Jules", false, false, false, "Retrieving price..." },
- VoiceProduct {"fabian", "Fabian", false, false, false, "Retrieving price..." },
- VoiceProduct {"ed", "Ed", false, false, false, "Retrieving price..." },
- VoiceProduct {"lukasz", "Lukasz", false, false, false, "Retrieving price..." },
- VoiceProduct {"jb", "JB", false, false, false, "Retrieving price..." } });
- }
-
- ~VoicePurchases()
- {
- inAppPurchases.removeListener (this);
- }
-
- //==============================================================================
- VoiceProduct getPurchase (int voiceIndex)
- {
- if (! havePurchasesBeenRestored)
- {
- havePurchasesBeenRestored = true;
- inAppPurchases.addListener (this);
-
- inAppPurchases.restoreProductsBoughtList (true);
- }
-
- return voiceProducts[voiceIndex];
- }
-
- void purchaseVoice (int voiceIndex)
- {
- if (havePricesBeenFetched && isPositiveAndBelow (voiceIndex, voiceProducts.size()))
- {
- auto& product = voiceProducts.getReference (voiceIndex);
-
- if (! product.isPurchased)
- {
- product.purchaseInProgress = true;
- inAppPurchases.purchaseProduct (product.identifier, false);
- }
- }
- }
-
- StringArray getVoiceNames() const
- {
- StringArray names;
-
- for (auto& voiceProduct : voiceProducts)
- names.add (voiceProduct.humanReadable);
-
- return names;
- }
-
- private:
- //==============================================================================
- void productsInfoReturned (const Array<InAppPurchases::Product>& products) override
- {
- if (! inAppPurchases.isInAppPurchasesSupported())
- {
- for (auto idx = 1; idx < voiceProducts.size(); ++idx)
- {
- auto& voiceProduct = voiceProducts.getReference (idx);
-
- voiceProduct.isPurchased = false;
- voiceProduct.priceIsKnown = false;
- voiceProduct.purchasePrice = "In-App purcahses unavailable";
- }
-
- AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,
- "In-app purchase is unavailable!",
- "In-App purchases are not available. This either means you are trying "
- "to use IAP on a platform that does not support IAP or you haven't setup "
- "your app correctly to work with IAP.",
- "OK");
- }
- else
- {
- for (auto product : products)
- {
- auto idx = findVoiceIndexFromIdentifier (product.identifier);
-
- if (isPositiveAndBelow (idx, voiceProducts.size()))
- {
- auto& voiceProduct = voiceProducts.getReference (idx);
-
- voiceProduct.priceIsKnown = true;
- voiceProduct.purchasePrice = product.price;
- }
- }
-
- AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,
- "Your credit card will be charged!",
- "You are running the sample code for JUCE In-App purchases. "
- "Although this is only sample code, it will still CHARGE YOUR CREDIT CARD!",
- "Understood!");
- }
-
- guiUpdater.triggerAsyncUpdate();
- }
-
- void productPurchaseFinished (const PurchaseInfo& info, bool success, const String&) override
- {
- auto idx = findVoiceIndexFromIdentifier (info.purchase.productId);
-
- if (isPositiveAndBelow (idx, voiceProducts.size()))
- {
- auto& voiceProduct = voiceProducts.getReference (idx);
-
- voiceProduct.isPurchased = success;
- voiceProduct.purchaseInProgress = false;
- guiUpdater.triggerAsyncUpdate();
- }
- }
-
- void purchasesListRestored (const Array<PurchaseInfo>& infos, bool success, const String&) override
- {
- if (success)
- {
- for (auto& info : infos)
- {
- auto idx = findVoiceIndexFromIdentifier (info.purchase.productId);
-
- if (isPositiveAndBelow (idx, voiceProducts.size()))
- {
- auto& voiceProduct = voiceProducts.getReference (idx);
-
- voiceProduct.isPurchased = true;
- }
- }
-
- guiUpdater.triggerAsyncUpdate();
- }
-
- if (! havePricesBeenFetched)
- {
- havePricesBeenFetched = true;
- StringArray identifiers;
-
- for (auto& voiceProduct : voiceProducts)
- identifiers.add (voiceProduct.identifier);
-
- inAppPurchases.getProductsInformation(identifiers);
- }
- }
-
- //==============================================================================
- int findVoiceIndexFromIdentifier (String identifier) const
- {
- identifier = identifier.toLowerCase();
-
- for (auto i = 0; i < voiceProducts.size(); ++i)
- if (String (voiceProducts.getReference (i).identifier) == identifier)
- return i;
-
- return -1;
- }
-
- //==============================================================================
- AsyncUpdater& guiUpdater;
- bool havePurchasesBeenRestored = false, havePricesBeenFetched = false;
- InAppPurchases inAppPurchases;
- Array<VoiceProduct> voiceProducts;
-
- JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (VoicePurchases)
- };
|