In-app integration guidance for alternative billing only

This guide describes how to integrate the APIs to offer alternative billing only (i.e. without user choice) in eligible apps. To learn more about these programs including eligibility requirements and geographic scope see About Alternative Billing.

Play Billing Library setup

Add the Play Billing Library dependency to your Android app. To use the alternative billing APIs you need to use version 6.1 or higher.

Connect to Google Play

The first steps in the integration process are the same as the ones described in the Google Play Billing integration guide, with a few modifications when initializing your BillingClient:

The following example demonstrates initializing a BillingClient with these modifications:

Kotlin


var billingClient = BillingClient.newBuilder(context)
    .enableAlternativeBillingOnly()
    .build()

Java

private BillingClient billingClient = BillingClient.newBuilder(context)
    .enableAlternativeBillingOnly()
    .build();

After you initialize the BillingClient, you need to establish a connection to Google Play as described in the integration guide.

Checking Availability

Your app should confirm alternative billing only is available by calling isAlternativeBillingOnlyAvailableAsync.

This API will return BillingResponseCode.OK if alternative billing only is available. Refer to response handling for details on how your app should respond to other response codes.

Kotlin


billingClient.isAlternativeBillingOnlyAvailableAsync(object:
    AlternativeBillingOnlyAvailabilityListener {
        override fun onAlternativeBillingOnlyAvailabilityResponse(
            billingResult: BillingResult) {
            if (billingResult.responseCode !=  BillingResponseCode.OK) {
                // Handle failures such as retrying due to network errors,
                // handling alternative billing only being unavailable, etc.
                return
            }

            // Alternative billing only is available. Continue with steps in
            // the guide.
        }
    });

Java


billingClient.isAlternativeBillingOnlyAvailable(
    new AlternativeBillingOnlyAvailabilityListener() {
        @Override
        public void onAlternativeBillingOnlyAvailabilityResponse(
            BillingResult billingResult) {
            if (billingResult.getResponseCode() != BillingResponseCode.OK) {
                 // Handle failures such as retrying due to network errors,
                 // handling alternative billing only being unavailable,
                 // etc.
                return;
            }

            // Alternative billing only is available. Continue with steps in
            // the guide.
        }
    });

Information dialog for users

To integrate with alternative billing only, your eligible app must show an information screen which helps users understand that billing will not be managed by Google Play. The information screen must be shown to users by calling the showAlternativeBillingOnlyInformationDialog API before starting the alternative billing flow each time. If the user has already acknowledged the dialog, using this API will typically not result in the dialog being shown again. There may be times when the dialog is shown again to a user in situations such as if the user clears caches on their device.

Kotlin


// An activity reference from which the alternative billing only information
// dialog will be launched.
val activity : Activity = ...;

val listener : AlternativeBillingOnlyInformationDialogListener =
    AlternativeBillingOnlyInformationDialogListener { 
        override fun onAlternativeBillingOnlyInformationDialogResponse(
            billingResult: BillingResult) {
            // check billingResult
        }
}

val billingResult =
    billingClient.showAlternativeBillingOnlyInformationDialog(activity,
        listener)

Java


// An activity reference from which the alternative billing only information
// dialog will be launched.
Activity activity = ...;

AlternativeBillingOnlyInformationDialogListener listener =
    new AlternativeBillingOnlyInformationDialogListener() {
        @Override
        public void onAlternativeBillingOnlyInformationDialogResponse(
            BillingResult billingResult) {
                // check billingResult
            }
    };

BillingResult billingResult =
    billingClient.showAlternativeBillingOnlyInformationDialog(activity,
        listener);

If this method returns BillingResponseCode.OK then your app can proceed with the transaction. In the case of BillingResponseCode.USER_CANCELED your app should call showAlternativeBillingOnlyInformationDialog to show the dialog to the user again. For other response codes see the response handling section.

Reporting transactions to Google Play

All transactions made through an alternative billing system must be reported to Google Play by calling the Google Play Developer API from your backend within 24 hours, providing an externalTransactionToken which is obtained using the API described below. A new externalTransactionToken should be generated for each one-time purchase, each new subscription, and for any upgrade/downgrades to an existing subscription. To learn how to report a transaction once an externalTransactionToken is obtained see the backend integration guide.

Kotlin

billingClient.createAlternativeBillingOnlyReportingDetailsAsync(object:
    AlternativeBillingOnlyReportingDetailsListener {
        override fun onAlternativeBillingOnlyTokenResponse(
            billingResult: BillingResult,
            alternativeBillingOnlyReportingDetails:
                AlternativeBillingOnlyReportingDetails?) {
            if (billingResult.responseCode !=  BillingResponseCode.OK) {
                // Handle failures such as retrying due to network errors.
                return
            }

            val externalTransactionToken =
                alternativeBillingOnlyReportingDetails?
                    .externalTransactionToken

            // Send transaction token to backend and report to Google Play.
        }
    });

Java


billingClient.createAlternativeBillingOnlyReportingDetailsAsync(
    new AlternativeBillingOnlyReportingDetailsListener() {
        @Override
        public void onAlternativeBillingOnlyTokenResponse(
            BillingResult billingResult,
            @Nullable AlternativeBillingOnlyReportingDetails
                alternativeBillingOnlyReportingDetails) {
            if (billingResult.getResponseCode() != BillingResponseCode.OK) {
                // Handle failures such as retrying due to network errors.
                return;
            }

            String transactionToken =
                alternativeBillingOnlyReportingDetails
                .getExternalTransactionToken();

            // Send transaction token to backend and report to Google Play.
        }
    });

Response handling

The above methods isAlternativeBillingOnlyAvailableAsync(), showAlternativeBillingOnlyInformationDialog(), and createAlternativeBillingOnlyReportingDetailsAsync() may return non-BillingResponseCode.OK responses in the case of errors. The recommended handling of the errors is described below:

  • ERROR: This is an internal error. Don't proceed with the transaction. Retry again by calling showAlternativeBillingOnlyInformationDialog() to display the information dialog to the user the next time the user attempts to make a purchase.
  • FEATURE_NOT_SUPPORTED: The alternative billing APIs are not supported by the Play Store on the current device. Don't proceed with the transaction.
  • USER_CANCELED: Don't proceed with the transaction. Call showAlternativeBillingOnlyInformationDialog() again to display the information dialog to the user the next time the user attempts to make a purchase.
  • BILLING_UNAVAILABLE: The transaction is not eligible for alternative billing only and therefore shouldn't proceed under this program. This is either because the user is not in an eligible country for this program or your account has not been successfully enrolled in the program. If it's the latter, check your enrollment status in the Play Developer Console.
  • DEVELOPER_ERROR: There is an error with the request. Use the debug message to identify and correct the error before proceeding.
  • NETWORK_ERROR, SERVICE_DISCONNECTED, SERVICE_UNAVAILABLE: These are transient errors that should be retried. In the case of SERVICE_DISCONNECTED re-establish a connection with Google Play before retrying.

Test alternative billing

License testers should be used to test your alternative billing integration. You won't be invoiced for transactions that have been initiated by license tester accounts. See Test in-app billing with application licensing for more information on configuring license testers.

Next steps

Once you've finished in-app integration, you're ready to integrate your backend.