### Example Product IDs Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/google_play_console_setup.md These identifiers must match the product IDs defined in the Godot project code exactly. ```text coins_100 remove_ads premium_upgrade ``` -------------------------------- ### Initiate Purchase Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/methods.md Starts the purchase flow for a product. Ensure product details are fetched before calling this method. ```gdscript func purchase(product_id: String, purchase_option_id: String = "", offer_id: String = "", is_offer_personalized: bool = false) -> Dictionary ``` ```gdscript billing_client.purchase("coins_100", premium_purchase_id, new_login_offer_id) # billing_client.purchase("coins_100") ``` -------------------------------- ### Manual Installation Directory Structure Source: https://context7.com/godot-sdk-integrations/godot-google-play-billing/llms.txt This shows the required directory structure for manual installation of the GodotGooglePlayBilling plugin. ```plaintext your_project/ addons/ GodotGooglePlayBilling/ export_scripts/ BillingClient.gd export_plugin.gd plugin.cfg ``` -------------------------------- ### purchase_subscription Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/methods.md Starts the purchase flow for a subscription product. ```APIDOC ## purchase_subscription ### Description Starts the purchase flow for a subscription product. The product must first be fetched using query_product_details before attempting to purchase. ### Parameters #### Request Body - **product_id** (String) - Required - Subscription product identifier defined in Google Play Console. - **base_plan_id** (String) - Required - Base plan ID configured for the subscription. - **offer_id** (String) - Optional - Optional offer ID defined under the base plan. - **is_offer_personalized** (bool) - Optional - Indicates whether the price is personalized for the user. ### Response - **Dictionary** - Returns a dictionary describing whether the billing flow launched successfully. ``` -------------------------------- ### Initialize Billing Connection and Query Products Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/billing_client.md Connect to the Google Play Billing service and query product details. Ensure the `connected` signal is connected before calling `start_connection()`. This example queries for 'coins_100' in-app products. ```gdscript var billing_client := BillingClient.new() func _ready(): billing_client.connected.connect(_on_connected) billing_client.start_connection() func _on_connected(): var productIds = ["coins_100"] billing_client.query_product_details(productIds, BillingClient.ProductType.INAPP) ``` -------------------------------- ### Initiate In-App Product Purchase Source: https://context7.com/godot-sdk-integrations/godot-google-play-billing/llms.txt Use the `purchase()` method to start the purchase flow for in-app products. Ensure the product has been queried first. This function can optionally take offer details. ```gdscript func buy_product(product_id: String): # Simple purchase var result = billing_client.purchase(product_id) if result.response_code != BillingClient.BillingResponseCode.OK: print("Failed to launch billing flow: %s" % result.debug_message) return print("Billing flow launched successfully") # With optional parameters for offers func buy_product_with_offer(product_id: String, purchase_option_id: String, offer_id: String): var result = billing_client.purchase(product_id, purchase_option_id, offer_id, false) if result.response_code == BillingClient.BillingResponseCode.OK: print("Billing flow launched") func _on_purchase_updated(result: Dictionary): if result.response_code == BillingClient.BillingResponseCode.USER_CANCELED: print("User cancelled the purchase") return if result.response_code != BillingClient.BillingResponseCode.OK: print("Purchase failed: %s" % result.debug_message) return for purchase in result.purchases: print("Purchased products: %s" % str(purchase.product_ids)) print("Purchase token: %s" % purchase.purchase_token) print("Order ID: %s" % purchase.order_id) process_purchase(purchase) ``` -------------------------------- ### Implement Google Play Billing Flow in GDScript Source: https://context7.com/godot-sdk-integrations/godot-google-play-billing/llms.txt A comprehensive example demonstrating the lifecycle of a billing client, from connection initialization to purchase consumption and entitlement application. ```gdscript extends Node var billing_client: BillingClient var available_products: Dictionary = {} # product_id -> product_details var owned_products: Dictionary = {} # product_id -> purchase_token @export var product_ids: Array[String] = ["coins_100", "premium_upgrade", "remove_ads"] func _ready(): billing_client = BillingClient.new() billing_client.connected.connect(_on_connected) billing_client.connect_error.connect(_on_connect_error) billing_client.query_product_details_response.connect(_on_product_details) billing_client.query_purchases_response.connect(_on_purchases_queried) billing_client.on_purchase_updated.connect(_on_purchase_updated) billing_client.consume_purchase_response.connect(_on_consume_response) billing_client.acknowledge_purchase_response.connect(_on_acknowledge_response) billing_client.start_connection() func _on_connected(): # First restore existing purchases billing_client.query_purchases(BillingClient.ProductType.INAPP) await billing_client.query_purchases_response # Then query available products billing_client.query_product_details(product_ids, BillingClient.ProductType.INAPP) func _on_connect_error(code: int, msg: String): push_error("Billing connection failed: %d - %s" % [code, msg]) func _on_product_details(result: Dictionary): if result.response_code != BillingClient.BillingResponseCode.OK: return available_products.clear() for product in result.product_details: available_products[product.product_id] = product func _on_purchases_queried(result: Dictionary): if result.response_code != BillingClient.BillingResponseCode.OK: return for purchase in result.purchases: if purchase.purchase_state == BillingClient.PurchaseState.PURCHASED: for pid in purchase.product_ids: owned_products[pid] = purchase.purchase_token apply_product_entitlement(pid) func buy(product_id: String): if not billing_client.is_ready(): push_error("Billing not ready") return if owned_products.has(product_id): push_error("Already owned: %s" % product_id) return var result = billing_client.purchase(product_id) if result.response_code != BillingClient.BillingResponseCode.OK: push_error("Purchase launch failed: %s" % result.debug_message) func _on_purchase_updated(result: Dictionary): if result.response_code != BillingClient.BillingResponseCode.OK: return for purchase in result.purchases: if purchase.purchase_state != BillingClient.PurchaseState.PURCHASED: continue for pid in purchase.product_ids: owned_products[pid] = purchase.purchase_token if is_consumable(pid): billing_client.consume_purchase(purchase.purchase_token) elif not purchase.is_acknowledged: billing_client.acknowledge_purchase(purchase.purchase_token) else: apply_product_entitlement(pid) func _on_consume_response(result: Dictionary): if result.response_code == BillingClient.BillingResponseCode.OK: # Find and apply the consumable for pid in owned_products.keys(): if owned_products[pid] == result.token: apply_product_entitlement(pid) owned_products.erase(pid) break func _on_acknowledge_response(result: Dictionary): if result.response_code == BillingClient.BillingResponseCode.OK: for pid in owned_products.keys(): if owned_products[pid] == result.token: apply_product_entitlement(pid) break func is_consumable(product_id: String) -> bool: return product_id in ["coins_100"] func apply_product_entitlement(product_id: String): match product_id: "coins_100": GameData.coins += 100 "premium_upgrade": GameData.is_premium = true "remove_ads": GameData.ads_removed = true GameData.save() func _notification(what: int): if what == NOTIFICATION_WM_GO_BACK_REQUEST: if billing_client: billing_client.end_connection() ``` -------------------------------- ### Start Google Play Billing Connection Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/methods.md Initializes the connection to the Google Play Billing service. Must be called before any other billing operations. ```gdscript func start_connection() -> void ``` -------------------------------- ### Handle query_purchases_response signal Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/signals.md Example callback function to process the result of a purchase query, checking for a successful response code before iterating through owned products. ```gdscript func _on_query_purchases_response(result): if result.response_code == BillingClient.BillingResponseCode.OK: for purchase in result.purchases: print("Owned:", purchase.product_ids) ``` -------------------------------- ### Get Connection State Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/methods.md Retrieves the current connection state of the billing client. ```APIDOC ## get_connection_state ### Description Returns the current connection state of the billing client. ### Method GET ### Endpoint /godot-sdk-integrations/godot-google-play-billing ### Response #### Success Response (200) - **connection_state** (int) - An integer representing a value from `ConnectionState` enum. ### Response Example ```gdscript var state = billing_client.get_connection_state() if state == BillingClient.ConnectionState.CONNECTED: print("Billing ready") ``` ``` -------------------------------- ### Get Connection State Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/methods.md Retrieves the current connection status of the billing client. ```gdscript func get_connection_state() -> int ``` ```gdscript var state = billing_client.get_connection_state() if state == BillingClient.ConnectionState.CONNECTED: print("Billing ready") ``` -------------------------------- ### Initiate Subscription Purchase Source: https://context7.com/godot-sdk-integrations/godot-google-play-billing/llms.txt Use `purchase_subscription()` for subscriptions, providing the product ID, base plan ID, and optionally an offer ID. This method launches the subscription purchase flow. ```gdscript func buy_subscription(product_id: String, base_plan_id: String, offer_id: String = ""): var result = billing_client.purchase_subscription(product_id, base_plan_id, offer_id, false) if result.response_code != BillingClient.BillingResponseCode.OK: print("Failed to launch subscription flow: %s" % result.debug_message) return print("Subscription flow launched") # Example: Purchase monthly premium subscription func buy_monthly_premium(): billing_client.purchase_subscription("premium_sub", "monthly", "first_month_free") ``` -------------------------------- ### Purchase Subscription Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/methods.md Initiates the subscription purchase flow. Ensure product details are fetched via query_product_details before calling this. ```gdscript func purchase_subscription(product_id: String, base_plan_id: String, offer_id: String = "", is_offer_personalized: bool = false) -> Dictionary ``` -------------------------------- ### Define and handle query_product_details_response signal Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/signals.md Emitted after query_product_details finishes to return product information. ```gdscript signal query_product_details_response(response: Dictionary) ``` ```gdscript func _on_query_product_details_response(result): if result.response_code == BillingClient.BillingResponseCode.OK: for product in result.product_details: print(product) ``` -------------------------------- ### start_connection Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/methods.md Initializes the connection to the Google Play Billing service. This must be called before any other billing operations. ```APIDOC ## start_connection ### Description Starts the connection to the Google Play Billing service. The client must be connected before using any billing features. ### Method void ### Response - **connected** (signal) - Emitted on successful connection. - **connect_error** (signal) - Emitted if the connection fails. ``` -------------------------------- ### Initialize BillingClient and Connect Signals Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/quickstart.md Instantiate the BillingClient, connect to its signals for billing events, and initiate the connection to the Google Play Billing service. Ensure the API is connected before making further calls. ```gdscript var billing_client: BillingClient func _ready(): billing_client = BillingClient.new() billing_client.connected.connect(_on_connected) # No params billing_client.disconnected.connect(_on_disconnected) # No params billing_client.connect_error.connect(_on_connect_error) # response_code: int, debug_message: String billing_client.query_product_details_response.connect(_on_query_product_details_response) # response: Dictionary billing_client.query_purchases_response.connect(_on_query_purchases_response) # response: Dictionary billing_client.on_purchase_updated.connect(_on_purchase_updated) # response: Dictionary billing_client.consume_purchase_response.connect(_on_consume_purchase_response) # response: Dictionary billing_client.acknowledge_purchase_response.connect(_on_acknowledge_purchase_response) # response: Dictionary billing_client.start_connection() ``` -------------------------------- ### Is Ready Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/methods.md Checks if the billing client is connected and ready for use. ```APIDOC ## is_ready ### Description Returns `true` if the billing client is connected and ready for use. ### Method GET ### Endpoint /godot-sdk-integrations/godot-google-play-billing ### Response #### Success Response (200) - **ready** (bool) - `true` if the client is ready, `false` otherwise. ``` -------------------------------- ### Purchase Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/methods.md Initiates the purchase flow for an in-app product. Products must be fetched using `query_product_details(...)` before purchase. ```APIDOC ## purchase ### Description Starts the purchase flow for an in-app product. ### Method POST ### Endpoint /godot-sdk-integrations/godot-google-play-billing ### Parameters #### Path Parameters - **product_id** (String) - Required - Identifier of the in-app product configured in the Google Play Console. - **purchase_option_id** (String) - Optional - Purchase option identifier returned from `query_product_details_response`. Used when the product has multiple purchase options. - **offer_id** (String) - Optional - Offer identifier associated with the selected purchase option. - **is_offer_personalized** (bool) - Optional - Indicates whether the price is personalized for the user. ### Request Example ```gdscript billing_client.purchase("coins_100", premium_purchase_id, new_login_offer_id) # billing_client.purchase("coins_100") ``` ### Response #### Success Response (200) - **launch_result** (Dictionary) - A dictionary describing whether the billing flow launched successfully. Final purchase results are delivered through the `on_purchase_updated` signal. ``` -------------------------------- ### query_product_details_response Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/signals.md Emitted after query_product_details finishes. ```APIDOC ## query_product_details_response ### Description Emitted after query_product_details finishes. ### Response - **response_code** (int) - A value from BillingResponseCode. - **debug_message** (String) - Debug message returned by Google Play. - **product_details** (Array) - Array of product details dictionaries. ``` -------------------------------- ### Launch Billing Flow in GDScript Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/quickstart.md Initiates the purchase flow for an in-app item. Product details must be queried before calling this method. ```gdscript var result = billing_client.purchase("my_iap_item") if result.response_code == BillingClient.BillingResponseCode.OK: print("Billing flow launch success") else: print("Billing flow launch failed") print("response_code: ", result.response_code, "debug_message: ", result.debug_message) ``` -------------------------------- ### Query Subscription Products Source: https://context7.com/godot-sdk-integrations/godot-google-play-billing/llms.txt Use `query_product_details()` with `ProductType.SUBS` to retrieve available subscription products. Handle the response to access product details and their associated offers. ```gdscript func query_subscriptions(): var subscription_products = ["monthly_premium", "yearly_premium"] billing_client.query_product_details(subscription_products, BillingClient.ProductType.SUBS) func _on_query_product_details_response(result: Dictionary): if result.response_code != BillingClient.BillingResponseCode.OK: return for product in result.product_details: print("Subscription: %s" % product.product_id) # Subscription pricing is available in subscription_offer_details var subscription_offers = product.get("subscription_offer_details", []) for offer in subscription_offers: print("Base Plan: %s" % offer.get("base_plan_id", "")) print("Offer ID: %s" % offer.get("offer_id", "")) ``` -------------------------------- ### query_product_details Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/methods.md Queries product information from the Google Play Console. ```APIDOC ## query_product_details ### Description Queries product information. This must be called before attempting to purchase products. ### Parameters #### Request Body - **product_list** (PackedStringArray) - Required - List of product IDs configured in Google Play Console. - **product_type** (ProductType) - Required - Enum value indicating the product type being queried. ``` -------------------------------- ### Query Product Details Source: https://context7.com/godot-sdk-integrations/godot-google-play-billing/llms.txt Query product details from Google Play using `query_product_details()` before initiating purchases. This function requires an array of product IDs and the product type (INAPP or SUBS). Handle the response to display product information and prices. ```gdscript func _on_connected(): # Query in-app products (one-time purchases, consumables) var inapp_products = ["coins_100", "premium_upgrade", "remove_ads"] billing_client.query_product_details(inapp_products, BillingClient.ProductType.INAPP) func _on_query_product_details_response(result: Dictionary): if result.response_code != BillingClient.BillingResponseCode.OK: print("Query failed: %s" % result.debug_message) return print("Found %d products" % result.product_details.size()) for product in result.product_details: print("Product ID: %s" % product.product_id) print("Name: %s" % product.name) print("Description: %s" % product.description) # Get price from one-time purchase offer details var offers = product.get("one_time_purchase_offer_details_list", []) for offer in offers: if offer.get("offer_id", "") == null: print("Price: %s" % offer.get("formatted_price", "N/A")) ``` -------------------------------- ### Query Product Details Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/methods.md Retrieves information for specific products. This must be called before attempting any purchases. ```gdscript func query_product_details(product_list: PackedStringArray, product_type: ProductType) ``` ```gdscript var product_ids = ["coins_100", "premium_potion"] billing_client.query_product_details(products_ids, BillingClient.ProductType.INAPP) ``` -------------------------------- ### Check Readiness Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/methods.md Checks if the billing client is connected and ready for operations. ```gdscript func is_ready() -> bool ``` -------------------------------- ### Create BillingClient Instance Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/billing_client.md Instantiate the BillingClient before initiating any billing operations. This client communicates with the Android plugin via a JNI singleton. ```gdscript var billing_client := BillingClient.new() ``` -------------------------------- ### Query User Purchases in GDScript Source: https://context7.com/godot-sdk-integrations/godot-google-play-billing/llms.txt Retrieve unconsumed purchases on app startup to restore user entitlements. ```gdscript func restore_purchases(): # Query in-app purchases billing_client.query_purchases(BillingClient.ProductType.INAPP) func restore_subscriptions(include_suspended: bool = false): # Query subscriptions, optionally including suspended ones billing_client.query_purchases(BillingClient.ProductType.SUBS, include_suspended) func _on_query_purchases_response(result: Dictionary): if result.response_code != BillingClient.BillingResponseCode.OK: print("Query purchases failed: %s" % result.debug_message) return print("Found %d purchases" % result.purchases.size()) for purchase in result.purchases: print("Owned: %s" % str(purchase.product_ids)) print(" Order ID: %s" % purchase.order_id) print(" Acknowledged: %s" % purchase.is_acknowledged) print(" Auto-renewing: %s" % purchase.is_auto_renewing) # Check for suspended subscriptions if purchase.get("is_suspended", false): print(" SUSPENDED - guide user to update payment") continue # Restore the purchase if purchase.purchase_state == BillingClient.PurchaseState.PURCHASED: for product_id in purchase.product_ids: restore_product_entitlement(product_id) # Acknowledge if needed if not purchase.is_acknowledged: acknowledge_product(purchase) ``` -------------------------------- ### Update Subscription Plan Source: https://context7.com/godot-sdk-integrations/godot-google-play-billing/llms.txt Use `update_subscription()` to upgrade or downgrade an existing subscription to a different plan. Specify the replacement mode for how the change should be handled. ```gdscript func upgrade_subscription(old_product_id: String, old_token: String, new_product_id: String, base_plan_id: String): # Upgrade with prorated charge var result = billing_client.update_subscription( old_product_id, old_token, BillingClient.ReplacementMode.CHARGE_PRORATED_PRICE, new_product_id, base_plan_id, "", # offer_id (optional) false # is_offer_personalized ) if result.response_code == BillingClient.BillingResponseCode.OK: print("Subscription update flow launched") ``` ```gdscript # Example: Upgrade from monthly to yearly plan func upgrade_to_yearly(current_purchase: Dictionary): billing_client.update_subscription( "monthly_premium", current_purchase.purchase_token, BillingClient.ReplacementMode.WITH_TIME_PRORATION, "yearly_premium", "yearly_base_plan" ) ``` -------------------------------- ### Billing Enums Reference Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/enums.md Definitions for BillingResponseCode, ConnectionState, ProductType, PurchaseState, and ReplacementMode. ```APIDOC ## BillingResponseCode ### Description Response codes returned by billing operations. ### Values - **OK** (0) - Success. - **USER_CANCELED** (1) - User cancelled the purchase flow. - **SERVICE_UNAVAILABLE** (2) - Network error or no connection. - **BILLING_UNAVAILABLE** (3) - A user billing error occurred during processing. - **ITEM_UNAVAILABLE** (4) - The requested product is not available for purchase. - **DEVELOPER_ERROR** (5) - Error resulting from incorrect usage of the API. - **ERROR** (6) - Fatal error during the API action. - **ITEM_ALREADY_OWNED** (7) - The purchase failed because the item is already owned. - **ITEM_NOT_OWNED** (8) - Requested action on the item failed since it is not owned by the user. - **NETWORK_ERROR** (12) - A network error occurred during the operation. - **SERVICE_DISCONNECTED** (-1) - The app is not connected to the Play Store service. - **FEATURE_NOT_SUPPORTED** (-2) - The requested feature is not supported by the Play Store on the current device. - **SERVICE_TIMEOUT** (-3) - Request timed out. ## ConnectionState ### Description Represents the billing connection state. ### Values - **DISCONNECTED** - Client not yet connected or already closed. - **CONNECTING** - Client is currently connecting. - **CONNECTED** - Client is currently connected. - **CLOSED** - Client was closed and should not be used. ## ProductType ### Description Defines the type of product. ### Values - **INAPP** - Android in-app products. - **SUBS** - Android subscriptions. ## PurchaseState ### Description Represents the state of a purchase. ### Values - **UNSPECIFIED_STATE** - Purchase with unknown state. - **PURCHASED** - Purchase is completed. - **PENDING** - Purchase is pending. ## ReplacementMode ### Description Defines how subscription replacements behave. ### Values - **UNKNOWN_REPLACEMENT_MODE** (0) - **WITH_TIME_PRORATION** (1) - New plan takes effect immediately, remaining time prorated. - **CHARGE_PRORATED_PRICE** (2) - New plan takes effect immediately, billing cycle remains same. - **WITHOUT_PRORATION** (3) - New plan takes effect immediately, new price charged on next recurrence. - **CHARGE_FULL_PRICE** (4) - New plan takes effect immediately, charged full price. - **DEFERRED** (5) - New purchase takes effect when old item expires. - **KEEP_EXISTING** (6) - Plan remains unchanged. ``` -------------------------------- ### Check Billing Client Connection State Source: https://context7.com/godot-sdk-integrations/godot-google-play-billing/llms.txt Check the connection status of the billing client using `is_ready()` for a quick check or `get_connection_state()` for detailed status. Operations should only be performed when the client is connected. ```gdscript func check_billing_status(): # Quick check if billing is ready if billing_client.is_ready(): print("Billing is ready for operations") return true # Get detailed connection state var state = billing_client.get_connection_state() match state: BillingClient.ConnectionState.DISCONNECTED: print("Not connected - call start_connection()") BillingClient.ConnectionState.CONNECTING: print("Connection in progress...") BillingClient.ConnectionState.CONNECTED: print("Connected and ready") BillingClient.ConnectionState.CLOSED: print("Connection closed - create new BillingClient") return state == BillingClient.ConnectionState.CONNECTED ``` -------------------------------- ### Query Product Details Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/quickstart.md Query available in-app products or subscriptions after the BillingClient has connected. This is a prerequisite for initiating purchases. Handles the response, printing success or failure details. ```gdscript func _on_connected(): billing_client.query_product_details(["my_iap_item"], BillingClient.ProductType.INAPP) # BillingClient.ProductType.SUBS for subscriptions. func _on_query_product_details_response(query_result: Dictionary): if query_result.response_code == BillingClient.BillingResponseCode.OK: print("Product details query success") for available_product in query_result.product_details: print(available_product) else: print("Product details query failed") print("response_code: ", query_result.response_code, "debug_message: ", query_result.debug_message) ``` -------------------------------- ### Open Subscriptions Page Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/methods.md Opens the Google Play subscription management interface, optionally for a specific product. ```gdscript func open_subscriptions_page(product_id: String = "") ``` ```gdscript billing_client.open_subscriptions_page("my_subscription_product_id") ``` -------------------------------- ### ProductType Enum Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/enums.md Defines the type of product. Use this to differentiate between in-app products and subscriptions. ```gdscript enum ProductType { INAPP, # A Product type for Android apps in-app products. SUBS # A Product type for Android apps subscriptions. } ``` -------------------------------- ### Signal: query_purchases_response Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/signals.md Emitted when query_purchases completes, providing the status code, debug message, and a list of user-owned purchases. ```APIDOC ## Signal: query_purchases_response ### Description Emitted when `query_purchases(...)` completes. Contains the result of the purchase query. ### Response Data - **response_code** (int) - A value from BillingResponseCode. - **debug_message** (String) - Debug message returned by Google Play. - **purchases** (Array) - Array of purchase dictionaries owned by the user. ### Example ```gdscript func _on_query_purchases_response(result): if result.response_code == BillingClient.BillingResponseCode.OK: for purchase in result.purchases: print("Owned:", purchase.product_ids) ``` ``` -------------------------------- ### Open Subscription Management Page Source: https://context7.com/godot-sdk-integrations/godot-google-play-billing/llms.txt Use `open_subscriptions_page()` to direct users to Google Play's subscription management screen. An optional product ID can be provided to open the page for a specific subscription. ```gdscript func show_subscription_management(): # Open general subscriptions page billing_client.open_subscriptions_page() ``` ```gdscript func show_specific_subscription(product_id: String): # Open management page for specific subscription billing_client.open_subscriptions_page(product_id) ``` ```gdscript # Useful when subscription is suspended due to payment issues func handle_suspended_subscription(purchase: Dictionary): if purchase.get("is_suspended", false): show_dialog("Your subscription is suspended. Please update your payment method.") billing_client.open_subscriptions_page(purchase.product_ids[0]) ``` -------------------------------- ### on_purchase_updated Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/signals.md Emitted when the purchase state changes. ```APIDOC ## on_purchase_updated ### Description Emitted when the purchase state changes, triggered after a purchase flow completes or when a pending purchase updates. ### Response - **response_code** (int) - A value from BillingResponseCode. - **debug_message** (String) - Debug message returned by Google Play billing library. - **purchases** (Array) - Array of purchase dictionaries owned by the user. ``` -------------------------------- ### Open Subscriptions Page Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/methods.md Opens the Google Play subscription management page, optionally for a specific product. ```APIDOC ## open_subscriptions_page ### Description Opens the Google Play subscription management page. ### Method POST ### Endpoint /godot-sdk-integrations/godot-google-play-billing ### Parameters #### Query Parameters - **product_id** (String) - Optional - Subscription product ID. If provided, Google Play will open the management page for that specific subscription. ### Request Example ```gdscript billing_client.open_subscriptions_page("my_subscription_product_id") ``` ``` -------------------------------- ### Set User Identifiers for Fraud Detection Source: https://context7.com/godot-sdk-integrations/godot-google-play-billing/llms.txt Use `set_obfuscated_account_id()` and `set_obfuscated_profile_id()` to associate purchases with your user system for fraud detection. These methods require a consistent, obfuscated identifier. ```gdscript func configure_user_tracking(): # Set obfuscated account ID for fraud detection var account_hash = hash_user_id(current_user.id) billing_client.set_obfuscated_account_id(account_hash) # Set profile ID if app supports multiple profiles per account if current_user.active_profile: var profile_hash = hash_profile_id(current_user.active_profile.id) billing_client.set_obfuscated_profile_id(profile_hash) ``` ```gdscript func hash_user_id(user_id: String) -> String: # Create obfuscated but consistent identifier return user_id.sha256_text().substr(0, 32) ``` ```gdscript func hash_profile_id(profile_id: String) -> String: return profile_id.sha256_text().substr(0, 32) ``` -------------------------------- ### Handle Purchase Updates in GDScript Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/quickstart.md Processes purchase results received through the on_purchase_updated signal. ```gdscript func _on_purchase_updated(result: Dictionary): if result.response_code == BillingClient.BillingResponseCode.OK: print("Purchase update received") for purchase in result.purchases: _process_purchase(purchase) else: print("Purchase update error") print("response_code: ", result.response_code, "debug_message: ", result.debug_message) ``` -------------------------------- ### Process Purchase States Source: https://context7.com/godot-sdk-integrations/godot-google-play-billing/llms.txt Handle the outcome of purchases by checking the `purchase_state`. Award content for `PURCHASED` states and acknowledge or consume the purchase. Handle `PENDING` states by informing the user to complete the purchase in the Play Store. ```gdscript func process_purchase(purchase: Dictionary): var purchase_state = purchase.purchase_state match purchase_state: BillingClient.PurchaseState.PURCHASED: print("Purchase completed!") # Award the content to the user for product_id in purchase.product_ids: award_product(product_id) # Acknowledge or consume the purchase if not purchase.is_acknowledged: handle_acknowledgement(purchase) BillingClient.PurchaseState.PENDING: print("Purchase is pending - do not grant content yet") # Show UI indicating purchase needs completion in Play Store BillingClient.PurchaseState.UNSPECIFIED_STATE: print("Unknown purchase state") func award_product(product_id: String): match product_id: "coins_100": GameData.coins += 100 "premium_upgrade": GameData.is_premium = true "remove_ads": GameData.ads_removed = true ``` -------------------------------- ### connected Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/signals.md Emitted when the billing client successfully connects to the Google Play Billing service. ```APIDOC ## connected ### Description Emitted when the billing client successfully connects to the Google Play Billing service. Once this signal is received, billing operations such as product queries and purchases can be performed. ``` -------------------------------- ### Query User Purchases Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/methods.md Retrieves currently owned purchases. Use the include_suspended_subs parameter to optionally include inactive subscriptions. ```gdscript func query_purchases(product_type: ProductType, include_suspended_subs: bool = false) ``` ```gdscript billing_client.query_purchases(BillingClient.ProductType.INAPP) billing_client.query_purchases(BillingClient.ProductType.SUBS, true) ``` -------------------------------- ### Update Subscription Plan Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/methods.md Updates an existing subscription to a new product or plan. Requires the purchase token of the current subscription and a defined replacement mode. ```gdscript func update_subscription(old_product_id: String, old_purchase_token: String, replacement_mode: ReplacementMode, new_product_id: String, base_plan_id: String, offer_id: String = "", is_offer_personalized: bool = false) -> Dictionary ``` ```gdscript billing_client.update_subscription("monthly_adfree_sub", old_purchase_token, BillingClient.ReplacementMode.CHARGE_PRORATED_PRICE, "premium_sub", "monthly") ``` -------------------------------- ### Consume Purchase Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/methods.md Consumes a given in-app product, making it available for repurchase. This action also automatically acknowledges the purchase. ```APIDOC ## consume_purchase ### Description Consume an in-app product. ### Method POST ### Endpoint /godot-sdk-integrations/godot-google-play-billing ### Parameters #### Path Parameters - **purchase_token** (String) - Required - Token identifying the purchase to consume. This token is included in purchase data received from `on_purchase_updated` or `query_purchases_response`. ### Request Example ```gdscript func consume_purchase(purchase_token: String) ``` ### Response #### Success Response (200) This method emits the `consume_purchase_response` signal upon completion. ``` -------------------------------- ### Define query_purchases_response signal Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/signals.md Signal definition for handling the response from a purchase query. ```gdscript signal query_purchases_response(response: Dictionary) ``` -------------------------------- ### ReplacementMode Enum Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/enums.md Defines how subscription replacements behave. Use these constants to control the proration and timing of subscription upgrades or downgrades. ```gdscript enum ReplacementMode { # Unknown... UNKNOWN_REPLACEMENT_MODE = 0, # The new plan takes effect immediately, and the remaining time will be prorated and credited to the user. # Note: This is the default behavior. WITH_TIME_PRORATION = 1, # The new plan takes effect immediately, and the billing cycle remains the same. CHARGE_PRORATED_PRICE = 2, # The new plan takes effect immediately, and the new price will be charged on next recurrence time. WITHOUT_PRORATION = 3, # Replacement takes effect immediately, and the user is charged full price of new plan and # is given a full billing cycle of subscription, plus remaining prorated time from the old plan. CHARGE_FULL_PRICE = 4, # The new purchase takes effect immediately, the new plan will take effect when the old item expires. DEFERRED = 5, # Indicates that this plan should remain unchanged in the new purchase. KEEP_EXISTING = 6 } ``` -------------------------------- ### Define Purchase States in GDScript Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/quickstart.md Enumeration representing the possible states of a purchase, used to check if a transaction is completed or pending. ```gdscript # Matches Purchase.PurchaseState in the Play Billing Library # Access in your script as: BillingClient.PurchaseState.PURCHASED enum PurchaseState { UNSPECIFIED, PURCHASED, PENDING, } ``` -------------------------------- ### Query User Purchases in GDScript Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/quickstart.md Retrieves active subscriptions or non-consumed one-time purchases using the billing client and handles the response via a signal. ```gdscript func _query_purchases(): billing_client.query_purchases(BillingClient.ProductType.INAPP) # Or BillingClient.ProductType.SUBS for subscriptions. func _on_query_purchases_response(query_result: Dictionary): if query_result.response_code == BillingClient.BillingResponseCode.OK: print("Purchase query success") for purchase in query_result.purchases: _process_purchase(purchase) else: print("Purchase query failed") print("response_code: ", query_result.response_code, "debug_message: ", query_result.debug_message) ``` -------------------------------- ### Define and handle on_purchase_updated signal Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/signals.md Emitted when the purchase state changes, such as after a purchase flow completes. ```gdscript signal on_purchase_updated(response: Dictionary) ``` ```gdscript func _on_purchase_updated(result): if result.response_code == BillingClient.BillingResponseCode.OK: for purchase in result.purchases: print("Purchased:", purchase.product_ids) ``` -------------------------------- ### Consume a Purchase in Godot Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/quickstart.md Call `consume_purchase` with the `purchase_token` to allow users to buy consumable items again. This action also acknowledges the purchase. ```gdscript func _process_purchase(purchase): if "my_consumable_iap_item" in purchase.product_ids and purchase.purchase_state == BillingClient.PurchaseState.PURCHASED: # Add code to store payment so we can reconcile the purchase token # in the completion callback against the original purchase billing_client.consume_purchase(purchase.purchase_token) func _on_consume_purchase_response(result: Dictionary): if result.response_code == BillingClient.BillingResponseCode.OK: print("Consume purchase success") _handle_purchase_token(result.token, true) else: print("Consume purchase failed") print("response_code: ", result.response_code, "debug_message: ", result.debug_message, "purchase_token: ", result.token) # Find the product associated with the purchase token and award the # product if successful func _handle_purchase_token(purchase_token, purchase_successful): # check/award logic, remove purchase from tracking list ``` -------------------------------- ### Close Billing Connection Source: https://context7.com/godot-sdk-integrations/godot-google-play-billing/llms.txt Use `end_connection()` to properly close the billing client when the game exits or billing is no longer needed. This should be called to release resources and prevent potential issues. ```gdscript func _notification(what: int) -> void: if what == NOTIFICATION_WM_GO_BACK_REQUEST: billing_client.end_connection() ``` ```gdscript func _on_exit_pressed() -> void: billing_client.end_connection() get_tree().quit() ``` ```gdscript func cleanup_billing(): if billing_client and billing_client.is_ready(): billing_client.end_connection() # The disconnected signal will be emitted ``` -------------------------------- ### query_purchases Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/methods.md Queries the user's currently owned purchases. ```APIDOC ## query_purchases ### Description Queries the user's currently owned purchases. By default, this returns active subscriptions and unconsumed in-app purchases. ### Parameters #### Request Body - **product_type** (ProductType) - Required - Enum value indicating the product type being queried. - **include_suspended_subs** (bool) - Optional - If true, suspended subscriptions will also be included in the results. ``` -------------------------------- ### update_subscription Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/methods.md Updates an existing subscription to a new product or plan. ```APIDOC ## update_subscription ### Description Updates an existing subscription to a new subscription product or plan. ### Parameters - **old_product_id** (String) - Required - The ID of the current subscription. - **old_purchase_token** (String) - Required - Purchase token of the currently active subscription. - **replacement_mode** (ReplacementMode) - Required - Enum value defining how the replacement behaves. - **new_product_id** (String) - Required - Product ID of the subscription to switch to. - **base_plan_id** (String) - Required - Base plan ID of the new subscription. - **offer_id** (String) - Optional - Offer ID configured under the base plan. - **is_offer_personalized** (bool) - Optional - Indicates if the price is personalized. ### Response - **Returns** (Dictionary) - Describes whether the update flow launched successfully. - **Emits** (signal) - Emits on_purchase_updated signal. ``` -------------------------------- ### acknowledge_purchase_response Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/signals.md Emitted when an acknowledge purchase request finishes. ```APIDOC ## acknowledge_purchase_response ### Description Emitted when an acknowledge purchase request finishes. ### Response - **response_code** (int) - A value from BillingResponseCode. - **debug_message** (String) - Debug message returned by Google Play billing library. - **token** (String) - The purchase token associated with the request. ``` -------------------------------- ### connect_error Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/signals.md Emitted when the billing client fails to connect to the Google Play Billing service. ```APIDOC ## connect_error ### Description Emitted when the billing client fails to connect to the Google Play Billing service. ### Response - **response_code** (int) - Error code from BillingResponseCode. - **debug_message** (String) - Debug message returned by Google Play billing library. ``` -------------------------------- ### BillingClient ConnectionState Enum Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/quickstart.md Represents the connection states of the BillingClient, mirroring the states in the Play Billing Library. Use these constants to check the current connection status. ```gdscript # Matches BillingClient.ConnectionState in the Play Billing Library. # Access in your script as: BillingClient.ConnectionState.CONNECTED enum ConnectionState { DISCONNECTED, # This client was not yet connected to billing service or was already closed. CONNECTING, # This client is currently in process of connecting to billing service. CONNECTED, # This client is currently connected to billing service. CLOSED, # This client was already closed and shouldn't be used again. } ``` -------------------------------- ### PurchaseState Enum Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/enums.md Represents the state of a purchase. Use this to determine if a purchase is completed, pending, or in an unknown state. ```gdscript enum PurchaseState { UNSPECIFIED_STATE, # Purchase with unknown state. PURCHASED, # Purchase is completed. PENDING, # Purchase is pending and not yet completed to be processed by your app. } ``` -------------------------------- ### ConnectionState Enum Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/enums.md Represents the billing connection state. Use this to check the current status of the connection to the billing service. ```gdscript enum ConnectionState { DISCONNECTED, # This client was not yet connected to billing service or was already closed. CONNECTING, # This client is currently in process of connecting to billing service. CONNECTED, # This client is currently connected to billing service. CLOSED, # This client was already closed and shouldn't be used again. } ``` -------------------------------- ### Define acknowledge_purchase_response signal Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/signals.md Emitted when an acknowledge purchase request finishes. ```gdscript signal acknowledge_purchase_response(response: Dictionary) ``` -------------------------------- ### Consume Purchase Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/methods.md Consumes a consumable product, allowing it to be purchased again. This action automatically acknowledges the purchase. ```gdscript func consume_purchase(purchase_token: String) ``` -------------------------------- ### Acknowledge a One-Time Purchase in Godot Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/quickstart.md Call `acknowledge_purchase` with the `purchase_token` for one-time purchases to prevent automatic refunds and revocations. This is not needed if `consume_purchase` is used. ```gdscript func _process_purchase(purchase): if "my_one_time_iap_item" in purchase.product_ids and \ purchase.purchase_state == BillingClient.PurchaseState.PURCHASED and \ not purchase.is_acknowledged: # Add code to store payment so we can reconcile the purchase token # in the completion callback against the original purchase billing_client.acknowledge_purchase(purchase.purchase_token) func _on_acknowledge_purchase_response(result: Dictionary): if result.response_code == BillingClient.BillingResponseCode.OK: print("Acknowledge purchase success") _handle_purchase_token(result.token, true) else: print("Acknowledge purchase failed") print("response_code: ", result.response_code, "debug_message: ", result.debug_message, "purchase_token: ", result.token) # Find the product associated with the purchase token and award the # product if successful func _handle_purchase_token(purchase_token, purchase_successful): # check/award logic, remove purchase from tracking list ``` -------------------------------- ### Define and Handle BillingResponseCode Source: https://context7.com/godot-sdk-integrations/godot-google-play-billing/llms.txt Defines the BillingResponseCode enum for Google Play billing and provides a function to map response codes to strings. ```gdscript enum BillingResponseCode { OK = 0, # Success USER_CANCELED = 1, # User cancelled the purchase flow SERVICE_UNAVAILABLE = 2, # Network error or no connection BILLING_UNAVAILABLE = 3, # User billing error during processing ITEM_UNAVAILABLE = 4, # Product not available for purchase DEVELOPER_ERROR = 5, # Incorrect API usage ERROR = 6, # Fatal error during API action ITEM_ALREADY_OWNED = 7, # Item already owned (need to consume first) ITEM_NOT_OWNED = 8, # Action failed - item not owned NETWORK_ERROR = 12, # Network error during operation SERVICE_DISCONNECTED = -1, # Not connected to Play Store FEATURE_NOT_SUPPORTED = -2, # Feature not supported on device SERVICE_TIMEOUT = -3 # Request timed out (deprecated) } func handle_response_code(code: int) -> String: match code: BillingClient.BillingResponseCode.OK: return "Success" BillingClient.BillingResponseCode.USER_CANCELED: return "Cancelled by user" BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED: return "Already owned - consume to repurchase" _: return "Error code: %d" % code ``` -------------------------------- ### Consume Consumable Purchases in GDScript Source: https://context7.com/godot-sdk-integrations/godot-google-play-billing/llms.txt Use consume_purchase to allow repurchase of consumable items. This action automatically acknowledges the purchase. ```gdscript var pending_consumptions: Dictionary = {} # token -> product_id func consume_product(purchase: Dictionary): var token = purchase.purchase_token pending_consumptions[token] = purchase.product_ids[0] billing_client.consume_purchase(token) func _on_consume_purchase_response(result: Dictionary): var token = result.token var product_id = pending_consumptions.get(token, "") if result.response_code == BillingClient.BillingResponseCode.OK: print("Successfully consumed: %s" % product_id) # Award the consumable content match product_id: "coins_100": GameData.coins += 100 "health_potion": GameData.potions += 1 pending_consumptions.erase(token) else: print("Consume failed - Code: %d, Message: %s" % [result.response_code, result.debug_message]) # Full consumable purchase flow func process_consumable_purchase(purchase: Dictionary): if purchase.purchase_state == BillingClient.PurchaseState.PURCHASED: consume_product(purchase) ``` -------------------------------- ### End Connection Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/methods.md Ends the connection to the Google Play Billing service. The client should not be used after this method is called. ```APIDOC ## end_connection ### Description Ends the connection to the Google Play Billing service. ### Method POST ### Endpoint /godot-sdk-integrations/godot-google-play-billing ### Request Example ```gdscript func end_connection() -> void ``` ### Response #### Success Response (200) This method emits the `disconnected` signal upon completion. ``` -------------------------------- ### Set Obfuscated Account ID Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/methods.md Sets an obfuscated identifier for fraud detection and account association. ```gdscript func set_obfuscated_account_id(account_id: String) ``` -------------------------------- ### End Connection Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/methods.md Terminates the connection to the Google Play Billing service. The client should not be used after calling this. ```gdscript func end_connection() -> void ``` -------------------------------- ### Define connect_error signal Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/signals.md Emitted when the billing client fails to connect to the Google Play Billing service. ```gdscript signal connect_error(response_code: int, debug_message: String) ``` -------------------------------- ### Set Obfuscated Profile ID Source: https://github.com/godot-sdk-integrations/godot-google-play-billing/blob/master/docs/api/methods.md Sets an obfuscated identifier for applications supporting multiple profiles per account. ```gdscript func set_obfuscated_profile_id(profile_id: String) ```