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. Proceed with processing the transaction through the alternative billing system. The transaction does not need to be reported to Google including any renewals for affected subscriptions.
  • FEATURE_NOT_SUPPORTED: The alternative billing APIs are not supported by the Play Store on the current device. Proceed with processing the transaction through the alternative billing system. The transaction does not need to be reported to Google as well as any renewals for affected subscriptions.
  • USER_CANCELED: 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.

Next steps

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