Anleitung zur In-App-Integration der Abrechnung mit Auswahlmöglichkeit für Nutzer

In dieser Anleitung wird beschrieben, wie Sie Ihre App in die Play Billing Library APIs einbinden, damit Sie Ihren Nutzern die Abrechnungsauswahl anbieten können.

Einbindung in die PBL

Sie können die Abrechnungsauswahl in vier Szenarien in die PBL einbinden. Die Szenarien unterscheiden sich darin, wer den Bildschirm für die Auswahl rendert und wo die Zahlung erfolgt. In der folgenden Tabelle sind die Einbindungsszenarien aufgeführt:

Welchen Bildschirm für die Abrechnungsauswahl möchten Sie rendern?
Google Play Ihren eigenen (gemäß den UX-Richtlinien)
Wo erfolgt die Zahlung? In-App Szenario 1A

Google rendert den Bildschirm für die Auswahl und die alternative Abrechnung erfolgt in Ihrer App.

Szenario 1B

Der App-Entwickler rendert den Bildschirm für die Auswahl und die alternative Abrechnung erfolgt in Ihrer App.

Externer Weblink Szenario 2A

Google rendert den Bildschirm für die Auswahl und der Nutzer wird für Käufe zu Ihren eigenen Websites außerhalb Ihrer App weitergeleitet.

Szenario 2B

Der App-Entwickler rendert den Bildschirm für die Auswahl und der Nutzer wird für Käufe zu Ihren eigenen Websites außerhalb Ihrer App weitergeleitet.

Die folgende Abbildung veranschaulicht den Ablauf der Abrechnungsauswahl für jedes dieser Szenarien:

Der Ablauf für die Abrechnungsauswahl mit der Abfolge von API-Aufrufen und Nutzerinteraktionen für die vier Integrationsszenarien.
Abbildung 1. Szenarien für die Einbindung der Abrechnungsauswahl

Der Ablauf für die Abrechnungsauswahl mit der Abfolge von API-Aufrufen und Nutzerinteraktionen für die vier Integrationsszenarien.

PBL-Einbindungsszenarien

Führen Sie je nach Einbindungsszenario die Schritte in diesem Abschnitt aus, um die Abrechnungsauswahl in Ihrer App zu implementieren.

Szenario 1A verarbeiten

Google rendert den Bildschirm für die Auswahl und die alternative Abrechnung erfolgt in Ihrer App. Führen Sie die folgenden Schritte aus, um die Abrechnungsauswahl in diesem Szenario zu aktivieren:

  1. Rufen Sie enableBillingProgram mit EnableBillingProgramParams auf, wenn Sie Ihre BillingClient-Instanz erstellen, und starten Sie dann die Verbindung. Beispiel:

    Kotlin

    // Build the parameters to enable the Billing Choice program and assign the listener
    // to handle user selection of the developer-provided billing option.
    val enableBillingProgramParams = EnableBillingProgramParams.newBuilder()
        .setBillingProgram(BillingProgram.BILLING_CHOICE)
        .setDeveloperProvidedBillingListener(developerProvidedBillingListener)
        .build()
    
    // Build the parameters to enable support for pending purchases.
    val pendingPurchasesParams = PendingPurchasesParams.newBuilder()
        .enableOneTimeProducts()
        .build()
    
    // Construct the BillingClient instance with the purchases updated listener,
    // pending purchases support, and the billing choice params.
    val billingClient = BillingClient.newBuilder(context)
        .setListener(purchasesUpdatedListener)
        .enablePendingPurchases(pendingPurchasesParams)
        .enableBillingProgram(enableBillingProgramParams)
        .build()
    
    // Establish a connection to Google Play
    val billingResult = suspendCancellableCoroutine<BillingResult> { continuation ->
        billingClient.startConnection(object : BillingClientStateListener {
            // Called when the connection setup process completes.
            override fun onBillingSetupFinished(billingResult: BillingResult) {
                // Resume the coroutine and pass back the BillingResult to the caller.
                if (continuation.isActive) {
                    continuation.resume(billingResult)
                }
            }
    
            // Called if the connection to the Play Store service is dropped.
            // This prevents the await or suspension point from hanging indefinitely.
            override fun onBillingServiceDisconnected() {
                if (continuation.isActive) {
                    continuation.resume(
                        BillingResult.newBuilder()
                            .setResponseCode(BillingResponseCode.SERVICE_DISCONNECTED)
                            .setDebugMessage("Billing service disconnected during connection setup")
                            .build()
                    )
                }
            }
        })
    }

    Java

    
    EnableBillingProgramParams params = EnableBillingProgramParams.newBuilder()
            .setBillingProgram(BillingProgram.BILLING_CHOICE)
            .setDeveloperProvidedBillingListener(developerProvidedBillingListener)
            .build();
    
    BillingClient billingClient = BillingClient.newBuilder(context)
            .setListener(purchasesUpdatedListener)
            .enablePendingPurchases(
                    PendingPurchasesParams.newBuilder()
                            .enableOneTimeProducts()
                            .build()
            )
            .enableBillingProgram(params)
            .build();
    
    
  2. Prüfen Sie, ob die von Google gerenderte Abrechnungsauswahl für den Nutzer verfügbar ist.

    Rufen Sie isBillingProgramAvailableAsync auf, um die Programm verfügbarkeit zu prüfen, und rufen Sie dann queryProductDetailsAsync auf, um verfügbare Produkte anzuzeigen. Beispiel:

    Kotlin

    val (billingResult, billingProgramAvailabilityDetails) = billingClient.isBillingProgramAvailable(BillingProgram.BILLING_CHOICE)
    
    if (billingResult.responseCode == BillingResponseCode.OK) {
        val billingChoiceAvailabilityDetails = billingProgramAvailabilityDetails.billingChoiceAvailabilityDetails
        if (billingChoiceAvailabilityDetails != null &&
            billingChoiceAvailabilityDetails.choiceScreenType == ChoiceScreenType.GOOGLE_RENDERED
        ) {
            // Billing choice is available. Query products and proceed.
        } else {
            // Fallback to other available programs.
        }
    } else {
        // Fallback to other available programs.
    }

    Java

    
    // ...
    billingClient.isBillingProgramAvailableAsync(
        BillingProgram.BILLING_CHOICE,
        (billingResult, billingProgramAvailabilityDetails) -> {
            if (billingResult.getResponseCode() == BillingResponseCode.OK) {
                BillingChoiceAvailabilityDetails billingChoiceAvailabilityDetails =
                    billingProgramAvailabilityDetails.getBillingChoiceAvailabilityDetails();
    
                if (billingChoiceAvailabilityDetails != null &&
                    billingChoiceAvailabilityDetails.getChoiceScreenType() == ChoiceScreenType.GOOGLE_RENDERED) {
                    // Billing choice is available. Query products and proceed.
                } else {
                    // Fallback to other available programs.
                }
            } else {
                // Fallback to other available programs.
            }
        }
    );
    
    

    Hinweis: billingProgramAvailabilityDetails gibt an, ob der von Google gerenderte oder vom Entwickler gerenderte Bildschirm für die Abrechnungsauswahl verfügbar ist.

  3. Rufen Sie launchBillingFlow auf, um den Kaufvorgang auszulösen, wenn der Nutzer auf „Kaufen“ klickt. Wenn die Abrechnungsauswahl verfügbar ist, übergeben Sie DeveloperBillingOptionParams an BillingFlowParams. Beispiel:

    Kotlin

    val developerBillingOptionParams = DeveloperBillingOptionParams.newBuilder()
        .setBillingProgram(BillingProgram.BILLING_CHOICE)
        .build()
    
    val billingFlowParams = BillingFlowParams.newBuilder()
        .setProductDetailsParamsList(productDetailsParamsList)
        .enableDeveloperBillingOption(developerBillingOptionParams)
        .build()
    
    val billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)

    Java

    
    DeveloperBillingOptionParams developerBillingOptionParams =
        DeveloperBillingOptionParams.newBuilder()
            .setBillingProgram(BillingProgram.BILLING_CHOICE)
            .build();
    BillingFlowParams billingFlowParams =
        BillingFlowParams.newBuilder()
            .setProductDetailsParamsList(productDetailsParamsList)
            .enableDeveloperBillingOption(developerBillingOptionParams)
            .build();
    
    BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams);
    
    

    Hinweis: Für Nutzer mit Elternaufsicht werden die Jugendschutzeinstellungen angezeigt.

  4. Verarbeiten Sie die Auswahl des Abrechnungstyps durch den Nutzer so:

    • Wenn der Nutzer Google Play Billing auswählt, wird das Abrechnungsergebnis an den PurchasesUpdatedListener in Schritt 1 registriert zurückgegeben.
    • Wenn der Nutzer Ihre alternative Abrechnung auswählt, wird das Abrechnungsergebnis an den in Schritt 1 registrierten DeveloperProvidedBillingListener zurückgegeben. Die zurückgegebenen DeveloperProvidedBillingDetails enthalten in diesem Fall ein externalTransactionToken. Das Token wird für die Transaktionsberichterstellung verwendet.

Szenario 1B verarbeiten

Der Entwickler rendert den Bildschirm für die Auswahl und die alternative Abrechnung erfolgt in Ihrer App. Führen Sie die folgenden Schritte aus, um die Abrechnungsauswahl in diesem Szenario zu aktivieren:

  1. Rufen Sie enableBillingProgram ohne das DeveloperProvidedBillingListener in EnableBillingProgramParams beim Erstellen einer BillingClient Instanz auf und starten Sie dann die Verbindung. Beispiel:

    Kotlin

    // Build the parameters to enable the Billing Choice program.
    val enableBillingProgramParams = EnableBillingProgramParams.newBuilder()
        .setBillingProgram(BillingProgram.BILLING_CHOICE)
        .build()
    
    // Build the parameters to enable support for pending purchases.
    val pendingPurchasesParams = PendingPurchasesParams.newBuilder()
        .enableOneTimeProducts()
        .build()
    
    // Construct the BillingClient instance with the purchases updated listener,
    // pending purchases support, and the billing choice params.
    val billingClient = BillingClient.newBuilder(context)
        .setListener(purchasesUpdatedListener)
        .enablePendingPurchases(pendingPurchasesParams)
        .enableBillingProgram(enableBillingProgramParams)
        .build()
    
    // Establish a connection to Google Play
    val billingResult = suspendCancellableCoroutine<BillingResult> { continuation ->
        billingClient.startConnection(object : BillingClientStateListener {
            // Called when the connection setup process completes.
            override fun onBillingSetupFinished(billingResult: BillingResult) {
                // Resume the coroutine and pass back the BillingResult to the caller.
                if (continuation.isActive) {
                    continuation.resume(billingResult)
                }
            }
    
            // Called if the connection to the Play Store service is dropped.
            // This prevents the await or suspension point from hanging indefinitely.
            override fun onBillingServiceDisconnected() {
                if (continuation.isActive) {
                    continuation.resume(
                        BillingResult.newBuilder()
                            .setResponseCode(BillingResponseCode.SERVICE_DISCONNECTED)
                            .setDebugMessage("Billing service disconnected during connection setup")
                            .build()
                    )
                }
            }
        })
    }

    Java

    
    EnableBillingProgramParams params = EnableBillingProgramParams.newBuilder()
            .setBillingProgram(BillingProgram.BILLING_CHOICE)
            .build();
    
    BillingClient billingClient = BillingClient.newBuilder(context)
            .setListener(purchasesUpdatedListener)
            .enablePendingPurchases()
            .enableBillingProgram(params)
            .build();
    
    
  2. Prüfen Sie, ob die vom Entwickler gerenderte Abrechnungsauswahl für den Nutzer verfügbar ist.

    Rufen Sie isBillingProgramAvailableAsync auf, um die Programm verfügbarkeit zu prüfen, und rufen Sie dann queryProductDetailsAsync auf, um verfügbare Produkte anzuzeigen. Beispiel:

    Kotlin

    val (billingResult, billingProgramAvailabilityDetails) =
        billingClient.isBillingProgramAvailable(BillingProgram.BILLING_CHOICE)
    
    if (billingResult.responseCode == BillingResponseCode.OK) {
        val billingChoiceAvailabilityDetails =
            billingProgramAvailabilityDetails.billingChoiceAvailabilityDetails
    
        if (billingChoiceAvailabilityDetails != null &&
            billingChoiceAvailabilityDetails.choiceScreenType == ChoiceScreenType.DEVELOPER_RENDERED
        ) {
            // Billing choice is available. Query products and proceed.
            // You can inspect details such as:
            // - billingChoiceAvailabilityDetails.choiceScreenType
            // - billingChoiceAvailabilityDetails.isExternalLinkAvailable
        } else {
            // Fallback to other available programs.
        }
    } else {
        // Fallback to other available programs.
    }

    Java

    
    // ...
    billingClient.isBillingProgramAvailableAsync(
        BillingProgram.BILLING_CHOICE,
        (billingResult, billingProgramAvailabilityDetails) -> {
            if (billingResult.getResponseCode() == BillingResponseCode.OK) {
                BillingChoiceAvailabilityDetails billingChoiceAvailabilityDetails =
                    billingProgramAvailabilityDetails.getBillingChoiceAvailabilityDetails();
    
                if (billingChoiceAvailabilityDetails != null
                        && billingChoiceAvailabilityDetails.getChoiceScreenType() == ChoiceScreenType.DEVELOPER_RENDERED) {
                    // Billing choice is available. Query products and proceed.
                    // You can inspect details such as:
                    // - billingChoiceAvailabilityDetails.getChoiceScreenType()
                    // - billingChoiceAvailabilityDetails.isExternalLinkAvailable()
                } else {
                    // Fallback to other available programs.
                }
            } else {
                // Fallback to other available programs.
            }
        }
    );
    
    

    Hinweis: billingProgramAvailabilityDetails gibt an, ob der von Google gerenderte oder vom Entwickler gerenderte Bildschirm für die Abrechnungsauswahl verfügbar ist.

  3. Rufen Sie die Methode getBillingChoiceInfoAsync auf, um das Google Play Billing-Banner und Informationen zu Treueprogrammen abzurufen. Beispiel:

    Kotlin

    // 1. Create the params required for the request
    val params = GetBillingChoiceInfoParams.newBuilder()
        .setBillingProgram(BillingProgram.BILLING_CHOICE)
        .setPlayBillingChoiceImageLayout(GetBillingChoiceInfoParams.ImageLayout.RECTANGULAR_FOUR_BY_ONE)
        .build()
    
    // 2. Call the suspend method on your billingClient instance
    val (billingResult, playBillingChoiceInfo) = billingClient.getBillingChoiceInfo(params)
    
    if (billingResult.responseCode == BillingResponseCode.OK && playBillingChoiceInfo != null) {
        // Access the URL of the image associated with the Play Billing Choice
        val imageUrl = playBillingChoiceInfo.playBillingChoiceImageUrl
    
        // Access the Play Loyalty string information, if available
        val loyaltyInfo = playBillingChoiceInfo.playBillingLoyaltyInfo
    
        // Populate your developer-rendered UI elements
        playBillingLoyaltyTextView.text = loyaltyInfo
        loadImage(imageUrl, playBillingImageView)
    } else {
        // Handle error scenarios
    }

    Java

    
    // 1. Create the params required for the request
    GetBillingChoiceInfoParams params = GetBillingChoiceInfoParams.newBuilder()
        .setBillingProgram(BillingClient.BillingProgram.BILLING_CHOICE)
        .setPlayBillingChoiceImageLayout(GetBillingChoiceInfoParams.ImageLayout.RECTANGULAR_FOUR_BY_ONE)
        .build();
    // 2. Call the method asynchronously on your billingClient instance
    billingClient.getBillingChoiceInfoAsync(params, (billingResult, playBillingChoiceInfo) -> {
        if (billingResult.getResponseCode() == BillingResponseCode.OK && playBillingChoiceInfo != null) {
          // Access the URL of the image associated with the Play Billing Choice
            String imageUrl = playBillingChoiceInfo.getPlayBillingChoiceImageUrl();
            // Access the Play Loyalty string information, if available
            String loyaltyInfo = playBillingChoiceInfo.getPlayBillingLoyaltyInfo();
    
            // Populate your developer-rendered UI elements
            playBillingLoyaltyTextView.setText(loyaltyInfo);
              loadImage(imageUrl, playBillingImageView);
          } else {
              // Handle error scenarios
          }
    });
    
    
  4. Erstellen Sie ein externes Transaktionstoken, wobei „DeveloperBillingType“ auf IN_APP festgelegt ist. Beispiel:

    Kotlin

    // Build the parameters specifying the billing program and that the billing type is IN_APP.
    val params = BillingProgramReportingDetailsParams.newBuilder()
        .setBillingProgram(BillingProgram.BILLING_CHOICE)
        .setDeveloperBillingType(DeveloperBillingType.IN_APP)
        .build()
    
    // Call the suspending extension function to request the reporting details
    val (billingResult, billingProgramReportingDetails) =
        billingClient.createBillingProgramReportingDetails(params)
    
    if (billingResult.responseCode != BillingResponseCode.OK) {
        // Handle failures such as retrying due to network errors.
        return
    }
    
    // Extract the transaction token from the returned reporting details
    val transactionToken = billingProgramReportingDetails?.externalTransactionToken
    
    // Persist the external transaction token locally. Pass it to
    // DeveloperBillingOptionParams when launchBillingFlow is called.
    // It can also be used as part of your external website

    Java

    
    BillingProgramReportingDetailsParams params =
        BillingProgramReportingDetailsParams.newBuilder()
            .setBillingProgram(BillingProgram.BILLING_CHOICE)
            .setDeveloperBillingType(DeveloperBillingType.IN_APP)
            .build();
    
    billingClient.createBillingProgramReportingDetailsAsync(
        params,
        new BillingProgramReportingDetailsListener() {
            @Override
            public void onCreateBillingProgramReportingDetailsResponse(
                BillingResult billingResult,
                @Nullable BillingProgramReportingDetails billingProgramReportingDetails
            ) {
                if (billingResult.getResponseCode() != BillingResponseCode.OK) {
                    // Handle failures such as retrying due to network errors.
                    return;
                }
    
                String transactionToken =
                    billingProgramReportingDetails.getExternalTransactionToken();
    
                // Persist the external transaction token locally. Pass it to
                // DeveloperBillingOptionParams when launchBillingFlow is called.
                // It can also be used as part of your external website
            }
        }
    );
    
    
    
  5. Wenn der Nutzer auf „Kaufen“ klickt, rufen Sie showBillingProgramInformationDialog auf, um ein Informationsdialogfeld anzuzeigen. Ein Beispiel finden Sie unter Informationsdialogfeld für Nutzer. BillingProgram und transactionToken aus Schritt 4 müssen in der Anfrage festgelegt werden.

    Hinweis: Für Nutzer mit Elternaufsicht werden die Jugendschutzeinstellungen angezeigt.

  6. Starten Sie Ihren Bildschirm für die alternative Abrechnungsauswahl, wenn das Ergebnis aus dem vorherigen Schritt OK ist.

  7. Verarbeiten Sie die Auswahl des Abrechnungstyps durch den Nutzer so:

Szenario 2A verarbeiten

Google rendert den Bildschirm für die Auswahl und die alternative Abrechnung erfolgt außerhalb Ihrer App. Führen Sie die folgenden Schritte aus, um die Abrechnungsauswahl in diesem Szenario zu aktivieren:

  1. Rufen Sie enableBillingProgram mit EnableBillingProgramParams auf, wenn Sie Ihre BillingClient-Instanz erstellen, und starten Sie dann die Verbindung. Beispiel:

    Kotlin

    // Build the parameters to enable the Billing Choice program and assign the listener
    // to handle user selection of the developer-provided billing option.
    val enableBillingProgramParams = EnableBillingProgramParams.newBuilder()
        .setBillingProgram(BillingProgram.BILLING_CHOICE)
        .setDeveloperProvidedBillingListener(developerProvidedBillingListener)
        .build()
    
    // Build the parameters to enable support for pending purchases.
    val pendingPurchasesParams = PendingPurchasesParams.newBuilder()
        .enableOneTimeProducts()
        .build()
    
    // Construct the BillingClient instance with the purchases updated listener,
    // pending purchases support, and the billing choice params.
    val billingClient = BillingClient.newBuilder(context)
        .setListener(purchasesUpdatedListener)
        .enablePendingPurchases(pendingPurchasesParams)
        .enableBillingProgram(enableBillingProgramParams)
        .build()
    
    // Establish a connection to Google Play
    val billingResult = suspendCancellableCoroutine<BillingResult> { continuation ->
        billingClient.startConnection(object : BillingClientStateListener {
            // Called when the connection setup process completes.
            override fun onBillingSetupFinished(billingResult: BillingResult) {
                // Resume the coroutine and pass back the BillingResult to the caller.
                if (continuation.isActive) {
                    continuation.resume(billingResult)
                }
            }
    
            // Called if the connection to the Play Store service is dropped.
            // This prevents the await or suspension point from hanging indefinitely.
            override fun onBillingServiceDisconnected() {
                if (continuation.isActive) {
                    continuation.resume(
                        BillingResult.newBuilder()
                            .setResponseCode(BillingResponseCode.SERVICE_DISCONNECTED)
                            .setDebugMessage("Billing service disconnected during connection setup")
                            .build()
                    )
                }
            }
        })
    }

    Java

    
    EnableBillingProgramParams params = EnableBillingProgramParams.newBuilder()
            .setBillingProgram(BillingProgram.BILLING_CHOICE)
            .setDeveloperProvidedBillingListener(developerProvidedBillingListener)
            .build();
    
    BillingClient billingClient = BillingClient.newBuilder(context)
            .setListener(purchasesUpdatedListener)
            .enablePendingPurchases(
                    PendingPurchasesParams.newBuilder()
                            .enableOneTimeProducts()
                            .build()
            )
            .enableBillingProgram(params)
            .build();
    
    
  2. Prüfen Sie die Verfügbarkeit der folgenden Elemente:

    • Von Google gerenderte Abrechnungsauswahl
    • Externer Weblink

    Rufen Sie isBillingProgramAvailableAsync auf, um die Verfügbarkeit des Programms zu prüfen, und rufen Sie dann queryProductDetailsAsync auf, um verfügbare Produkte anzuzeigen. Beispiel:

    Kotlin

    Java

    
    // ...
    billingClient.isBillingProgramAvailableAsync(
        BillingProgram.BILLING_CHOICE,
        (billingResult, billingProgramAvailabilityDetails) -> {
            if (billingResult.getResponseCode() == BillingResponseCode.OK) {
                BillingChoiceAvailabilityDetails billingChoiceAvailabilityDetails =
                    billingProgramAvailabilityDetails.getBillingChoiceAvailabilityDetails();
    
                if (billingChoiceAvailabilityDetails != null
                        && billingChoiceAvailabilityDetails.getChoiceScreenType() == ChoiceScreenType.GOOGLE_RENDERED
                        && billingChoiceAvailabilityDetails.isExternalLinkAvailable()) {
                    // Billing choice is available and external transaction links are supported.
                    // Query products and proceed.
                } else {
                    // Fallback to other available programs.
                }
            } else {
                // Fallback to other available programs.
            }
        }
    );
    
    
    
  3. Rufen Sie createBillingProgramReportingDetailsAsync auf, um ein externes Transaktionstoken zu erstellen, wenn der Nutzer Kaufinteresse zeigt. Beispiel:

    Kotlin

    Java

    
    BillingProgramReportingDetailsParams params =
        BillingProgramReportingDetailsParams.newBuilder()
            .setBillingProgram(BillingProgram.BILLING_CHOICE)
            .setDeveloperBillingType(DeveloperBillingType.EXTERNAL_LINK)
            .build();
    
    billingClient.createBillingProgramReportingDetailsAsync(
        params,
        new BillingProgramReportingDetailsListener() {
            @Override
            public void onCreateBillingProgramReportingDetailsResponse(
                BillingResult billingResult,
                @Nullable BillingProgramReportingDetails billingProgramReportingDetails
            ) {
                if (billingResult.getResponseCode() != BillingResponseCode.OK) {
                    // Handle failures such as retrying due to network errors.
                    return;
                }
    
                String transactionToken =
                    billingProgramReportingDetails.getExternalTransactionToken();
    
                // Persist the external transaction token locally. Pass it to
                // DeveloperBillingOptionParams when launchBillingFlow is called.
                // It can also be used as part of your external website.
            }
        }
    );
    
    
  4. Rufen Sie launchBillingFlow auf, um den Kaufvorgang auszulösen, wenn der Nutzer auf „Kaufen“ klickt. Wenn die Abrechnungsauswahl für den Nutzer verfügbar ist, führen Sie die folgenden Schritte aus:

    1. Übergeben Sie DeveloperBillingOptionParams an BillingFlowParams.
    2. Übergeben Sie das externe Transaktionstoken aus Schritt 3 an DeveloperBillingOptionParams.

    Beispiel:

    Kotlin

    Java

    
    DeveloperBillingOptionParams developerBillingOptionParams =
        DeveloperBillingOptionParams.newBuilder()
            .setBillingProgram(BillingProgram.BILLING_CHOICE)
            .setLinkUri(Uri.parse("https://www.example.com/external/purchase"))
            .setExternalTransactionToken(transactionToken)
            .setLaunchMode(
              DeveloperBillingOptionParams.LaunchMode.LAUNCH_IN_EXTERNAL_BROWSER_OR_APP)
            .build();
    
    

    Hinweis: Für Nutzer mit Elternaufsicht werden die Jugendschutzeinstellungen angezeigt.

  5. Verarbeiten Sie die Auswahl des Abrechnungstyps durch den Nutzer so:

Szenario 2B verarbeiten

Der Entwickler rendert den Bildschirm für die Auswahl und die alternative Abrechnung erfolgt außerhalb der App. Führen Sie die folgenden Schritte aus, um die Abrechnungsauswahl in diesem Szenario zu aktivieren:

  1. Rufen Sie enableBillingProgram beim Erstellen einer BillingClient Instanz ohne das DeveloperProvidedBillingListener in EnableBillingProgramParams auf und starten Sie dann die Verbindung. Beispiel:

    Kotlin

    // Build the parameters to enable the Billing Choice program.
    val enableBillingProgramParams = EnableBillingProgramParams.newBuilder()
        .setBillingProgram(BillingProgram.BILLING_CHOICE)
        .build()
    
    // Build the parameters to enable support for pending purchases.
    val pendingPurchasesParams = PendingPurchasesParams.newBuilder()
        .enableOneTimeProducts()
        .build()
    
    // Construct the BillingClient instance with the purchases updated listener,
    // pending purchases support, and the billing choice params.
    val billingClient = BillingClient.newBuilder(context)
        .setListener(purchasesUpdatedListener)
        .enablePendingPurchases(pendingPurchasesParams)
        .enableBillingProgram(enableBillingProgramParams)
        .build()
    
    // Establish a connection to Google Play
    val billingResult = suspendCancellableCoroutine<BillingResult> { continuation ->
        billingClient.startConnection(object : BillingClientStateListener {
            // Called when the connection setup process completes.
            override fun onBillingSetupFinished(billingResult: BillingResult) {
                // Resume the coroutine and pass back the BillingResult to the caller.
                if (continuation.isActive) {
                    continuation.resume(billingResult)
                }
            }
    
            // Called if the connection to the Play Store service is dropped.
            // This prevents the await or suspension point from hanging indefinitely.
            override fun onBillingServiceDisconnected() {
                if (continuation.isActive) {
                    continuation.resume(
                        BillingResult.newBuilder()
                            .setResponseCode(BillingResponseCode.SERVICE_DISCONNECTED)
                            .setDebugMessage("Billing service disconnected during connection setup")
                            .build()
                    )
                }
            }
        })
    }

    Java

    
    EnableBillingProgramParams params = EnableBillingProgramParams.newBuilder()
            .setBillingProgram(BillingProgram.BILLING_CHOICE)
            .build();
    
    BillingClient billingClient = BillingClient.newBuilder(context)
            .setListener(purchasesUpdatedListener)
            .enablePendingPurchases()
            .enableBillingProgram(params)
            .build();
    
    
  2. Prüfen Sie die Verfügbarkeit der folgenden Elemente:

    • Von Google gerenderte Abrechnungsauswahl
    • Externer Weblink

    Rufen Sie isBillingProgramAvailableAsync auf, um die Verfügbarkeit des Programms zu prüfen, und rufen Sie dann queryProductDetailsAsync auf, um verfügbare Produkte anzuzeigen. Beispiel:

    Kotlin

    Java

    
    // ...
    
    billingClient.isBillingProgramAvailableAsync(
        BillingProgram.BILLING_CHOICE,
        (billingResult, billingProgramAvailabilityDetails) -> {
            if (billingResult.getResponseCode() == BillingResponseCode.OK) {
                BillingChoiceAvailabilityDetails billingChoiceAvailabilityDetails =
                    billingProgramAvailabilityDetails.getBillingChoiceAvailabilityDetails();
                if (billingChoiceAvailabilityDetails != null &&
                    billingChoiceAvailabilityDetails.getChoiceScreenType() == ChoiceScreenType.DEVELOPER_RENDERED &&
                    billingChoiceAvailabilityDetails.isExternalLinkAvailable()) {
                    // Billing choice is available and external transaction links are supported. Query products and proceed.
                } else {
                    // Fallback to other available programs.
                }
            } else {
                // Fallback to other available programs.
            }
        }
    );
    
    
  3. Rufen Sie die Methode getBillingChoiceInfoAsync auf, um das Google Play Billing-Banner und Informationen zu Treueprogrammen abzurufen.

    Kotlin

    // 1. Create the params required for the request
    val params = GetBillingChoiceInfoParams.newBuilder()
        .setBillingProgram(BillingProgram.BILLING_CHOICE)
        .setPlayBillingChoiceImageLayout(GetBillingChoiceInfoParams.ImageLayout.RECTANGULAR_FOUR_BY_ONE)
        .build()
    
    // 2. Call the suspend method on your billingClient instance
    val (billingResult, playBillingChoiceInfo) = billingClient.getBillingChoiceInfo(params)
    
    if (billingResult.responseCode == BillingResponseCode.OK && playBillingChoiceInfo != null) {
        // Access the URL of the image associated with the Play Billing Choice
        val imageUrl = playBillingChoiceInfo.playBillingChoiceImageUrl
    
        // Access the Play Loyalty string information, if available
        val loyaltyInfo = playBillingChoiceInfo.playBillingLoyaltyInfo
    
        // Populate your developer-rendered UI elements
        playBillingLoyaltyTextView.text = loyaltyInfo
        loadImage(imageUrl, playBillingImageView)
    } else {
        // Handle error scenarios
    }

    Java

    
    // 1. Create the params required for the request
    GetBillingChoiceInfoParams params = GetBillingChoiceInfoParams.newBuilder()
        .setBillingProgram(BillingClient.BillingProgram.BILLING_CHOICE)
        .setPlayBillingChoiceImageLayout(GetBillingChoiceInfoParams.ImageLayout.RECTANGULAR_FOUR_BY_ONE)
        .build();
    // 2. Call the method asynchronously on your billingClient instance
    billingClient.getBillingChoiceInfoAsync(params, (billingResult, playBillingChoiceInfo) -> {
        if (billingResult.getResponseCode() == BillingResponseCode.OK && playBillingChoiceInfo != null) {
          // Access the URL of the image associated with the Play Billing Choice
            String imageUrl = playBillingChoiceInfo.getPlayBillingChoiceImageUrl();
            // Access the Play Loyalty string information, if available
            String loyaltyInfo = playBillingChoiceInfo.getPlayBillingLoyaltyInfo();
    
            // Populate your developer-rendered UI elements
            playBillingLoyaltyTextView.setText(loyaltyInfo);
              loadImage(imageUrl, playBillingImageView);
          } else {
              // Handle error scenarios
          }
    });
    
    
  4. Rufen Sie createBillingProgramReportingDetailsAsync auf, um ein externes Transaktionstoken zu erstellen, wenn der Nutzer Kaufinteresse zeigt. Beispiel:

    Kotlin

    Java

    
    BillingProgramReportingDetailsParams params =
        BillingProgramReportingDetailsParams.newBuilder()
            .setBillingProgram(BillingProgram.BILLING_CHOICE)
            .setDeveloperBillingType(DeveloperBillingType.EXTERNAL_LINK)
            .build();
    
    billingClient.createBillingProgramReportingDetailsAsync(
        params,
        new BillingProgramReportingDetailsListener() {
            @Override
            public void onCreateBillingProgramReportingDetailsResponse(
                BillingResult billingResult,
                @Nullable BillingProgramReportingDetails billingProgramReportingDetails
            ) {
                if (billingResult.getResponseCode() != BillingResponseCode.OK) {
                    // Handle failures such as retrying due to network errors.
                    return;
                }
    
                String transactionToken =
                    billingProgramReportingDetails.getExternalTransactionToken();
    
                // Persist the external transaction token locally. Pass it to
                // DeveloperBillingOptionParams when launchBillingFlow is called.
                // It can also be used as part of your external website.
            }
        }
    );
    
    
  5. Starten Sie Ihren Bildschirm für die alternative Auswahl, wenn der Nutzer auf „Kaufen“ klickt.

  6. Verarbeiten Sie die Auswahl des Abrechnungstyps durch den Nutzer so:

    • Wenn der Nutzer Google Play Billing auswählt, rufen Sie launchBillingFlow gemäß der Standardanleitung für Google Play Billing auf. Das Abrechnungsergebnis wird an den PurchasesUpdatedListener in Schritt 1 zurückgegeben.

      Für Nutzer mit Elternaufsicht werden die Jugendschutzeinstellungen angezeigt.

    • Wenn der Nutzer Ihre alternative Abrechnung auswählt, rufen Sie `launchExternalLink` auf. Beispiel:

      Kotlin

      Java

      
      // An activity reference from which the purchase flow will be launched.
      Activity activity = ...;
      
      LaunchExternalLinkParams params = LaunchExternalLinkParams.newBuilder()
          .setBillingProgram(BillingProgram.BILLING_CHOICE)
          // You can pass along the external transaction token from
          // BillingProgramReportingDetails as a URL parameter in the URI
          .setLinkUri(yourLinkUri)
          .setLinkType(LaunchExternalLinkParams.LinkType.LINK_TO_DIGITAL_CONTENT_OFFER)
          .setLaunchMode(
              LaunchExternalLinkParams.LaunchMode.LAUNCH_IN_EXTERNAL_BROWSER_OR_APP)
          .setExternalTransactionToken(transactionToken)
          .build();
      
      LaunchExternalLinkResponseListener listener =
          new LaunchExternalLinkResponseListener() {
            @Override
            public void onLaunchExternalLinkResponse(BillingResult billingResult) {
              if (billingResult.getResponseCode() == BillingResponseCode.OK) {
                // Proceed with the rest of the purchase flow. If the user
                // purchases an item, be sure to report the transaction to Google
                // Play.
              } else {
                // Handle failures such as retrying due to network errors.
              }
            }
          };
      
      billingClient.launchExternalLink(activity, params, listener);
      
      
    • Übergeben Sie das externe Transaktionstoken aus Schritt 4 an LaunchExternalLinkParams. Wenn „OK“ zurückgegeben wird, fahren Sie mit der Transaktion fort und melden Sie sie Google Play.

      Für Nutzer mit Elternaufsicht werden die Jugendschutzeinstellungen angezeigt.

Abrechnungsauswahl beim Ersetzen eines Abos

Beim Ersetzen eines Abos sollte der Bildschirm für die Nutzerauswahl nicht angezeigt werden, da die Nutzerauswahl für den ursprünglichen Kauf für Upgrades und Downgrades beibehalten wird.

Wenn der ursprüngliche Kauf über Google Play Billing verarbeitet wurde, sollten Sie launchBillingFlow mit den Standardinformationen zum Ersetzen von Abos in Google Play Billing aufrufen.

Wenn der ursprüngliche Kauf jedoch über eine alternative Abrechnung verarbeitet wurde, unterscheidet sich die Verarbeitung von Abo-Ersetzungen je nach den Szenarien geringfügig.

Abo-Ersetzung in Szenario 1A

Nutzer, die ein Upgrade oder ein Downgrade anfordern, sollten über das alternative Abrechnungssystem des Entwicklers fortfahren, ohne die Nutzerauswahl noch einmal durchlaufen zu müssen.

Rufen Sie dazu launchBillingFlow auf, wenn der Nutzer ein Upgrade oder ein Downgrade anfordert. Verwenden Sie setOriginalExternalTransactionId im Objekt SubscriptionUpdateParams in den Parametern, um die externe Transaktions-ID für den ursprünglichen Kauf anzugeben. Der Bildschirm für die Nutzerauswahl wird nicht angezeigt, da die Nutzerauswahl für den ursprünglichen Kauf für Upgrades und Downgrades beibehalten wird. Der Aufruf von launchBillingFlow generiert in diesem Fall ein neues externes Transaktionstoken für die Transaktion, das Sie über den Callback abrufen können.

Kotlin

// The external transaction ID from the current
// alternative billing subscription.
val externalTransactionId = "external_transaction_id"

val developerBillingOptionParams = DeveloperBillingOptionParams.newBuilder()
    .setBillingProgram(BillingProgram.BILLING_CHOICE)
    .build()

val billingFlowParams = BillingFlowParams.newBuilder()
    .setProductDetailsParamsList(
        listOf(
            BillingFlowParams.ProductDetailsParams.newBuilder()
                // Fetched using queryProductDetailsAsync.
                .setProductDetails(productDetailsNewPlan)
                // offerIdToken can be found in
                // ProductDetails=>SubscriptionOfferDetails.
                .setOfferToken(offerTokenNewPlan)
                .build()
        )
    )
    .setSubscriptionUpdateParams(
        SubscriptionUpdateParams.newBuilder()
            .setOriginalExternalTransactionId(externalTransactionId)
            .build()
    )
    .enableDeveloperBillingOption(developerBillingOptionParams)
    .build()

val billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)

// When the user selects the alternative billing flow,
// the DeveloperProvidedBillingListener is triggered.

Java


// The external transaction ID from the current
// alternative billing subscription.
String externalTransactionId = //... ;

DeveloperBillingOptionParams developerBillingOptionParams =
    DeveloperBillingOptionParams.newBuilder()
        .setBillingProgram(BillingProgram.BILLING_CHOICE)
        .build();

List<ProductDetailsParams> productDetailsParamsList = new ArrayList<>();
productDetailsParamsList.add(
    ProductDetailsParams.newBuilder()
        // Fetched using queryProductDetailsAsync.
        .setProductDetails(productDetailsNewPlan)
        // offerIdToken can be found in
        // ProductDetails=>SubscriptionOfferDetails
        .setOfferToken(offerTokenNewPlan)
        .build());

BillingFlowParams billingFlowParams =
    BillingFlowParams.newBuilder()
        .setProductDetailsParamsList(productDetailsParamsList)
        .setSubscriptionUpdateParams(
            SubscriptionUpdateParams.newBuilder()
                .setOriginalExternalTransactionId(externalTransactionId)
                .build())
        .enableDeveloperBillingOption(developerBillingOptionParams)
        .build();

BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams);

// When the user selects the alternative billing flow,
// the DeveloperProvidedBillingListener is triggered.


Nach Abschluss des Upgrades oder Downgrades müssen Sie eine neue Transaktion mit dem externen Transaktionstoken melden, das Sie durch den vorherigen Aufruf für den neuen Abo-Kauf erhalten haben.

Abo-Ersetzung in Szenario 1B

In diesem Szenario muss ein neues externes Transaktionstoken generiert werden. Der einzige Unterschied zu einem normalen Kauf besteht darin, dass in diesem Szenario die Nutzerauswahl beibehalten wird und Sie den Bildschirm für die Auswahl für ein Upgrade oder Downgrade nicht anzeigen müssen. Sie müssen jedoch das einmalige Informationsdialogfeld und die Bestätigung der Elternaufsicht anzeigen.

Beispielcode für die Einbindung finden Sie in Schritt 4 unter Szenario 1B: Der Entwickler rendert den Bildschirm für die Auswahl und die alternative Abrechnung erfolgt in Ihrer App.

Nach Abschluss des Upgrades oder Downgrades müssen Sie eine neue Transaktion mit dem externen Transaktionstoken melden, das Sie durch den vorherigen Aufruf für den neuen Abo-Kauf erhalten haben.

Abo-Ersetzung in Szenario 2A

Bei Abos, die ursprünglich nach der Nutzerauswahl über die Website des Entwicklers oder eine Zahlungs-App gekauft wurden, sollten Nutzer, die ein Upgrade oder ein Downgrade anfordern, über die Website des Entwicklers oder eine Zahlungs-App fortfahren, ohne die Nutzerauswahl noch einmal durchlaufen zu müssen.

Rufen Sie dazu launchBillingFlow auf, wenn der Nutzer ein Upgrade oder ein Downgrade anfordert. Anstatt andere Parameter unter dem SubscriptionUpdateParams Objekt anzugeben, verwenden Sie setOriginalExternalTransactionId, und geben Sie die externe Transaktions-ID für den ursprünglichen Kauf an. DeveloperBillingOptionParams muss ebenfalls in diesem Aufruf angegeben werden. Der Bildschirm für die Nutzerauswahl wird nicht angezeigt, da die Nutzerauswahl für den ursprünglichen Kauf für Upgrades und Downgrades beibehalten wird. Beispiel:

Kotlin

val externalTransactionId = "external_transaction_id"

// 1. Construct DeveloperBillingOptionParams indicating the billing program
val developerBillingOptionParams = DeveloperBillingOptionParams.newBuilder()
    .setBillingProgram(BillingProgram.BILLING_CHOICE)
    .build()

// 2. Build BillingFlowParams combining DeveloperBillingOptionParams and SubscriptionUpdateParams
val billingFlowParams = BillingFlowParams.newBuilder()
    .setProductDetailsParamsList(
        listOf(
            BillingFlowParams.ProductDetailsParams.newBuilder()
                // Fetched using queryProductDetailsAsync.
                .setProductDetails(productDetailsNewPlan)
                // offerIdToken can be found in ProductDetails=>SubscriptionOfferDetails.
                .setOfferToken(offerTokenNewPlan)
                .build()
        )
    )
    .setSubscriptionUpdateParams(
        SubscriptionUpdateParams.newBuilder()
            .setOriginalExternalTransactionId(externalTransactionId)
            .build()
    )
    .enableDeveloperBillingOption(developerBillingOptionParams)
    .build()

Java


String externalTransactionId = //... ;

// 1. Construct DeveloperBillingOptionParams indicating the billing program
DeveloperBillingOptionParams developerBillingOptionParams =
    DeveloperBillingOptionParams.newBuilder()
        .setBillingProgram(BillingClient.BillingProgram.BILLING_CHOICE)
        .build();

// 2. Add ProductDetailsParams
List productDetailsParamsList = new ArrayList<>();
productDetailsParamsList.add(
    ProductDetailsParams.newBuilder()
        // Fetched using queryProductDetailsAsync.
        .setProductDetails(productDetailsNewPlan)
        // offerIdToken can be found in ProductDetails=>SubscriptionOfferDetails
        .setOfferToken(offerTokenNewPlan)
        .build());

// 3. Build BillingFlowParams combining DeveloperBillingOptionParams and SubscriptionUpdateParams
BillingFlowParams billingFlowParams =
    BillingFlowParams.newBuilder()
        .setProductDetailsParamsList(productDetailsParamsList)
        .setSubscriptionUpdateParams(
            SubscriptionUpdateParams.newBuilder()
                .setOriginalExternalTransactionId(externalTransactionId)
                .build())
        .enableDeveloperBillingOption(developerBillingOptionParams)
        .build();


Sie müssen auch ein neues externes Transaktionstoken generieren. Beispiel:

Kotlin

val params =
    BillingProgramReportingDetailsParams.newBuilder()
        .setBillingProgram(BillingProgram.BILLING_CHOICE)
        .setDeveloperBillingType(DeveloperBillingType.EXTERNAL_LINK)
        .build()

val (billingResult, billingProgramReportingDetails) =
    billingClient.createBillingProgramReportingDetails(params)

if (billingResult.responseCode != BillingResponseCode.OK) {
    // Handle failures such as retrying due to network errors.
    return
}

val externalTransactionToken =
    billingProgramReportingDetails?.externalTransactionToken
// Persist the external transaction token locally. Pass it to
// the external website using DeveloperBillingOptionParams when
// launchBillingFlow is called.

Java


BillingProgramReportingDetailsParams params =
    BillingProgramReportingDetailsParams.newBuilder()
        .setBillingProgram(BillingProgram.BILLING_CHOICE)
        .setDeveloperBillingType(DeveloperBillingType.EXTERNAL_LINK)
        .build();

billingClient.createBillingProgramReportingDetailsAsync(
    params,
    new BillingProgramReportingDetailsListener() {
      @Override
      public void onCreateBillingProgramReportingDetailsResponse(
          BillingResult billingResult,
          @Nullable BillingProgramReportingDetails billingProgramReportingDetails) {
        if (billingResult.getResponseCode() != BillingResponseCode.OK) {
          // Handle failures such as retrying due to network errors.
          return;
        }
        String transactionToken =
            billingProgramReportingDetails.getExternalTransactionToken();
        // Persist the external transaction token locally. Pass it to
        // the external website using DeveloperBillingOptionParams when
        // launchBillingFlow is called.
      }
    });

Nachdem Sie das neue Token generiert haben, müssen Sie die launchBillingFlow Methode aufrufen, um den Kaufvorgang zu starten.

Nach Abschluss des Upgrades oder Downgrades müssen Sie eine neue Transaktion mit dem externen Transaktionstoken melden, das Sie durch den vorherigen Aufruf für den neuen Abo-Kauf erhalten haben.

Abo-Ersetzung in Szenario 2B

Die Schritte zum Verarbeiten der Abo-Ersetzung in diesem Szenario ähneln den Schritten, die unter Abo-Ersetzung in Szenario 2A beschrieben sind. Der einzige Unterschied besteht darin, dass Sie nach dem Generieren des Transaktionstokens anstelle der Methode launchBillingFlow die Methode launchExternalLink aufrufen müssen, um das Dialogfeld mit dem Haftungsausschluss für den Linkout anzuzeigen. In diesem Szenario wird die Nutzerauswahl beibehalten und Sie müssen den Bildschirm für die Auswahl für ein Upgrade oder Downgrade nicht anzeigen.

Beispielcode für die Einbindung finden Sie in Schritt 6 unter Szenario 2B: Der Entwickler rendert den Bildschirm für die Auswahl und die alternative Abrechnung erfolgt in Ihrer App.

Nach Abschluss des Upgrades oder Downgrades müssen Sie eine neue Transaktion mit dem externen Transaktionstoken melden, das Sie durch den vorherigen Aufruf für den neuen Abo-Kauf erhalten haben.