summaryrefslogtreecommitdiffstats
path: root/examples/demos/hangman/doc
diff options
context:
space:
mode:
authorJani Korteniemi <jani.korteniemi@qt.io>2021-07-26 13:42:14 +0300
committerJani Korteniemi <jani.korteniemi@qt.io>2021-11-10 13:46:03 +0200
commit2eff5e431435f2b5be3511823400080d4029a6c1 (patch)
tree7d4647e00bdb463bc4bb29b85b445745bc18c0f3 /examples/demos/hangman/doc
parent28dd0b133435e044224c3141265e14f2a2586efc (diff)
Add QtPurchasing module as an example under Qt demos
QtPurchasing module is deprecated in Qt6. However, the purchasing code is moved as example/demo under qtdoc to demonstrate the use of in-app purchases in Android/iOS. The demo is under demos\hangman. Few fixes done to the original code: * Ported the code to Qt 6. * Removed reinterpret_casts and QQmlListPropertys. * Fixed few QML warnings. * Added documentation * Fixed documentation * Added CMake port * Fixed Cmake for iOS * Modified Fonts in qml file * project name changed from qthangmanpurchasing to hangman Task-number: QTBUG-84776 Pick-to: 6.2 Change-Id: I86051b29d54cfb4a48b310ebc8d538c806fbf8da Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Nicholas Bennett <nicholas.bennett@qt.io> Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
Diffstat (limited to 'examples/demos/hangman/doc')
-rw-r--r--examples/demos/hangman/doc/images/qthangman-example.pngbin0 -> 41985 bytes
-rw-r--r--examples/demos/hangman/doc/images/qthangman-store-example.pngbin0 -> 37374 bytes
-rw-r--r--examples/demos/hangman/doc/src/androidclasses.qdoc100
-rw-r--r--examples/demos/hangman/doc/src/appstore.qdoc189
-rw-r--r--examples/demos/hangman/doc/src/baseclass.qdoc160
-rw-r--r--examples/demos/hangman/doc/src/gettingstarted-qml.qdoc275
-rw-r--r--examples/demos/hangman/doc/src/googleplay.qdoc112
-rw-r--r--examples/demos/hangman/doc/src/iosclasses.qdoc92
-rw-r--r--examples/demos/hangman/doc/src/qtpurchasing-overview.qdoc129
9 files changed, 1057 insertions, 0 deletions
diff --git a/examples/demos/hangman/doc/images/qthangman-example.png b/examples/demos/hangman/doc/images/qthangman-example.png
new file mode 100644
index 000000000..df54b8d4e
--- /dev/null
+++ b/examples/demos/hangman/doc/images/qthangman-example.png
Binary files differ
diff --git a/examples/demos/hangman/doc/images/qthangman-store-example.png b/examples/demos/hangman/doc/images/qthangman-store-example.png
new file mode 100644
index 000000000..99583b520
--- /dev/null
+++ b/examples/demos/hangman/doc/images/qthangman-store-example.png
Binary files differ
diff --git a/examples/demos/hangman/doc/src/androidclasses.qdoc b/examples/demos/hangman/doc/src/androidclasses.qdoc
new file mode 100644
index 000000000..8e4224438
--- /dev/null
+++ b/examples/demos/hangman/doc/src/androidclasses.qdoc
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \page qtpurchasing-androidclasses.html
+ \title Demo Android Classes
+ \brief Android classes are used in the purchasing demo to enable purchasing in Android.
+ \ingroup qtpurchasing-examples
+
+ \section1 Classes
+ \table
+ \row
+ \li \l AndroidInAppProduct
+ \li A product registered in the store.
+ \row
+ \li \l AndroidInAppTransaction
+ \li Contains information about a transaction in the external app store.
+ \row
+ \li \l AndroidInAppPurchaseBackend
+ \li Comminucates with external store.
+ \row
+ \li \l androidjni.cpp and InAppPurchase.java
+ \li Communication between Google Play's billing system and C++.
+ \endtable
+
+ Check out \l {Base Classes}
+
+ \section1 AndroidInAppProduct
+
+ AndroidInAppProduct adds purchase() for initializing purchasing process.
+
+ \section1 AndroidInAppTransaction
+
+ AndroidInAppTransaction is created in the AndroidInAppPurchaseBackend using
+ purchaseSucceeded(), purchaseFailed() and checkFinalizationStatus().
+
+ AndroidInAppTransaction adds new parameters and return types.
+ Class has finalize() function that separates Consumable and Unlockable
+ products to be either acknowledged or consumed in the InAppPurchase.java.
+
+ \section1 AndroidInAppPurchaseBackend
+
+ AndroidInAppPurchaseBackend makes and receives calls from InAppPurchase.java.
+ This class is one of the back end components in the application.
+
+ \section2 Initialize
+
+ Shows the products information on the store page.
+
+ \list 1
+ \li AndroidInAppPurchaseBackend is called from InAppStore::setupBackend().
+ \li At initialization AndroidInAppPurchaseBackend will give \l {https://developer.android.com/reference/android/content/Context} {Context} and
+ pointer of its self to the Java in the calls constructor and then
+ initializes the connection to the Google Play store using the initialize()
+ function.
+ \li When the connection is successful, androidjni will call registerRedy() which
+ emits the ready() singnal to InAppStore and starts queryProducts() function to get
+ the information of the purchasable items.
+ \li When the query is done, productQueryDone() signal is emitted and
+ the item's information will be visible on the application's store page.
+ \endlist
+
+ \section2 Purchasing
+
+ When pressing one of the products on the applications store page a call is routed
+ through \c AndroidInAppProduct::purchase() to purchaseProduct() function. This then calls
+ the Java method launchBillingFlow() which opens Goole Plays billing flow to the user.
+
+ \section1 InAppPurchase.java and androidjni.cpp
+
+ AndroidInAppPurchaseBackend makes calls directly to InAppPurchase.java and
+ receives Java calls from androidjni. The demo application communicates
+ with Java function using \l QJniObjects.
+
+ \sa \l {https://developer.android.com/google/play/billing/integrate#java}{Integrate the Google Play Billing Library}, \l QJniObjects and \l QJniEnvironment.
+*/
diff --git a/examples/demos/hangman/doc/src/appstore.qdoc b/examples/demos/hangman/doc/src/appstore.qdoc
new file mode 100644
index 000000000..86d466bb2
--- /dev/null
+++ b/examples/demos/hangman/doc/src/appstore.qdoc
@@ -0,0 +1,189 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+ \page qtpurchasing-appstore.html
+ \title Registering Products in App Store
+ \brief A short guide to registering in-app products in the iOS App Store.
+
+ To take advantage of in-app purchasing functionality on iOS, register your
+ application and all the available products in
+ \l{https://appstoreconnect.apple.com/login}{App Store Connect}.
+ This guide provides a brief introduction on how to register an application
+ and it's in-app products on App Store.
+
+ In-App purchasing can only be tested on the actual hardware for the iOS
+ platform. For more information refer to the
+ \l{http://developer.apple.com/in-app-purchase/}{iOS documentation}.
+
+
+ \section1 Register a unique app ID
+
+ One of the requirements to support in-app purchases on iOS is to have
+ a registered unique App ID. This means that it is not possible to use
+ an App ID that contains a wildcard character. You can check the existing App
+ IDs and create new ones from the
+ \l{https://developer.apple.com/account/ios/identifiers/bundle/bundleList.action}{Apple Developer Certificate, Identifiers, and Profiles manager}.
+
+ In the \uicontrol{Identifiers} tab of the
+ \uicontrol{Developer Certificate, Identifiers, and Profiles} manager, click
+ the \uicontrol{+} button to create a New App ID. This will open up the page
+ to register a new iOS App ID.
+
+ Give your App a relevant ID description and prefix. Your App ID Suffix
+ should be an Explicit App ID type. Enter a unique App ID in the Bundle ID
+ field. It is recommended to use the com.mycompany.myappname convention for
+ App ID. Where, the "com.mycompany" is the Internet domain name of the
+ publisher.
+
+ In the \uicontrol{App Services} area make sure that the
+ \uicontrol{In-App Purchases} is checked. Click \uicontrol{continue} your to
+ complete the App ID registration.
+
+ \section1 Create a provisioning profile
+
+ To be able to use your new App ID, generate a new provision profile that
+ includes the new ID to sign and run your app. Provisioning Profiles are also
+ managed through the
+ \uicontrol{Apple Developer Certificate, Identifiers, and Profiles} manager.
+
+ Navigate to the \uicontrol{Provisioning Profiles} tab of the manager and
+ click the \uicontrol{+} button to create a new Provisioning Profile. Make
+ sure that the \uicontrol{iOS App Development} is selected and click the
+ \uicontrol{Continue} button.
+
+ You are now given an option to choose the App ID to use for this profile,
+ which will be the unique App ID you created in the previous section. Once
+ again make sure that the App ID does not contain any wildcard characters
+ (“*”) as it is not be possible to use the In-App Purchasing service with
+ such an App ID.
+
+ On the next page you will need to select the certificates that will be
+ distributed with your Provisioning Profile. You would have needed to uploaded
+ a certificate on your local development machine to the Apple Developer
+ Certificate, Identifiers, and Profiles manger previously. Generally you will
+ want to add any certificates of the members of your team who will need to build
+ your App.
+
+ On the next page you will need to select the devices you will be developing and
+ testing your app on. You must register your devices to the Apple Developer
+ Certificate, Identifiers, and Profiles manger previously. The devices you
+ select here are the only ones capable of running apps signed against this
+ provisioning profile, so select all the devices you intend use during the
+ development and testing phase.
+
+ Give your Provisioning Profile a descriptive display name, and click
+ \uicontrol{Generate} to create the actual profile. When this process is
+ completed you’ll be given a choice to download the Provisioning Profile.
+
+ Open the downloaded file in XCode to install. Now the next time you plug in
+ one of the registered devices, your Provisioning Profile should be installed
+ to it automatically.
+
+ \section1 Register your application
+
+ Before you can register new products available to the in-app purchasing service,
+ you need to register your application in App Store Connect. App Store Connect is the
+ place where you register an app when you want to submit it to the Apple iOS
+ App Store.
+
+ Start by going to \l{https://appstoreconnect.apple.com/login}{App Store Connect} and
+ logging in. Once logged in open the \uicontrol{My Apps} link that will take you
+ to \uicontrol{Apps} page. If you have already registered your app here, you can
+ skip the registration step, otherwise click the plus button and select
+ \uicontrol{New App} in the top left corner of the page.
+
+ Select iOS App and then proceed to fill out the required information on the
+ next page. When you get to the \uicontrol{Bundle ID} section select the
+ unique App ID we created in the previous steps.
+
+ It is likely at this point that you do not have all the necessary details to
+ complete the information required to register your app. For now, just fill
+ out the forms with stub data as everything except the \uicontrol{SKU} and
+ \uicontrol{Version} fields are editable later.
+
+ \section1 Archive and uploading application
+
+ When you build application for iOs device Qt Creator creates XCode project
+ that will be used for uploading your application to the App Store. Open the
+ XCode project and go to \c {signing and Capabilities} from your project
+ properties and make sure that the Apple ID is selected what you use on App
+ Store Connect. Make Sure that the \c {Bundle Identifier} is the same as that you
+ created on the \uicontrol{Developer Certificate, Identifiers, and Profiles} page.
+
+ Next select \c {Set the active scheme} from the top bar of the XCode window and
+ select \c {Generic iOS Device}. Afte that select \c Product on the menu bar and
+ click \c Archive. On the pop-up window select \c {Distribute App} go through the
+ wizard and the build will show up to the App Store Connect.
+
+ \section1 Setting up application testing
+
+ From the App Store Connect select your application and go to \TestFlight page.
+ You should see at least one build of your application in the page. there are two
+ type of testing groups internal and external. In internal testing group you can
+ select developer who has access to your application on the App Store Connect. In
+ external group you can share your application with public link or you can invite
+ specific people to test your application.
+
+ \section1 Register the products
+
+ Once your app is registered in App Store Connect you will have additional options
+ available to manage that App. In the \uicontrol{Apps} page of App Sotre
+ Connect, click the icon representing your app to manage its details. Within this
+ menu you can select the \uicontrol{Manage In-App Purchases} from list on the right
+ to register in-app products you wish to offer.
+
+ To register a new product, click the \uicontrol{Plus icon} button in the right
+ of the "In-App Purchase" header. The first choice you will be given is the type of
+ in-app purchase you would like to create.
+
+ On the next page, you must fill out the details about your product. The
+ \uicontrol{Reference Name} field refers to how the product will be
+ displayed in App Store Connect and in sales reports, but not in the
+ App Store itself. The \uicontrol{Product ID} field is very important
+ as it is the unique ID that will be used to query for the product from your
+ app itself. If possible make this the same ID as the corresponding products
+ in the other platform’s stores, otherwise you will have to conditional logic
+ in your app for each platform when specifying product identifiers.
+
+ Select the pricing and availability details for you product next. For the iOS
+ App Store, pricing is set via a tier system. Each tier represents a price
+ level in each iOS App Store region. Your end users will be given the actual
+ price expected for a product in terms of what region their App Store is in.
+
+ In the next section \uicontrol{In-App Purchase Details} you specify the details
+ for at least one language. When the app requests the product details like
+ \c title and \c description, they will be provided in the language of their
+ locale if they are available. Create language details for the regions you
+ expect to distribute app in.
+
+ Finally, you will need to attach a screenshot that will be used for review
+ purposes. This again can be a stub for now, but your product will need to
+ pass the review before it can go live to be sold in your published app. Click
+ \uicontrol{save} to complete the product registration.
+*/
diff --git a/examples/demos/hangman/doc/src/baseclass.qdoc b/examples/demos/hangman/doc/src/baseclass.qdoc
new file mode 100644
index 000000000..ef71f6b69
--- /dev/null
+++ b/examples/demos/hangman/doc/src/baseclass.qdoc
@@ -0,0 +1,160 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \page qtpurchasing-baseclasses.html
+ \title Base Classes
+ \brief Base classes are used in purchasing demo to enable cross-platform for Android and iOS.
+ \ingroup qtpurchasing-examples
+
+ \section1 Classes
+ \table
+ \header
+ \li Class
+ \li Description
+ \row
+ \li \l InAppProduct
+ \li A product registered in the store.
+ \row
+ \li \l InAppStore
+ \li Main entry point for managing in-app purchases.
+ \row
+ \li \l InAppTransaction
+ \li Contains information about a transaction in the external app store.
+ \row
+ \li \l InAppPurchaseBackend
+ \li Communicates with the external store.
+ \endtable
+
+ \section1 InAppProduct
+
+ InAppProduct encapsulates a product in the external store after it has been registered in
+ InAppStore and confirmed to exist. It has an identifier which matches the identifier of the
+ product in the external store, it has a price which is retrieved from the external store,
+ and it has a product type.
+
+ The product type can be \c Consumable or \c Unlockable. Consumable products can be
+ purchased any number of times as long as each transaction is finalized explicitly by the
+ application. Unlockable types can only be purchased once.
+
+ InAppProduct has 5 returnable variables \c price, \c title, \c description \c identifier and
+ \c productType. All return a QString except productType.
+
+ ProductType is an enum type and returns \c 0 if it is Consumable and \c 1 if Unlockable.
+ \code
+ enum ProductType
+ {
+ Consumable,
+ Unlockable
+ };
+ \endcode
+
+ Check out the derived classes \l AndroidInAppProduct for Android and \l IosInAppProduct for iOS.
+
+ \section1 InAppStore
+
+ The main entry point for managing in-app purchases. It is the base class for AndroidInAppProduct and
+ IosInAppProduct.
+
+ InAppStore is used for managing in-app purchases in the application in a cross-platform way.
+ Depending on the compiler, InAppStore checks what platform is available using \c Macros.
+
+ \code
+ void InAppStore::setupBackend()
+ {
+ #ifdef Q_OS_ANDROID
+ d->backend = new AndroidInAppPurchaseBackend;
+ #endif
+
+ #ifdef Q_OS_IOS
+ d->backend = new IosInAppPurchaseBackend;
+ #endif
+
+ d->backend->setStore(this);
+
+ ...
+ \endcode
+
+ \section2 Initializing the store
+
+ Upon going to the store page in the demo, InAppStore connects all signals to related slots in
+ setupBackend() function. Then uses the registerProduct() function to register product ID and
+ productType of each product registered in the external store to a QHash registeredProducts.
+
+ Registering a product is asynchronous, and will at some point yield productRegistered()
+ signals when its found from external store.
+
+ \code
+ void InAppStore::registerProduct(InAppProduct *product)
+ {
+ d->registeredProducts[product->identifier()] = product;
+ emit productRegistered(product);
+ }
+ \endcode
+
+ \section2 Completing a purchase
+
+ Once the items have been successfully registered in the store, The user can purchase them by
+ pressing on of the products on the apps store page. QML will call product.purchase()
+ function in AndroidInAppProduct or IosInAppProduct which will open the external store's
+ purchasing flow.
+
+ When a purchase has been completed regardless of success, the transactionRedy signal will be
+ sent to \c InAppProductQmlType, to notify QML to start finalize the transaction.
+
+ section2 Restoring purchases
+
+ In the demo unlockable purchases will be saved on the apps storage. By clearing the storage
+ the user will lose the unlockable purchase and it cannot be purchased again, as according to
+ the external store it is already owned.
+
+ You can use the \c{restore purchases} button in the apps store page to restore your unlockable purchases.
+ The restore purchases button calls the restorePurchases() function and will check the external store for already owned
+ purchases. It emits the transactionRedy() signal to finalize and restore the purchase.
+
+ InAppStore has no derived classes.
+
+ \section1 InAppTransaction
+
+ InAppTransaction contains information about a transaction in the external app store and is
+ usually provided as a result of calling InAppProduct::purchase(). When the purchase flow has
+ been completed by the user (confirming the purchase, for instance by entering their password),
+ the InAppStore instance containing the product will emit a InAppStore::transactionReady()
+ signal with data about the transaction.
+
+ The status() function provides information on if the transaction was successful or not. If it was
+ successful, then the application should take appropriate action. When the necessary action has
+ been performed, finalize() should be called. The finalize() function should be called regardless
+ of the status of the transaction.
+
+ Check out the derived classes \l {AndroidInAppTransaction}{AndroidInAppTransaction} for android and \l {IosInAppTransaction}{IosInAppTransaction} for iOS.
+
+ \section1 InAppPurchaseBackend
+
+ InAppPurchaseBackend is used to create derived classs for
+ AndroidInAppPurchaseBackend and IosInAppPurchaseBackend
+*/
diff --git a/examples/demos/hangman/doc/src/gettingstarted-qml.qdoc b/examples/demos/hangman/doc/src/gettingstarted-qml.qdoc
new file mode 100644
index 000000000..63d6f1629
--- /dev/null
+++ b/examples/demos/hangman/doc/src/gettingstarted-qml.qdoc
@@ -0,0 +1,275 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+ \page qtpurchasing-gettingstarted-qml.html
+ \title Getting Started with Qt Purchasing in QML
+ \brief Guide to getting started with Qt Purchasing using QML.
+
+ This guide assumes that you have registered the in-app products for your
+ application in the external store. For more information about registering
+ products, see \l{Registering Products in Google Play} and
+ \l{Registering Products in App Store}.
+
+ \section1 Preparing the application
+
+ Register and import your QML types. The QML types can be imported into your
+ application for example using the following import statement:
+
+ \qml \QtMinorVersion
+ import com.mycompany.myappname
+ \endqml
+
+ And by adding following statements in the \c .pro file to link against defined QML types:
+
+ \code
+ CONFIG += qmltypes
+ QML_IMPORT_NAME = com.mycompany.myappname
+ QML_IMPORT_MAJOR_VERSION = 1
+ \endcode
+
+ For more information check out \l{https://doc.qt.io/qt-5/qtqml-cppintegration-definetypes.html}{Defining QML Types from C++}.
+
+ \section1 Registering products
+
+ Before you can operate on the products in your code, they must be
+ registered in the QML graph. You start by making a \l{Store} item,
+ and then create each product as a child of this.
+
+ \qml
+ Store {
+ Product {
+ identifier: "consumableProduct"
+ type: Product.Consumable
+
+ // ...
+ }
+
+ Product {
+ identifier: "unlockableProduct"
+ type: Product.Unlockable
+
+ // ...
+ }
+ }
+ \endqml
+
+ As you can see, there are consumable products and unlockable products. The former
+ can be purchased any number of times by the same user, while the latter can only
+ be purchased once.
+
+ \section1 The product declaration
+
+ For each product you must fill out the \c identifier, before the product can
+ be queried from the external store. You should also always add a \l{QtPurchasing::Product::onPurchaseSucceeded}{onPurchaseSucceeded}
+ and a \l{QtPurchasing::Product::onPurchaseFailed}{onPurchaseFailed} handler if you intend to provide the option to purchase
+ the products. If you are also using the restore functionality, you should add a
+ \l{QtPurchasing::Product::onPurchaseRestored}{onPurchaseRestored} handler to your unlockable products.
+
+ The signal handlers should handle the incoming transaction. Once the transaction
+ has been handled appropriately, it should be finalized. For instance, when a purchase
+ has succeeded, it's appropriate to save information about the purchased product in
+ persistent storage, so that this product can still be available the next time the
+ application launches.
+
+ The following example calls custom methods to save data about a succeeded purchase so that
+ it survives across application runs. After verifying that the data has been stored, it finalizes
+ the transaction. When the transaction has failed, it displays information about the failure
+ to the user and finalizes the transaction.
+
+ \qml
+ Store {
+ id: store
+ Product {
+ id: healthPotionProduct
+ identifier: "healthPotion"
+ type: Product.Consumable
+
+ property bool purchasing: false
+
+ onPurchaseSucceeded: {
+ if (!hasAlreadyStoredTransaction(transaction.orderId)) {
+ ++healthPotions
+ if (!addHealthPotionToPersistentStorage(transaction.orderId)) {
+ popupErrorDialog(qsTr("Unable to write to persistent storage. Please make sure there is sufficient space and restart."))
+ } else {
+ transaction.finalize()
+ }
+ }
+
+ // Reset purchasing flag
+ purchasing = false
+ }
+
+ onPurchaseFailed: {
+ popupErrorDialog(qsTr("Purchase not completed."))
+ transaction.finalize()
+
+ // Reset purchasing flag
+ purchasing = false
+ }
+ }
+ }
+ \endqml
+
+ If a transaction is not finalized, it will be called again for the same transaction the next time the application
+ starts up, providing another chance to store the data. The transaction for a consumable product has
+ to be finalized before the product can be purchased again.
+
+ \section1 Purchasing a product
+
+ In order to purchase a product, call the object's purchase() method. This launches a platform-specific, asynchronous
+ process to purchase the product, for example by requesting the user's password and confirmation of the purchase.
+ In most cases, you should make sure that the application UI is not accepting input while the purchasing request
+ is being processed, as this is not handled automatically on all platforms.
+
+ The following example adds a button to be used with the example product in the previous section:
+ \qml
+ Rectangle {
+ id: button
+ width: 100
+ height: 50
+
+ Text {
+ anchors.centerIn: parent
+ text: qsTr("Buy health potion for only " + healthPotionProduct.price + "!")
+ }
+
+ MouseArea {
+ enabled: !healthPotionProduct.purchasing && healthPotionProduct.status === Product.Registered
+ anchors.fill: parent
+ onClicked: {
+ healthPotionProduct.purchasing = true
+ healthPotionProduct.purchase()
+ }
+ }
+ }
+ \endqml
+
+ When the button is clicked, the purchase process is started. At some point in the future, either the
+ \l{QtPurchasing::Product::onPurchaseFailed}{onPurchaseFailed} handler will be called (for example if the user cancels the transaction), or the
+ \l{QtPurchasing::Product::onPurchaseSucceeded}{onPurchaseSucceeded} handler will be called.
+
+ \note The button is only enabled if the product's status is set to Registered. The registration process
+ for a product is asynchronous, so purchases attempted on a product before it has been successfully registered
+ will always fail.
+
+ \section1 Restoring previously purchased products
+
+ If the application is uninstalled and subsequently reinstalled (or installed by the same user on
+ a different device) you should provide a way to restore the previously purchased unlockable products
+ in the external market place.
+
+ To start the process of restoring purchases, you should call the restorePurchases() method in the
+ \l Store object. This will cause the onPurchaseRestored handler to be called in each of the application's
+ unlockable products that has previously been purchased by the current user.
+
+ Continuing on the example from before, which could be some sort of role-playing computer game, lets imagine
+ that the game has downloadable content that you can buy to expand the game further. This should be an unlockable product,
+ because the user should not have to purchase it more than once.
+
+ \qml
+ Store {
+ id: store
+
+ // ... other products
+
+ Product {
+ id: dlcForestOfFooBarProduct
+ identifier: "dlcForestOfFooBar"
+ type: Product.Unlockable
+
+ property bool purchasing: false
+
+ onPurchaseSucceeded: {
+ if (!hasMap("forestOfFooBar.map")) {
+ if (!downloadExtraMap("forestOfFooBar.map")) {
+ popupErrorDialog(qsTr("Unable to download The Forest of FooBar map. Please make sure there is sufficient space and restart."))
+ } else {
+ transaction.finalize()
+ }
+ }
+
+ // Reset purchasing flag
+ purchasing = false
+ }
+
+ onPurchaseFailed: {
+ popupErrorDialog(qsTr("Purchase not completed."))
+ transaction.finalize()
+
+ // Reset purchasing flag
+ purchasing = false
+ }
+
+ onPurchaseRestored: {
+ if (!hasMap("forestOfFooBar.map")) {
+ if (!downloadExtraMap("forestOfFooBar.map")) {
+ popupErrorDialog(qsTr("Unable to download The Forest of FooBar map. Please make sure there is sufficient space and restart."))
+ } else {
+ transaction.finalize()
+ }
+ }
+ }
+ }
+ }
+ \endqml
+
+ If a user buys the downloadable content and later either installs the game on another device or uninstalls and reinstalls the game,
+ you can provide a way to restore the purchase, such as the following button:
+
+ \qml
+ Rectangle {
+ id: restoreButton
+ width: 100
+ height: 50
+
+ Text {
+ anchors.centerIn: parent
+ text: "Restore previously purchased content"
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ store.restorePurchases()
+ }
+ }
+ }
+ \endqml
+
+ Restoring purchases should always be done as a reaction to user input, as it may present a password dialog on some platforms.
+ Calling the restorePurchases() method launches the restore process asynchronously. At some point in the future the onPurchaseRestored
+ handler will be called if the product has previously been purchased.
+
+ \note While the function behaves as documented on Android, this functionality is technically not needed there. The reason for this
+ is that the Android device manages all unlockable purchases with no intervention from the application. If an application is
+ uninstalled and reinstalled (or installed on a different device) on Android, then onPurchaseSucceeded will be called for each previously
+ purchased, unlockable product when the application starts up.
+*/
+
diff --git a/examples/demos/hangman/doc/src/googleplay.qdoc b/examples/demos/hangman/doc/src/googleplay.qdoc
new file mode 100644
index 000000000..83b0a1168
--- /dev/null
+++ b/examples/demos/hangman/doc/src/googleplay.qdoc
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+ \page qtpurchasing-googleplay.html
+ \title Registering Products in Google Play
+ \brief A short guide to registering in-app products in Google Play Store.
+
+ The Google Play market place allows you to register your application, as well
+ as the in-app products you want to make available to it, without publishing
+ it. The following \l{https://developer.android.com/studio/publish}{this guide} gives a brief introduction on uploading your
+ application to Google Play and registering products.
+
+ \section1 Preparing your application for submission
+
+ Before you can upload your application to Google Play, you must prepare it
+ for submission.
+
+ \section2 Adding a Manifest XML
+
+ The default \c AndroidManifest.xml generated for applications by Qt is
+ suitable for development testing, but cannot be used when submitting the
+ application to Google Play.
+
+ Create your own manifest by clicking the
+ \uicontrol{Create Templates} button in Qt Creator. You can find the
+ button under \uicontrol{Projects} > \uicontrol{Build} tab. Expand
+ \uicontrol{Build Android APK} to see it.
+
+ Once the manifest is added to your project, you can modify it. The most
+ important parts are the \c{application name} and the \c{package name}. The
+ package name must be unique, and it is recommended to follow the
+ \b {com.mycompany.myappname} naming convention. The "com.mycompany"
+ namespace is based on the internet domain ownership to avoid naming
+ collisions with other applications.
+
+ Other important parts of the manifest include the \c{versionCode}, which must
+ be incremented every time you upload a new version of the application. Other
+ properties will decide how your application package
+ is presented in the store listing, such as the \c{application name} and the \c{version name}.
+
+ For more information on the \c AndroidManifest.xml, see the
+ \l{http://developer.android.com/guide/topics/manifest/manifest-element.html}{Android documentation}.
+
+ For more information, refer to the
+ \l{https://doc.qt.io/qt-5/android-3rdparty-libs.html}{Third-party Android Libraries}.
+
+ \section2 Signing the application
+
+ Qt uses the default debug key to sign your application to enable running the
+ application on a device. Same key cannot be used to sign the Android Application Bundles
+ that is meant to be published on Google Play.
+
+ See \l{https://doc.qt.io/qtcreator/creator-deploying-android.html#signing-android-packages}{Signing Android Packages}
+
+ \section1 Registering your application
+
+ Once the application is prepared for publishing, you can create a listing for
+ it in Google Play.
+
+ The first step is to get a publisher account, if you do not already have one.
+ Go to \l{https://play.google.com/apps/publish/}{the Google Play developer console},
+ log in with the Google account of your choice, and follow the steps as
+ directed.
+
+ When you have set up your account, click on \uicontrol{Add new application}
+ in Google Play's developer console.
+
+ Fill out as much information as you want in the store listing, and also the
+ \uicontrol{Pricing and distribution} page.
+
+ \section2 Publishing your application
+
+ In order to test in-app purchases in your application, you first have to
+ publish it.
+
+ See \l{https://developer.android.com/studio/publish}{Publish your app}
+
+ \section2 Adding in-app products
+
+ In order to access in-app products from your application, you must register
+ them in Google Play.
+
+ See \l{https://developer.android.com/google/play/billing/getting-ready#products}{Create and configure your products}
+
+*/
+
diff --git a/examples/demos/hangman/doc/src/iosclasses.qdoc b/examples/demos/hangman/doc/src/iosclasses.qdoc
new file mode 100644
index 000000000..f717352ed
--- /dev/null
+++ b/examples/demos/hangman/doc/src/iosclasses.qdoc
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \page qtpurchasing-iosclasses.html
+ \title Demo iOS Classes
+ \brief IOS classes are used in the purchasing demo to enable purchasing in iOS.
+ \ingroup qtpurchasing-examples
+
+ \section1 Classes
+ \table
+ \row
+ \li \l IosInAppPurchaseProduct
+ \li A product registered in the store.
+ \row
+ \li \l IosInAppPurchaseTransaction
+ \li Contains information about a transaction in the external app store.
+ \row
+ \li \l IosInAppPurchaseBackend
+ \li Comminucates with external store.
+ \endtable
+
+ Check out \l {Base Classes} which include InAppProduct, InAppStore,
+ InAppTransaction and InAppPurchaseBackend
+
+ \section1 IosInAppPurchaseProduct
+
+ IosInAppPurchaseProduct adds purchase() for initializing purchasing process.
+
+ \section1 IosInAppPurchaseTransaction
+
+ IosInAppPurchaseTransaction adds new parameters and return types.
+ Transaction error handling is implemented on IosInAppPurchaseTransaction's
+ constructor. The class has the finalize() function that finalizes the transaction.
+
+ \section1 IosInAppPurchaseBackend
+
+ IosInAppPurchaseBackend uses \b Objective-C language to communicate with the App
+ Store.
+
+ \section2 Initializing the products
+
+ This class shows the product's information on the store page.
+
+ \list 1
+ \li IosInAppPurchaseBackend is called from InAppStore::setupBackend().
+ \li At initialization IosInAppPurchaseBackend creates InAppPurchaseManager with
+ Objective-C.
+ \li InAppStore::registerProduct(productType, &identifier) function is called and
+ queryProduct() is executed in the back end.
+ \li Objective-C function requestProductData:() is called and will make \l{https://developer.apple.com/documentation/storekit/skproductsrequest}{SKProductRequest}.
+ \li After SKProductRequest is finished and product objects has been
+ created in Objective-C productsRequest:(), products will be registered
+ by the IosInAppPurchaseBackend::registerProduct() function.
+ \li Signal productQueryDone() will be emitted and the item's information will be
+ visible on the application's store page.
+ \endlist
+
+ \section2 Purchasing process
+
+ \list 1
+ \li The user presses one of the products on the applications store page.
+ \li \c IosInAppPurchaseProduct::purchase() function is called and payment is added to
+ the \c SKPaymentQueue in the Objective-C function paymentQueue:() in
+ IosInAppPurchaseBackend.
+ \li Purchase confirmation pop-up is launched for the user.
+ \endlist
+*/
diff --git a/examples/demos/hangman/doc/src/qtpurchasing-overview.qdoc b/examples/demos/hangman/doc/src/qtpurchasing-overview.qdoc
new file mode 100644
index 000000000..33790c8b2
--- /dev/null
+++ b/examples/demos/hangman/doc/src/qtpurchasing-overview.qdoc
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example demos/hangman
+ \title In-App purchasing demo
+ \brief A complete mobile application that demonstrates purchasing in-app products.
+ \ingroup qtpurchasing-examples
+ \ingroup android-examples
+
+
+ \section1 What is this demo?
+ \image qthangman-example.png
+
+ This demo is a complete mobile application that demonstrates how it is
+ possible to offer in-app products inside a Qt application, in a
+ cross-platform manner. In order to test the in-app purchase functionality in the
+ example, you must first register the application and its products in the
+ external store. For an introduction on how to do this, see the guides for
+ \l{Registering Products in Google Play}{Google Play} and
+ \l{Registering Products in App Store}{App Store} respectively.
+
+ \section1 3rd party app stores
+
+ The in-app products must be registered in the target stores, before they
+ can be queried or purchased in an application. We recommend using the same
+ identifiers for the products in each store, as it simplifies the code to
+ query and purchase the products.
+
+ \list
+ \li \l{Registering Products in Google Play}
+ \li \l{Registering Products in App Store}
+ \endlist
+
+ \section1 How does the demo work
+ The demo is a QML application that registers QML types to access information
+ about in-app products, as well as to request purchases for those products.
+ These are registered in the external store for the target platform
+
+ In-app purchasing are added to application by first adding a Store object. In
+ the demo the Store object is created by the MainView component that is loaded
+ on application startup.
+ \snippet demos/hangman/qml/MainView.qml 0
+
+ The demo defines a component for displaying a store for purchasing in-app
+ products made available. These products must be first registered with the
+ store object we created above in MainView. There are two products available,
+ the first being a consumable type.
+
+ \snippet demos/hangman/qml/StoreView.qml 0
+
+ This consumable product provides 100 additional vowels to be used when
+ guessing words in the game. When it is successfully purchased, we update the
+ state of the application to include 100 additional vowels. Then we call
+ finalize() on the transaction object to confirm to the platform store that the
+ consumable product has been provided.
+
+ The second product is a non-consumable type that will unlock vowels permanently
+ in the future. In addition to updating the application state on purchase, we
+ must make sure to provide a way to restore this purchase on other devices used
+ by the end user. In this case we create a signal handler for onPurchaseRestored.
+
+ \snippet demos/hangman/qml/StoreView.qml 1
+
+ \image qthangman-store-example.png
+
+ In addition to registering the products, the demo also provide an interface to
+ actually purchase the registered product. The demo defines a custom component
+ called \c StoreItem to display and handle the purchasing interaction.
+
+ \snippet demos/hangman/qml/StoreView.qml 1
+
+ The StoreItem component will display the product data that is queried from the
+ platform's store, and will call the purchase() method on the product when it is
+ clicked by the user.
+
+ \snippet demos/hangman/qml/StoreItem.qml 0
+
+ If you are planning to use QML in your project with purchasing functionality,
+ check out
+ \l{Getting Started with Qt Purchasing in QML}.
+
+ Android and iOS use the base classes. From base classes there are derivative
+ classes for android and ios:
+
+ \list
+ \li \l{Base Classes}
+ \li \l{Demo Android Classes}
+ \li \l{Demo iOS Classes}
+ \endlist
+
+ \section1 In-App purchases
+
+ In-app purchases are a way to monetize an application. These purchases are
+ made from inside the application and can include anything from unlocking
+ content to virtual items. The demo uses the system APIs
+ for in-app purchases, which means the purchase process is more familiar to
+ the user, and the information already stored by the platform (such as credit
+ card information) can be used to simplify the purchase process.
+
+ \section1 Licenses and attributions
+
+ In regards to deploying the demo on Android see
+ \l Android GNU C++ Run-time Licensing for more information.
+*/