Use this page with AI

Copy this into your coding assistant and add your request.

Read https://openiap.dev/docs/events/android/user-choice-billing-listener-android and https://openiap.dev/llms.txt. Follow the reading instructions, detailed reference, and linked guides relevant to my task before making changes.
Inspect my existing project and reuse its framework and conventions. Ask me for missing product decisions. Implement the requested behavior and run the applicable checks.
Show the working result, the commands and actual test results, and any remaining limitations. Keep your explanation brief.

My request: [describe what customers should be able to do]
See an example request →

Android userChoiceBillingListenerAndroid

Fired when a user selects alternative billing in the User Choice Billing dialog on Android.

With openiap-google 3.6.3+, selecting alternative billing completes the native purchase request without a Google Play purchase. After your external checkout finishes or is canceled, you can call requestPurchase again without reconnecting. This event does not confirm payment; verify the external payment on your backend before granting access.

originalExternalTransactionId and productDetailsAndroid are available in OpenIAP 2.3.0 / openiap-google 2.3.1 (requires Play Billing 9.1+). Legacy payloads may omit structured product details; use products as the product-ID fallback.

Listener Setup

swift
// Android only - not available on iOS

Registers a listener for User Choice Billing events. This listener is only triggered when the user selects alternative billing instead of Google Play billing.

kt
import dev.hyo.openiap.listener.OpenIapUserChoiceBillingListener

val userChoiceListener = OpenIapUserChoiceBillingListener { details ->
    lifecycleScope.launch {
        println("User chose alternative billing")
        println("Products: ${details.products}")
        println("External transaction token received; send it to your backend without logging it.")

        // Process payment with your backend
        val paymentResult = processPaymentWithBackend(
            products = details.products,
            token = details.externalTransactionToken
        )

        if (paymentResult.success) {
            // Backend should report token to Google Play within 24 hours
            grantUserAccess(details.products)
        }
    }
}

openIapStore.addUserChoiceBillingListener(userChoiceListener)

// Cleanup when done
openIapStore.removeUserChoiceBillingListener(userChoiceListener)

Event Payload

swift
// Android only - not available on iOS

externalTransactionToken - Token that must be reported to Google Play within 24 hours
originalExternalTransactionId - Originating external subscription transaction ID for developer-billed replacements (Play Billing 9.1+)
productDetailsAndroid - Selected product IDs, product types, and offer tokens as optional structured Play Billing 9.1+ data; use products when it is absent
products - List of product IDs selected by the user

Handling User Choice Billing

  1. Receive UserChoiceBillingDetails via listener
  2. Process payment with your backend payment system
  3. Send the external transaction token to your backend
  4. Backend reports token to Google Play within 24 hours (required for compliance)
  5. Grant user access to purchased content

⚠️ Important: The external transaction token MUST be reported to Google Play within 24 hours. Failure to report tokens may result in account suspension. It is strongly recommended to handle token reporting on your backend server for reliability and security.

Flow Comparison

When using User Choice Billing mode, there are two possible flows depending on user selection:

  • Google Play selected - Standard PurchaseUpdated event fires (handle normally)
  • Alternative billing selected - UserChoiceBillingAndroid event fires (handle with your payment system)

See External Purchase documentation for complete implementation examples.