Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. In-App Purchasing of Registered Product (google store)
QtWS25 Last Chance

In-App Purchasing of Registered Product (google store)

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
purchasingstoreandroidinappregistertype
2 Posts 1 Posters 413 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • F Offline
    F Offline
    Fitndex-developer
    wrote on 31 Mar 2022, 18:07 last edited by
    #1

    Hello All,

    I'm in Qt. 5.15.1 and am working with an in-app product. I have set my store up in a qtquick application using qtpurchasing qml type. But am unable to confirm that the product is registered in my app. I hope someone can pick up on what I'm missing here.

    app name: com.fitndex.theApp
    version: 4.0 (as of now)
    product identifier: 30day_data_access (this is the product id on google play console)
    the product is active on google play console. image: inapp_products.png link text
    The package has been uploaded to google play and is currently the active internal-testing tracking version (version 4.0). link text

    .pro

    CONFIG += qmltypes
    QML_IMPORT_NAME = com.fitndex.theApp
    QML_IMPORT_MAJOR_VERSION = 4
    

    main.cpp

    qmlRegisterType<Helper>("com.fitndex.theApp", 4, 0, "Helper");
    

    android manifest
    link text

    GoogleStore.qml

    import QtQuick 2.0
    import QtPurchasing 1.0
    import com.fitndex.theApp 4.0
    
    Store {
       signal updateStatus
       signal assignProduct1(var product1)
    
       id: play_Store
       property bool bool_premium_access: false
       property bool bool_premium_plus: false
       property bool bool_monthly_access_status: false
       property bool bool_monthly_access_registered: false
    
       Product {
          id: fitndex_premium
          identifier: "com.fitndex.theApp.30day_data_access"
          type: Product.Consumable
          property bool purchasing: false
    
          onPurchaseSucceeded: {
             if (!hasAlreadyStoredTransaction(transaction.orderId)) {
                bool_premium_access = true
                 updateStatus()
                if (!add30Day_data_accessToPersistentStorage(transaction.orderId)) {
                   console.log("Unable to write to persistent storage. Please make sure there is sufficient space and restart.")
                    //send to c++ and store to sqlite & server
                } else {
                   transaction.finalize()
                    //send to c++ and store to sqlite & server
                }
             }
             // Reset purchasing flag
             purchasing = false
          }
    
          onPurchaseFailed: {
             console.log("Purchase not completed.")
             bool_premium_access = false
             transaction.finalize()
    
             // Reset purchasing flag
             purchasing = false
          }
          Component.onCompleted: {
              assignProduct1(fitndex_premium)
              bool_monthly_access_status = fitndex_premium.status
              bool_monthly_access_registered = fitndex_premium.Registered
    
          }
       }
       
    }
    
    

    main.qml

    StackView {
            id: stackView
            anchors.fill: parent
            Loader {
                id: googleStoreLoader
                active: false
                GoogleStore {
                    id: google_store
                    onUpdateStatus: {
                        monthly_access = google_store.bool_premium_access
                        training_program = google_store.bool_premium_plus
                    }
                    onAssignProduct1: {
                        fitndex_premium = product1
                        exercise_data_entry_dist.product = product1
                        console.log("product 1", fitndex_premium, google_store.bool_monthly_access_status, google_store.bool_monthly_access_registered)
                        boot_page.product_name = fitndex_premium.identifier
                        boot_page.fitndex_premium_status = google_store.bool_monthly_access_status
                        boot_page.fitndex_premium_registered = google_store.bool_monthly_access_registered
    
                    }
                    
                }
            }
    

    When the user attempts to log a distance exercise such as run, row or cycling.
    link text
    ExerciseDataEntry.qml

    Rectangle {
            id: storeRect
            anchors.fill: parent
            color: "ghostwhite"
            visible: false
            z: 20
            Rectangle {
                id: storeItem
                anchors.centerIn: parent
                height: topWindow.width*0.50
                width: height
    
                state: "NORMAL"
    
                radius: 10
                color: "green"
    
                // ![0]
                Text {
                    id: titleText
                    text: product.title
                    font.bold: true
                    anchors.horizontalCenter: parent.horizontalCenter
                    anchors.top: parent.top
                    color: "white"
                }
                Text {
                    id: descriptionText
                    text: product.description
                    anchors.horizontalCenter: parent.horizontalCenter
                    anchors.top: titleText.bottom
                    wrapMode: Text.WordWrap
                    color: "gray"
                }
    
                Text {
                    id: priceText
                    text: product.price
                    anchors.horizontalCenter: parent.horizontalCenter
                    anchors.top: descriptionText.bottom
                    color: themePrimary
                }
    
                MouseArea {
                    anchors.fill: parent
                    onClicked: {
                        pendingRect.visible = true;
                        spinBox.visible = true;
                        statusText.text = "Purchasing...";
                        storeItem.state = "PURCHASING";
                        product.purchase();
                    }
                    onPressed: {
                        storeItem.state = "PRESSED";
                    }
                    onReleased: {
                        storeItem.state = "NORMAL";
                    }
                }
                // ![0]
    
                Rectangle {
                    id: pendingRect
                    anchors.fill: parent
                    opacity: 1
                    color: "gray"
                    radius: parent.radius
                    visible: false
                    Text {
                        id: statusText
                        anchors.top: parent.top
                        anchors.bottom: parent.bottom
                        anchors.left: parent.left
                        anchors.right: spinBox.left
                        anchors.margins: topWindow.width*0.025
                        verticalAlignment: Text.AlignVCenter
                    }
                    BusyIndicator {
                        id: spinBox
                        anchors.top: parent.top
                        anchors.bottom: parent.bottom
                        anchors.right: parent.right
                        anchors.margins: topWindow.width*0.025
                        width: height
    
                    }
    
                    Connections {
                        target: product
                        onPurchaseSucceeded: {
                            statusText.text = "Purchase Succeeded";
                            spinBox.visible = false;
    
                        }
                        onPurchaseFailed: {
                            statusText.text = "Purchase Failed";
                            spinBox.visible = false;
                            storeItem.state = "NORMAL";
                        }
                    }
                }
    
                states: [
                    State {
                        name: "NORMAL"
                        PropertyChanges {
                            target: storeItem
                            color: "yellow"
                            border.color: "transparent"
                        }
                        PropertyChanges {
                            target: pendingRect
                            opacity: 0.0
                        }
                    },
                    State {
                        name: "PRESSED"
                        PropertyChanges {
                            target: storeItem
                            color: "blue"
                            border.color: "white"
                        }
                    },
                    State {
                        name: "PURCHASING"
                        PropertyChanges {
                            target: pendingRect
                            opacity: 1.0
                            color: "orange"
                        }
                    }
                ]
    
                transitions: [
                    Transition {
                        from: "PURCHASING"
                        to: "NORMAL"
                        NumberAnimation { target: pendingRect; property: "opacity"; duration: 2000; easing.type: Easing.InExpo }
                    }
                ]
            }
    
        }
    

    console when attempt to purchase

    W libFITNDEX_android_beta_v14_arm64-v8a.so: Attempted to purchase unregistered product
    
    1 Reply Last reply
    0
    • F Offline
      F Offline
      Fitndex-developer
      wrote on 11 Apr 2022, 16:23 last edited by
      #2

      @Fitndex-developer said in In-App Purchasing of Registered Product (google store):

      com.fitndex.theApp

      Hello Everyone,

      since there has been no activity on this post, I thought I'd let everyone know that this setup works with one change in the code:

      do not include the app name in the identifier.

      identifier: 30day_data_access ... is correct
      identifier com.fitndex.theApp.30day_data_access ... is wrong

      On google play I was missing the following.

      1. I was in internal testing and the app had not been published, i published to closed testing.
      2. Add licence testers to the app in google play console (this is different than the release track email list)
      3. If using the same app version code as the published version, testing will work, even when plugged in for debug, if you are logged into the tester gmail account.

      I took a crack at developing subscriptions in java, and for me, that is going to take a while but I will finish (the jni messenger example in android extras helps start with communicating with java if you are new to that), Qt purchasing makes life a lot easier just most of your work is going to be on the google play console side when dealing with Qt Purchasing. So if things are not working, check your settings with google (or apple), that is most likely it.

      Qt purchasing does not handle subscriptions, it will never find your subscriptions no matter what. The reason for that is the developers could not come up with a platform independent solution for subscriptions. The community needs to figure this one out for everyone. An example anyone?

      Since monetization is so important; and documentation/examples on qt purchasing are minimal, I hope this helps some of you!! I could have used something like this when I was working on it.

      FITNDEX HOME now we are on track to launch this summer. You can join the beta on website.

      Lets help each other get to market. The more money we all make, the better Qt will get, I promise.

      Steve

      1 Reply Last reply
      0

      • Login

      • Login or register to search.
      • First post
        Last post
      0
      • Categories
      • Recent
      • Tags
      • Popular
      • Users
      • Groups
      • Search
      • Get Qt Extensions
      • Unsolved