Android 应用内购买

自 Godot 3.2.2 以来,Godot提供了一个第一方的 GodotGooglePlayBilling Android 插件。新插件使用 Google Play Billing 库,而不是现在已经废弃的 AIDL IAP 实现。

If you learn better by looking at an example, you can find the demo project here.

从 Godot 3.2.1 和更低版本迁移(GodotPaymentsV3)

新的 GodotGooglePlayBilling API 与其前身 GodotPaymentsV3 不兼容。

修改

  • 你需要在你的 Android 导出设置中启用 Custom Build 选项,并手动安装 GodotGooglePlayBilling 插件(详见下文)

  • 所有的购买都必须被你的应用程序所确认。这是 Google 的要求。您的应用程序未确认的购买将被退款。

  • 支持订阅

  • 信号(没有轮询或回调对象)

用法

入门

If not already done, make sure you have enabled and successfully set up Android Custom Builds. Grab the``GodotGooglePlayBilling`` plugin binary and config from the releases page and put both into res://android/plugins. The plugin should now show up in the Android export settings, where you can enable it.

入门

要使用 GodotGooglePlayBilling API, 你首先要获得 GodotGooglePlayBilling 单例, 并启动连接:

var payment

func _ready():
    if Engine.has_singleton("GodotGooglePlayBilling"):
        payment = Engine.get_singleton("GodotGooglePlayBilling")

        # These are all signals supported by the API
        # You can drop some of these based on your needs
        payment.connect("connected", self, "_on_connected") # No params
        payment.connect("disconnected", self, "_on_disconnected") # No params
        payment.connect("connect_error", self, "_on_connect_error") # Response ID (int), Debug message (string)
        payment.connect("purchases_updated", self, "_on_purchases_updated") # Purchases (Dictionary[])
        payment.connect("purchase_error", self, "_on_purchase_error") # Response ID (int), Debug message (string)
        payment.connect("sku_details_query_completed", self, "_on_sku_details_query_completed") # SKUs (Dictionary[])
        payment.connect("sku_details_query_error", self, "_on_sku_details_query_error") # Response ID (int), Debug message (string), Queried SKUs (string[])
        payment.connect("purchase_acknowledged", self, "_on_purchase_acknowledged") # Purchase token (string)
        payment.connect("purchase_acknowledgement_error", self, "_on_purchase_acknowledgement_error") # Response ID (int), Debug message (string), Purchase token (string)
        payment.connect("purchase_consumed", self, "_on_purchase_consumed") # Purchase token (string)
        payment.connect("purchase_consumption_error", self, "_on_purchase_consumption_error") # Response ID (int), Debug message (string), Purchase token (string)

        payment.startConnection()
    else:
        print("Android IAP support is not enabled. Make sure you have enabled 'Custom Build' and the GodotGooglePlayBilling plugin in your Android export settings! IAP will not work.")

所有的 API 方法只有在 API 被连接的情况下才会工作,你可以使用 payment.isReady() 检查连接状态。

查询可获取的项目

只要连接了 API,你就可以使用 querySkuDetails 来查询 SKU。

完整示例:

func _on_connected():
  payment.querySkuDetails(["my_iap_item"], "inapp") # "subs" for subscriptions

func _on_sku_details_query_completed(sku_details):
  for available_sku in sku_details:
    print(available_sku)

购买项目

要启动一个项目的购买流程,请调用 purchase。在启动购买流程之前,你必须查询该项目的 SKU 详情。

payment.purchase("my_iap_item")

然后,等待 _on_purchases_updated 回调并处理购买结果:

func _on_purchases_updated(purchases):
    for purchase in purchases:
        if purchase.purchase_state == 1: # 1 means "purchased", see https://developer.android.com/reference/com/android/billingclient/api/Purchase.PurchaseState#constants_1
            # enable_premium(purchase.sku) # unlock paid content, add coins, save token on server, etc. (you have to implement enable_premium yourself)
            if not purchase.is_acknowledged:
                payment.acknowledgePurchase(purchase.purchase_token) # call if non-consumable product
                if purchase.sku in list_of_consumable_products:
                    payment.consumePurchase(purchase.purchase_token) # call if consumable product

检查用户是否购买了某个项目

要获得所有的购买,请调用 queryPurchases。与大多数其他函数不同的是,queryPurchases 是一个同步操作,会返回一个 Dictionary,其中包含状态码和一个购买数组或一个错误信息。只会返回处于活跃状态的订阅和尚未消耗的一次性购买。

完整示例:

var query = payment.queryPurchases("inapp") # Or "subs" for subscriptions
if query.status == OK:
    for purchase in query.purchases:
        if purchase.sku == "my_iap_item" and purchase.purchase_state == 1:
            # enable_premium(purchase.sku) # unlock paid content, save token on server, etc.
            if !purchase.is_acknowledged:
                payment.acknowledgePurchase(purchase.purchase_token)
                # Or wait for the _on_purchase_acknowledged callback before giving the user what they bought

消耗品

如果你的应用内物品不是一次性购买,而是可以多次购买的消耗品(如硬币),你可以用购买令牌调用 consumePurchase 来消耗物品。调用 queryPurchases 来获取购买令牌。调用 consumePurchase 会自动确认购买。消耗产品后,用户就可以再一次进行购买,同时也会将其从后续 queryPurchases 的返回中移除。

var query = payment.queryPurchases("inapp") # Or "subs" for subscriptions
if query.status == OK:
    for purchase in query.purchases:
        if purchase.sku == "my_consumable_iap_item" and purchase.purchase_state == 1:
            # enable_premium(purchase.sku) # add coins, save token on server, etc.
            payment.consumePurchase(purchase.purchase_token)
            # Or wait for the _on_purchase_consumed callback before giving the user what they bought

订阅

订阅的工作原理和普通的应用内项目没有太大区别. 只要使用 "subs" 作为 querySkuDetails 的第二个参数, 就可以得到订阅的详细信息. 在 queryPurchases() 的结果中检查 is_auto_renewing 来查看用户是否取消了自动更新的订阅