In-App Purchasing of Registered Product (google store)
-
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 textGoogleStore.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.qmlRectangle { 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
-
@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 wrongOn google play I was missing the following.
- I was in internal testing and the app had not been published, i published to closed testing.
- Add licence testers to the app in google play console (this is different than the release track email list)
- 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