A product for in-app purchasing. More...
Import Statement: | import QtPurchasing 1.0 |
Since: | QtPurchasing 1.0 |
Product contains information about a product in the external market place. Once the product's identifier and type are set, the product will be queried from the external market place. Properties such as price will then be set, and it will be possible to purchase the product. The status property holds information on the registration process.
Note: It is not possible to change the identifier and type once they have both been set and the product has been registered.
description : string |
This property holds the description of the product once it has been successfully queried from the external market place. The title is localized if the external market place has defined a description in the current users locale.
identifier : string |
This property holds the identifier of the product in the external market place. It must match the identifier used to register the product externally before-hand.
When both the identifier and type is set, the product is queried from the external market place, and its other properties are updated asynchronously. At this point, the identifier and type can no longer be changed.
The following example queries an unlockable product named "myUnlockableProduct" from the external market place.
Store { Product { identifier: "myUnlockableProduct" type: Product.Unlockable // ... } }
price : string |
This property holds the price of the product once it has been successfully queried from the external market place. The price is a string consisting of both currency and value, and is usually localized to the current user.
For example, the following example displays the price of the unlockable product named "myUnlockableProduct":
Store { Product { id: myUnlockableProduct identifier: "myUnlockableProduct" type: Product.Unlockable // ... } } Text { text: myUnlockableProduct.status === Product.Registered ? "Price is " + myUnlockableProduct.price : "Price unknown at the moment" }
When run in a Norwegian locale, this code could for instance display "Price is kr 6,00" for a one-dollar product.
status : enumeration |
This property holds the current status of the product in the registration sequence.
Store { Product { identifier: "myConsumableProduct" type: Product.Consumable onStatusChanged: { switch (status) { case Product.PendingRegistration: console.debug("Registering " + identifier); break case Product.Registered: console.debug(identifier + " registered with price " + price); break case Product.Unknown: console.debug(identifier + " was not found in the market place"); break } } // ... } }
This property holds the store containing the product. When the product is created as a child of the store, this is set automatically to the parent, as in the following example:
Store { Product { // No need to set the store explicitly here, as it will automatically be // bound to the parent identifier: "myConsumableProduct" type: Product.Consumable } Product { // No need to set the store explicitly here, as it will automatically be // bound to the parent identifier: "myUnlockableProduct" type: Product.Unlockable } }
However, in some advanced use cases, for example when products are created based on a model, it's also possible to create the product anywhere in the QML document and set the store explicitly, like in the following example:
ListModel { id: productModel ListElement { productIdentifier: "myConsumableProduct" productType: Product.Consumable } ListElement { productIdentifier: "myUnlockableProduct" productType: Product.Unlockable } } Store { id: myStore } Instantiator { model: productModel delegate: Product { identifier: productIdentifier type: productType store: myStore } }
title : string |
This property holds the title of the product once it has been successfully queried from the external market place. The title is localized if the external market place has defined a title in the current users locale.
type : string |
This property holds the type of the product in the external market place.
It can hold one of the following values:
When both the identifier and type is set, the product is queried from the external market place, and its other properties are updated asynchronously. At this point, the identifier and type can no longer be changed.
The following example queries an unlockable product named "myUnlockableProduct" from the external market place.
Store { Product { identifier: "myUnlockableProduct" type: Product.Unlockable // ... } }
This handler is called when a purchase was requested for a given product, but the purchase failed. This will typically happen if the application calls purchase() on a product, and the user subsequently cancels the purchase. It could also happen under other circumstances, for example if there is no suitable network connection.
All products should have an onPurchaseFailed
handler.
After a proper reaction is taken, the finalize() function should be called on the transaction object. If this is not done, the handler may be called again the next time the product is registered.
The following example reacts to a failed purchase attempt by calling a custom function to display a message to the user.
Store { Product { id: myConsumableProduct identifier: "myConsumableProduct" type: Product.Consumable onPurchaseFailed: { myDisplayHelper.message("Product was not purchased. You have not been charged.") transaction.finalize() } // ... } }
This handler is called when a previously purchased unlockable product is restored. This can happen when the restorePurchases() function in the current
Store is called. The onPurchaseRestored
handler will then be called for each unlockable product which has previously been purchased by the user.
Applications which uses the restorePurchases() function should include this handler in all unlockable products. In the handler, the application should make sure information about the purchase is stored and call finalize() on the transaction object if the information has been successfully stored (or has been verified to already be stored).
The following example calls a custom function which either saves the information about the purchase or verifies that it is already saved. When the data has been verified, it finalizes the transaction. If it could not be verified, it calls another custom function to display an error message to the user. If the transaction is not finalized, the handler will be called again for the same transaction the next time the product is registered (on application start-up).
Store { Product { id: myUnlockableProduct identifier: "myUnlockableProduct" type: Product.Unlockable onPurchaseRestored: { if (myStorage.savePurchaseInformation(identifier)) { transaction.finalize() } else { myDisplayHelper.message("Failed to store purchase information. Is there available storage?") } } // ... } }
This handler is called when a product has been purchased successfully. It is triggered when the application has called purchase() on the product and the user has subsequently confirmed the purchase, for example by entering their password.
All products should have a handler for onPurchaseSucceeded. This handler should in turn save information about the purchased product and when the information has been stored and verified, it should call finalize() on the transaction object.
The handler should support being called multiple times for the same purchase. For example, the application execution might by accident be interrupted after saving the purchase information, but before finalizing the transaction. In this case, the handler should verify that the information is already stored in the persistent storage and then finalize the transaction.
The following example attempts to store the purchase state of a consumable product using a custom made function. It only finalizes the transaction if saving the data was successful. Otherwise, it calls another custom function to display an error message to the user.
Store { Product { id: myConsumableProduct identifier: "myConsumableProduct" type: Product.Consumable onPurchaseSucceeded: { if (myStorage.savePurchaseInformation(identifier)) { transaction.finalize() } else { myDisplayHelper.message("Failed to store purchase information. Is there available storage?") } } // ... } }
If the transaction is not finalized, the onPurchaseSucceeded handler will be called again the next time the product is registered (on application startup.) This means that if saving the information failed, the user will have the opportunity of rectifying the problem (for example by deleting something else to make space for the data) and the transaction will be completed once they restart the application and the problem has been solved.
Note: A purchased, consumable product can not be purchased again until its previous transaction is finalized.
Launches the purchasing process for this product. The purchasing process is asynchronous. When it completes, either the onPurchaseSucceeded or the onPurchaseFailed handler in the object will be called with the resulting transaction.
Resets the status of this product and retries querying it from the external market place.
This method can be used when querying the product failed for some reason (such as network timeouts).
This QML method was introduced in QtPurchasing 1.0.2.