Android In-App Käufe

Godot offers a first-party GodotGooglePlayBilling Android plugin since Godot 3.2.2. The new plugin uses the Google Play Billing library instead of the now deprecated AIDL IAP implementation.

Wenn Sie anhand eines Beispiels besser lernen, finden Sie das Demo-Projekt hier.

Migrieren von Godot 3.2.1 und kleiner (GodotPaymentsV3)

Die neue GodotGooglePlayBilling API ist nicht mit dem Vorgänger GodotPaymentsV3 kompatibel.

Veränderungen

  • Sie müssen die Benutzerdefinierte Build-Option in Ihren Android-Exporteinstellungen aktivieren und das Plugin GodotGooglePlayBilling manuell installieren (Details siehe unten).

  • All purchases have to be acknowledged by your app. This is a requirement from Google. Purchases that are not acknowledged by your app will be refunded.

  • Unterstützung für Abonnements

  • Signale (keine Abruf- oder Rückrufobjekte)

Nutzung

Erste Schritte

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.

Erste Schritte

To use the GodotGooglePlayBilling API you first have to get the GodotGooglePlayBilling singleton and start the connection:

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.")

Alle API-Methoden funktionieren nur, wenn die API verbunden ist. Sie können payment.isReady() verwenden, um den Verbindungsstatus zu überprüfen.

Verfügbare Elemente abfragen

Sobald die API verbunden ist, können Sie SKUs mit querySkuDetails abfragen.

Ein komplettes Beispiel:

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)

Einen Artikel kaufen

To initiate the purchase flow for an item, call purchase. You must query the SKU details for an item before you can initiate the purchase flow for it.

payment.purchase("my_iap_item")

Then, wait for the _on_purchases_updated callback and handle the purchase result:

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

Prüfen Sie, ob der Nutzer einen Artikel gekauft hat

To get all purchases, call queryPurchases. Unlike most of the other functions, queryPurchases is a synchronous operation and returns a Dictionary with a status code and either an array of purchases or an error message. Only active subscriptions and non-consumed one-time purchases are returned.

Ein komplettes Beispiel:

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

Käufliches

If your in-app item is not a one-time purchase but a consumable item (e.g. coins) which can be purchased multiple times, you can consume an item by calling consumePurchase with a purchase token. Call queryPurchases to get the purchase token. Calling consumePurchase automatically acknowledges a purchase. Consuming a product allows the user to purchase it again, and removes it from appearing in subsequent queryPurchases calls.

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

Abonnements

Subscriptions don't work much different from regular in-app items. Just use "subs" as second argument to querySkuDetails to get subscription details. Check is_auto_renewing in the results of queryPurchases() to see if a user has cancelled an auto-renewing subscription