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

In diesem Leitfaden wird beschrieben, wie Sie Ihre App in die APIs der Play Billing Library einbinden, damit Sie Ihren Nutzern die Abrechnung mit Auswahlmöglichkeit anbieten können.

Integration mit PBL

Sie können die Abrechnungsauswahl in vier Szenarien in die PBL einbinden. Die Szenarien unterscheiden sich je nachdem, wer den Auswahlbildschirm rendert und wo die Zahlung erfolgt. In der folgenden Tabelle sind die Integrationsszenarien aufgeführt:

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

Google rendert den Auswahlbildschirm und die alternative Abrechnung erfolgt in Ihrer App.

Szenario 1B

Der App-Entwickler rendert den Auswahlbildschirm und die alternative Abrechnung erfolgt in Ihrer App.

Externer Weblink Szenario 2A

Google rendert den Auswahlbildschirm und der Nutzer wird für Käufe von Ihrer App zu Ihren eigenen Websites weitergeleitet.

Szenario 2B

Der App-Entwickler rendert den Auswahlbildschirm und der Nutzer wird für Käufe von Ihrer App zu Ihren eigenen Websites weitergeleitet.

Die folgende Abbildung veranschaulicht den Abrechnungsauswahlprozess für jedes dieser Szenarien:

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

PBL-Integrationsszenarien

Je nach Integrationsszenario müssen Sie die Schritte in diesem Abschnitt ausführen, um die Abrechnungsauswahl in Ihre App zu implementieren.

Szenario 1A bearbeiten

Google rendert den Auswahlbildschirm und die alternative Abrechnung erfolgt in Ihrer App. Gehen Sie so vor, 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 params = 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(params)
        .build()
    
    // Establish a connection to Google Play
    val billingResult = suspendCancellableCoroutine { 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.
                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() {
                continuation.resume(
                    BillingResult.newBuilder()
                        .setResponseCode(BillingClient.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 Abrechnungsoption für den Nutzer verfügbar ist.

    Rufen Sie isBillingProgramAvailableAsync an, um die Programmverfügbarkeit zu prüfen, und rufen Sie dann queryProductDetailsAsync an, 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 Abrechnungsbildschirm von Google oder vom Entwickler gerendert wird.

  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: Die Elternaufsicht wird für Nutzer mit Elternaufsicht angezeigt.

  4. So gehen Sie vor, wenn der Nutzer den Abrechnungstyp auswählt:

    • Wenn der Nutzer Play Billing auswählt, wird das Abrechnungsergebnis an die in Schritt 1 registrierte PurchasesUpdatedListener zurückgegeben.
    • Wenn der Nutzer Ihre alternative Abrechnung auswählt, wird das Abrechnungsergebnis an die in Schritt 1 registrierte DeveloperProvidedBillingListener zurückgegeben. Der zurückgegebene DeveloperProvidedBillingDetails enthält in diesem Fall einen externalTransactionToken. Das Token wird für die Transaktionsberichterstellung verwendet.

Szenario 1B bearbeiten

Der Entwickler rendert den Auswahlbildschirm und die alternative Abrechnung wird in Ihrer App abgewickelt. Führen Sie die folgenden Schritte aus, um die Abrechnungsauswahl in diesem Szenario zu aktivieren:

  1. Rufen Sie enableBillingProgram ohne DeveloperProvidedBillingListener in EnableBillingProgramParams auf, wenn Sie eine BillingClient-Instanz erstellen, und starten Sie dann die Verbindung. Beispiel:

    Kotlin

    
    // Build the parameters to enable the Billing Choice program.
    val params = EnableBillingProgramParams.newBuilder()
        .setBillingProgram(BillingProgram.BILLING_CHOICE)
        .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()
        .enableBillingProgram(params)
        .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.
                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() {
                continuation.resume(
                    BillingResult.newBuilder()
                        .setResponseCode(BillingClient.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 Abrechnungsoption für den Nutzer verfügbar ist.

    Rufen Sie isBillingProgramAvailableAsync an, um die Programmverfügbarkeit zu prüfen, und rufen Sie dann queryProductDetailsAsync an, 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 ein von Google oder vom Entwickler gerenderter Bildschirm zur Auswahl der Abrechnung verfügbar ist.

  3. Rufen Sie die getBillingChoiceInfoAsync-Methode auf, um das Play Billing-Banner und Treuepunkteinformationen abzurufen. Beispiel:

    Kotlin

    
    // 1. Create the params required for the request
    val params = GetBillingChoiceInfoParams.newBuilder()
        .setBillingProgram(BillingClient.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 Token für externe Transaktionen, bei dem „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 Informationsdialog für Nutzer. BillingProgram und transactionToken aus Schritt 4 müssen in der Anfrage festgelegt werden.

    Hinweis: Die Elternaufsicht wird für Nutzer mit Elternaufsicht angezeigt.

  6. Starten Sie den Auswahlbildschirm für das alternative Abrechnungssystem, wenn das Ergebnis aus dem vorherigen Schritt OK ist.

  7. So gehen Sie vor, wenn der Nutzer den Abrechnungstyp auswählt:

    • Wenn der Nutzer Play Billing auswählt, rufen Sie launchBillingFlow gemäß den Standardrichtlinien für Play Billing auf. Das Abrechnungsergebnis wird an die in Schritt 1 registrierte PurchasesUpdatedListener zurückgegeben.
    • Wenn der Nutzer Ihr alternatives Abrechnungssystem auswählt, müssen Sie die Transaktion selbst abwickeln und sie mit dem in Schritt 4 generierten Token an Play melden.

Szenario 2A bearbeiten

Google rendert den Auswahlbildschirm und die alternative Abrechnung wird außerhalb Ihrer App abgewickelt. 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 params = 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(params)
        .build()
    
    // Establish a connection to Google Play
    val billingResult = suspendCancellableCoroutine { 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.
                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() {
                continuation.resume(
                    BillingResult.newBuilder()
                        .setResponseCode(BillingClient.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 an, um die Programmverfügbarkeit zu prüfen, und rufen Sie dann queryProductDetailsAsync an, um verfügbare Produkte aufzurufen. Beispiel:

    Kotlin

    
    // Check the availability of the billing choice program asynchronously using coroutines
    val (billingResult, billingProgramAvailabilityDetails) =
        billingClient.isBillingProgramAvailable(BillingProgram.BILLING_CHOICE)
    
    // Ensure the billing program query succeeded
    if (billingResult.responseCode == BillingResponseCode.OK) {
        // Retrieve the availability details specific to the billing choice program
        val billingChoiceAvailabilityDetails =
            billingProgramAvailabilityDetails.billingChoiceAvailabilityDetails
    
        // Check if billing choice is available, renders via Google Play, and external link is supported
        if (billingChoiceAvailabilityDetails != null &&
            billingChoiceAvailabilityDetails.choiceScreenType == 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.
    }
    
    
    

    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 Transaktions-Token zu erstellen, wenn der Nutzer die Absicht zum Kauf zeigt. Beispiel:

    Kotlin

    
    // Build the parameters for creating reporting details
    val params =
        BillingProgramReportingDetailsParams.newBuilder()
            .setBillingProgram(BillingProgram.BILLING_CHOICE)
            .setDeveloperBillingType(DeveloperBillingType.EXTERNAL_LINK)
            .build()
    
    // Call the suspend function to create billing program reporting details
    val (billingResult, billingProgramReportingDetails) =
        billingClient.createBillingProgramReportingDetails(params)
    
    // Handle response failure cases
    if (billingResult.responseCode != BillingResponseCode.OK) {
        // Handle failures such as retrying due to network errors.
        return
    }
    
    // Retrieve the external transaction token
    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.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

    
    // Build the developer billing option parameters with the external link URI,
    // the transaction token, and browser/app launch mode.
    val 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()
    
    

    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: Die Elternaufsicht wird für Nutzer mit Elternaufsicht angezeigt.

  5. So gehen Sie vor, wenn der Nutzer den Abrechnungstyp auswählt:

Szenario 2B bearbeiten

Der Entwickler rendert den Auswahlbildschirm 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 ohne DeveloperProvidedBillingListener in EnableBillingProgramParams auf, wenn Sie eine BillingClient-Instanz erstellen, und starten Sie dann die Verbindung. Beispiel:

    Kotlin

    
    // Build the parameters to enable the Billing Choice program.
    val params = EnableBillingProgramParams.newBuilder()
        .setBillingProgram(BillingProgram.BILLING_CHOICE)
        .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()
        .enableBillingProgram(params)
        .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.
                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() {
                continuation.resume(
                    BillingResult.newBuilder()
                        .setResponseCode(BillingClient.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 an, um die Programmverfügbarkeit zu prüfen, und rufen Sie dann queryProductDetailsAsync an, um verfügbare Produkte aufzurufen. Beispiel:

    Kotlin

    
    // Check the availability of the billing choice program asynchronously using a coroutine
    val (billingResult, billingProgramAvailabilityDetails) =
        billingClient.isBillingProgramAvailable(BillingProgram.BILLING_CHOICE)
    
    // Ensure the response code is OK
    if (billingResult.responseCode == BillingResponseCode.OK) {
        // Retrieve the billing choice availability details
        val billingChoiceAvailabilityDetails =
            billingProgramAvailabilityDetails.billingChoiceAvailabilityDetails
    
        // Check if billing choice details are available, choice screen is developer-rendered,
        // and external transaction links are supported.
        if (billingChoiceAvailabilityDetails != null &&
            billingChoiceAvailabilityDetails.choiceScreenType == 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.
    }
    
    

    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 getBillingChoiceInfoAsync-Methode auf, um das Play Billing-Banner und Treuepunkteinformationen abzurufen.

    Kotlin

    
    // 1. Create the params required for the request
    val params = GetBillingChoiceInfoParams.newBuilder()
        .setBillingProgram(BillingClient.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 Transaktions-Token zu erstellen, wenn der Nutzer die Absicht zum Kauf zeigt. Beispiel:

    Kotlin

    
    // Build the parameters for creating reporting details
    val params =
        BillingProgramReportingDetailsParams.newBuilder()
            .setBillingProgram(BillingProgram.BILLING_CHOICE)
            .setDeveloperBillingType(DeveloperBillingType.EXTERNAL_LINK)
            .build()
    
    // Call the suspend function to create billing program reporting details
    val (billingResult, billingProgramReportingDetails) =
        billingClient.createBillingProgramReportingDetails(params)
    
    // Handle response failure cases
    if (billingResult.responseCode != BillingResponseCode.OK) {
        // Handle failures such as retrying due to network errors.
        return
    }
    
    // Retrieve the external transaction token
    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.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 den Bildschirm für die alternative Auswahl, wenn der Nutzer auf „Kaufen“ klickt.

  6. So gehen Sie vor, wenn der Nutzer den Abrechnungstyp auswählt:

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

      Jugendschutzeinstellungen werden für Nutzer mit Elternaufsicht angezeigt.

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

      Kotlin

      
      // An activity reference from which the purchase flow will be launched.
      val activity: Activity = ...
      
      val 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
          )
          .build()
      
      // Call launchExternalLink with a callback
      billingClient.launchExternalLink(activity, params) { billingResult ->
          if (billingResult.responseCode == 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.
          }
      }
      
      

      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 Transaktions-Token aus Schritt 4 an LaunchExternalLinkParams. Wenn „OK“ zurückgegeben wird, fahren Sie mit der Transaktion fort und melden Sie sie Google Play.

      Jugendschutzeinstellungen werden für Nutzer mit Elternaufsicht angezeigt.

Abrechnungsauswahl beim Ersetzen eines Abos

Bei einem Abo-Ersatz sollte der Nutzerauswahl-Bildschirm 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 abgewickelt wurde, solltest du launchBillingFlow mit den Standardinformationen zum Abo-Ersatz über Google Play Billing anrufen.

Wenn der ursprüngliche Kauf jedoch über eine alternative Abrechnung verarbeitet wurde, unterscheidet sich die Bearbeitung von Abo-Ersatz je nach Szenario geringfügig.

Aboersetzung in Szenario 1A

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

Rufen Sie dazu launchBillingFlow auf, wenn der Nutzer ein Upgrade oder 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 zur Nutzerauswahl wird nicht angezeigt, da die Nutzerauswahl für den ursprünglichen Kauf bei 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 = //... ;

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(
        BillingFlowParams.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.


Wenn das Upgrade oder Downgrade abgeschlossen ist, müssen Sie eine neue Transaktion melden. Verwenden Sie dazu das externe Transaktions-Token, das Sie beim vorherigen Aufruf für den Kauf des neuen Abos erhalten haben.

Aboersetzung in Szenario 1B

In diesem Fall 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 bei einem Upgrade oder Downgrade nicht anzeigen müssen. Sie müssen jedoch den einmaligen Informationsdialog und die Bestätigung der Eltern anzeigen.

Beispielcode für die Integration finden Sie unter Schritt 4 in Szenario 1B: Der Entwickler rendert den Auswahlbildschirm und die alternative Abrechnung wird in Ihrer App abgewickelt.

Wenn das Upgrade oder Downgrade abgeschlossen ist, müssen Sie eine neue Transaktion melden. Verwenden Sie dazu das externe Transaktions-Token, das Sie beim vorherigen Aufruf für den Kauf des neuen Abos erhalten haben.

Aboersetzung in Szenario 2A

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

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

Kotlin


val externalTransactionId = //... ;

// 1. Construct DeveloperBillingOptionParams indicating the billing program
val developerBillingOptionParams = DeveloperBillingOptionParams.newBuilder()
    .setBillingProgram(BillingClient.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();


Außerdem müssen Sie ein neues externes Transaktionstoken generieren. Beispiel:

Kotlin


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

billingClient.createBillingProgramReportingDetailsAsync(
    params,
    object : BillingProgramReportingDetailsListener {
        override fun onCreateBillingProgramReportingDetailsResponse(
            billingResult: BillingResult,
            billingProgramReportingDetails: BillingProgramReportingDetails?
        ) {
            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 Methode launchBillingFlow aufrufen, um den Kaufvorgang zu starten.

Wenn das Upgrade oder Downgrade abgeschlossen ist, müssen Sie eine neue Transaktion melden. Verwenden Sie dazu das externe Transaktions-Token, das Sie beim vorherigen Aufruf für den Kauf des neuen Abos erhalten haben.

Aboersetzung in Szenario 2B

Die Schritte zum Verarbeiten des Abo-Ersatzes in diesem Szenario ähneln den Schritten, die unter Abo-Ersatz in Szenario 2A beschrieben werden. 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 externe Links aufzurufen. In diesem Fall bleibt die Nutzerauswahl erhalten und Sie müssen den Auswahlbildschirm für das Upgrade oder Downgrade nicht anzeigen.

Beispielcode für die Integration finden Sie in Schritt 6 in Szenario 2B: Der Entwickler rendert den Auswahlbildschirm und die alternative Abrechnung wird in Ihrer App abgewickelt.

Wenn das Upgrade oder Downgrade abgeschlossen ist, müssen Sie eine neue Transaktion melden. Verwenden Sie dazu das externe Transaktions-Token, das Sie beim vorherigen Aufruf für den Kauf des neuen Abos erhalten haben.