Creating the store component

The Freemium sample app defines the storefront for the app using a StorePage custom component, which is defined in the StorePage.qml file. All digital goods sold in the app can be purchased here. This page also lets users know what they have purchased and provides a way to manually restore purchases from the Payment Service servers if necessary. For example, if a user switches to a new device or reinstalls the app, previous purchases can be restored to the device. You can use this custom store component for any store in any app just by changing the digital goods that are offered for sale.

Screen showing the store UI of the Freemium sample app on a device.

The StorePage component is defined using a Page object. A PaymentManager is attached to this Page to handle purchases and to store purchases when they are made successfully.

import bb.cascades 1.0
import bb.platform 1.2

Page {

    id: storePage

    attachedObjects: [

        PaymentManager {
            id: storePaymentManager
            property bool busy: false
            onExistingPurchasesFinished: {
                storePaymentManager.busy = false;
                
                // If there's no error message in the response ...
                if (reply.errorCode == 0) {
                   //... save the purchase to local cache
                   for (var i = 0; i < reply.purchases.length; ++ i){
                        PurchaseStore.storePurchase(
                            reply.purchases[i].receipt[
                                "digitalGoodSku"]);
                    }
                } else {
                    console.log("Error: " + reply.errorInfo);
                }
            }
        }
    ]

    // Container for the UI of the Store ... 

}

The UI of the store is defined in a Container. The background of the store is set up with an ImageView. A Banner ad is placed on top of the background using the FreemiumBanner custom componet. You can learn more about this custom component in Adding ads.

Three ImageButton objects supply the actions on the Page:

  • Force a refresh of purchased goods from the Payment Service servers
  • Pop the StorePage from the stack, returning to the previous page
  • Remove all purchase records from the local cache to make it easier to test your app

The app uses the Boolean property busy to ensure that only one request to the Payment Service server is made at a time. The button to restore the user's purchases is enabled based on this Boolean value.

    Container {
        layout: DockLayout {
        }
        // Store background
        ImageView {
            scalingMethod: ScalingMethod.AspectFill
            horizontalAlignment: HorizontalAlignment.Fill
            verticalAlignment: VerticalAlignment.Fill
            imageSource: "asset:///images/backgroundLandscape.png"
        }

        // Banner add at the top of the store
        FreemiumBanner {
            scaleX: 2.0
            scaleY: 2.0
            // removeAdsPurchased is the bool defined in main.qml
            hideAd: navigationPane.removeAdsPurchased
            horizontalAlignment: HorizontalAlignment.Center
        }

        // ... Container of digital goods

        // Button to restore purchases from the server
        ImageButton {
            verticalAlignment: VerticalAlignment.Bottom
            horizontalAlignment: HorizontalAlignment.Center
            defaultImageSource: "asset:///images/restorePurchases.png"
            preferredWidth: 900
            enabled: ! storePaymentManager.busy
            onClicked: {
                storePaymentManager.busy = true;
                storePaymentManager.requestExistingPurchases(true);
            }
        }
    
        // Button to return to the previous page
        Container {
            horizontalAlignment: HorizontalAlignment.Left
            verticalAlignment: VerticalAlignment.Bottom
            leftPadding: 25
            bottomPadding: 25
            ImageButton {
                defaultImageSource: "asset:///images/ic_previous.png"
                onClicked: storePage.parent.pop()
            }
        }

        // Button to clear all previous purchases (for testing)
        Container {
            horizontalAlignment: HorizontalAlignment.Right
            verticalAlignment: VerticalAlignment.Bottom
            rightPadding: 25
            bottomPadding: 25
            ImageButton {
                defaultImageSource: "asset:///images/ic_delete.png"
                onClicked: PurchaseStore.deletePurchaseRecords()
            }
        }
    }

A Container in the UI contains all the digital goods that are available for purchase. The user can also purchase a digital good that removes the Banner ad from the UI. The StorePage component uses a custom component, DigitalGood, to define each digital good. We explore this custom component in Creating the digital good component.

In this sample app, the user is given one digital good for free but needs to purchase the other items. The "UFO" digital good is created with the owned property set to true when the app starts. For the other digital goods, the owned property isn't set, so its default value is false, meaning that the user doesn't own them yet. In the main.qml file, we created three Boolean values to represent the purchase state of these digital goods. We used this technique so that other functions in our app can track which digital goods have been purchased. For more information, see Exploring the UI.

            
            Container {
                layout: StackLayout {
                    orientation: LayoutOrientation.LeftToRight
                }

                DigitalGood {
                    id: ufo
                    owned: true
                    imageSource: "asset:///images/ufoThumb.png"
                    sku: "1"
                    name: "UFO"
                }
                DigitalGood {
                    id: tbeam
                    imageSource: "asset:///images/tbeamThumb.png"
                    sku: "2"
                    name: "T-Beam"
                    // This Boolean is defined in main.qml
                    onOwnedChanged: 
                        navigationPane.tbeamPurchased = owned
                }
                DigitalGood {
                    id: freakinLaserBeam
                    imageSource: "asset:///images/freakinLaserBeam.png"
                    sku: "3"
                    name: "Freakin Laser"
                    // This Boolean is defined in main.qml
                    onOwnedChanged: 
                        navigationPane.freakinLaserBeamPurchased = owned
                }
                DigitalGood {
                    id: noAds
                    imageSource: "asset:///images/noAds.png"
                    sku: "4"
                    name: "Remove Ads"
                    // This Boolean is defined in main.qml
                    onOwnedChanged: 
                        navigationPane.removeAdsPurchased = owned
                }
            }
        }

Last modified: 2013-12-21



Got questions about leaving a comment? Get answers from our Disqus FAQ.

comments powered by Disqus