Android in-app purchases
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.
here.
Migrating from Godot 3.2.1 and lower (GodotPaymentsV3)
GodotGooglePlayBilling API is not compatible with its predecessor GodotPaymentsV3.
Changes
GodotGooglePlayBillingplugin manually (see below for details)- requirement from Google. Purchases that are not acknowledged by your app will be refunded.
- Support for subscriptions
- Signals (no polling or callback objects)
Usage
Getting started
Android Custom Builds. Grab theGodotGooglePlayBillingplugin 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.Getting started
GodotGooglePlayBillingAPI you first have to get theGodotGooglePlayBillingsingleton and start the connection:var paymentfunc _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.")
payment.isReady()to check the connection status.Querying available items
querySkuDetails. Full example:func _on_connected(): payment.querySkuDetails(["my_iap_item"], "inapp") # "subs" for subscriptionsfunc _on_sku_details_query_completed(sku_details): for available_sku in sku_details: print(available_sku)
Purchase an item
purchase. You must query the SKU details for an item before you can initiate the purchase flow for it.payment.purchase("my_iap_item")
_on_purchases_updatedcallback 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
Check if the user purchased an item
queryPurchases. Unlike most of the other functions,queryPurchasesis 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. Full example:var query = payment.queryPurchases("inapp") # Or "subs" for subscriptionsif 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
Consumables
consumePurchasewith a purchase token. CallqueryPurchasesto get the purchase token. CallingconsumePurchaseautomatically acknowledges a purchase. Consuming a product allows the user to purchase it again, and removes it from appearing in subsequentqueryPurchasescalls.var query = payment.queryPurchases("inapp") # Or "subs" for subscriptionsif 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
Subscriptions
"subs"as second argument toquerySkuDetailsto get subscription details. Checkis_auto_renewingin the results ofqueryPurchases()to see if a user has cancelled an auto-renewing subscription
