应用程序内购买演示

一个完整的移动应用程序示例,演示了如何在应用程序中购买产品。

注意: Qt Purchasing 模块是 Qt 6.0 中移除的模块之一,其代码现在包含在这个示例中,作为如何使用 Qt 集成常见市场的指南。

这个演示是什么?

这个演示是基于经典的游戏 Hangman 的移动游戏应用程序,其中可以通过内置的商店购买元音字母。在游戏中,您将看到一行短横线,代表猜谜单词中的字母。通过猜测给定单词中出现的正确字母,字母将放置在对应的短横线下。猜测该单词的全部字母或任何时候正确猜测整个单词,游戏结束并获胜。如果猜测错误,则会在立体人形垂直图案上画出一部分。一旦图案完成,您的猜测次数就用完了,您就输了。

这个演示展示了在 Qt 应用程序内部提供应用程序内产品的方法,适用于 Android 和 iOS 平台。为了测试该示例中应用程序内购买功能,您必须首先在外部商店中注册应用程序及其产品。有关如何操作的介绍,请参阅 Google PlayApp Store 的指南。

第三方应用程序商店

在应用程序中查询或购买应用程序内产品之前,必须在这些目标商店中注册这些产品。我们建议在每个商店中为产品使用相同的标识符,因为这样可以简化查询和购买产品的代码。

演示是如何工作的

这个演示是一个 QML 应用程序,它将 QML 类型注册以访问有关应用程序内产品信息,以及请求购买这些产品。这些注册在目标平台的外部商店中。

通过首先添加 Store 对象将应用程序内购买添加到应用程序中。在演示中,Store 对象是由在应用程序启动时加载的 MainView 组件创建的。

Store {
    id: iapStore
}

演示定义了一个用于显示用于购买应用程序内产品的商店的组件。这些产品必须首先注册到我们前面在 MainView 中创建的 Store 对象。有两种可用产品,第一种是消耗品类型。

Product {
    id: product100Vowels
    store: iapStore
    type: Product.Consumable
    identifier: "qt.io.demo.hangman.100vowels"

    onPurchaseSucceeded: {
        console.log(identifier + " purchase successful");
        //Add 100 Vowels
        applicationData.vowelsAvailable += 100;
        transaction.finalize();
        pageStack.pop();
    }

    onPurchaseFailed: {
        console.log(identifier + " purchase failed");
        console.log("reason: "
                    + transaction.failureReason === Transaction.CanceledByUser ? "Canceled" : transaction.errorString);
        transaction.finalize();
    }
}

该消耗性产品提供了100个额外的元音字母,可用于游戏猜词环节。购买成功后,我们将更新应用程序的状态,包括100个额外的元音字母。然后,我们调用事务对象的finalize()方法,以向平台商店确认已提供消耗性产品。

第二种产品是一款不可消耗型产品,未来将永久解锁元音字母。除了更新购买时的应用程序状态外,我们还必须确保为最终用户使用的其他设备提供恢复购买的方式。在这种情况下,我们为onPurchaseRestored创建了一个信号处理器。

Product {
    id: productUnlockVowels
    type: Product.Unlockable
    store: iapStore
    identifier: "qt.io.demo.hangman.unlockvowels"

    onPurchaseSucceeded: {
        console.log(identifier + " purchase successful");
        applicationData.vowelsUnlocked = true;
        transaction.finalize();
        pageStack.pop();
    }

    onPurchaseFailed: {
        console.log(identifier + " purchase failed");
        console.log("reason: "
                    + transaction.failureReason === Transaction.CanceledByUser ? "Canceled" : transaction.errorString);
        transaction.finalize();
    }

    onPurchaseRestored: {
        console.log(identifier + " purchase restored");
        applicationData.vowelsUnlocked = true;
        console.log("timestamp: " + transaction.timestamp);
        transaction.finalize();
        pageStack.pop();
    }
}

除注册产品外,该演示还提供了一个实际购买注册产品的接口。演示定义了一个自定义组件StoreItem,用于显示和处理购买交互。

Product {
    id: productUnlockVowels
    type: Product.Unlockable
    store: iapStore
    identifier: "qt.io.demo.hangman.unlockvowels"

    onPurchaseSucceeded: {
        console.log(identifier + " purchase successful");
        applicationData.vowelsUnlocked = true;
        transaction.finalize();
        pageStack.pop();
    }

    onPurchaseFailed: {
        console.log(identifier + " purchase failed");
        console.log("reason: "
                    + transaction.failureReason === Transaction.CanceledByUser ? "Canceled" : transaction.errorString);
        transaction.finalize();
    }

    onPurchaseRestored: {
        console.log(identifier + " purchase restored");
        applicationData.vowelsUnlocked = true;
        console.log("timestamp: " + transaction.timestamp);
        transaction.finalize();
        pageStack.pop();
    }
}

StoreItem组件将显示从平台商店查询到的产品数据,当用户点击时,将调用产品的purchase()方法。

Text {
    id: titleText
    text: product.title
    font.bold: true
    anchors.right: priceText.left
    anchors.rightMargin: topLevel.globalMargin
    anchors.top: parent.top
    anchors.topMargin: topLevel.globalMargin
    anchors.left: parent.left
    anchors.leftMargin: topLevel.globalMargin
}

Text {
    id: descriptionText
    text: product.description
    anchors.right: priceText.left
    anchors.rightMargin: topLevel.globalMargin
    anchors.left: parent.left
    anchors.leftMargin: topLevel.globalMargin
    anchors.top: titleText.bottom
    anchors.topMargin: topLevel.globalMargin / 2
    wrapMode: Text.WordWrap
}

Text {
    id: priceText
    text: product.price
    anchors.right: parent.right
    anchors.rightMargin: topLevel.globalMargin
    anchors.verticalCenter: parent.verticalCenter
}

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";
    }
}

Android和iOS使用基类。从基类派生出针对android和iOS的派生类

内购

内购是盈利应用程序的一种方式。这些购买是在应用程序内进行的,可以包括从解锁内容到虚拟物品等任何东西。该演示使用系统内购API,这意味着购买过程更加熟悉,并且可以复用平台已存储的信息(如信用卡信息),以简化购买过程。

许可证和归属权

关于将演示部署到Android,请参阅Android GNU C++ 运行时许可证以获取更多信息。

示例项目 @ code.qt.io

© 2024 The Qt Company Ltd. 本文档的贡献是各自所有者的版权。本文档是根据自由软件基金会发布的GNU自由文档许可协议版本1.3的条款许可的。Qt和相应的标志是The Qt Company Ltd.在芬兰以及/或全球其他国家的商标。所有其他商标均为其各自所有者的财产。