Integra la Libreria Fatturazione Google Play nella tua app

Questo argomento descrive come integrare la Libreria Fatturazione Google Play nella tua app per iniziare a vendere prodotti.

Durata di un acquisto

Di seguito è riportato un flusso di acquisto tipico per un acquisto una tantum o un abbonamento.

  1. Mostrare all'utente cosa può acquistare.
  2. Avvia il flusso di acquisto per consentire all'utente di accettare l'acquisto.
  3. Verifica l'acquisto sul tuo server.
  4. Fornisci contenuti all'utente.
  5. Confermare la consegna dei contenuti. Per i prodotti di consumo, utilizza l'acquisto in modo che l'utente possa acquistarlo di nuovo.

Gli abbonamenti si rinnovano automaticamente fino all'annullamento. Un abbonamento può essere tra i seguenti stati:

  • Attivo. L'utente è in regola e ha accesso all'abbonamento.
  • Annullato: l'utente ha annullato l'abbonamento, ma ha ancora accesso fino alla scadenza.
  • In periodo di tolleranza: l'utente ha riscontrato un problema di pagamento, ma può ancora accedere mentre Google sta riprovando a utilizzare il metodo di pagamento.
  • In attesa: l'utente ha riscontrato un problema di pagamento e non ha più accesso mentre Google sta riprovando a utilizzare il metodo di pagamento.
  • In pausa: l'utente ha messo in pausa l'accesso e non vi avrà accesso finché non lo riprende.
  • Scaduto: l'utente ha annullato l'accesso e non ha più accesso all'abbonamento. L'utente è considerato abbandonato alla scadenza.

Inizializzare una connessione a Google Play

Il primo passaggio per l'integrazione con il sistema di fatturazione di Google Play è aggiungere la Libreria Fatturazione Google Play all'app e inizializzare una connessione.

Aggiungi la dipendenza Libreria Fatturazione Google Play

Aggiungi la dipendenza Libreria Fatturazione Google Play al file build.gradle della tua app, come mostrato:

Trendy

dependencies {
    def billing_version = "6.1.0"

    implementation "com.android.billingclient:billing:$billing_version"
}

Kotlin

dependencies {
    val billing_version = "6.1.0"

    implementation("com.android.billingclient:billing:$billing_version")
}

Se utilizzi Kotlin, il modulo KTX della Libreria Fatturazione Google Play contiene il supporto di estensioni e coroutine di Kotlin che ti consentono di scrivere Kotlin idiomatico quando utilizzi la Libreria Fatturazione Google Play. Per includere queste estensioni nel progetto, aggiungi la seguente dipendenza al file build.gradle della tua app come mostrato:

Trendy

dependencies {
    def billing_version = "6.1.0"

    implementation "com.android.billingclient:billing-ktx:$billing_version"
}

Kotlin

dependencies {
    val billing_version = "6.1.0"

    implementation("com.android.billingclient:billing-ktx:$billing_version")
}

Inizializza un cliente di fatturazione

Dopo aver aggiunto una dipendenza a Libreria Fatturazione Google Play, devi inizializzare un'istanza BillingClient. BillingClient è l'interfaccia principale per la comunicazione tra la Libreria Fatturazione Google Play e il resto della tua app. BillingClient offre metodi pratici, sia sincroni che asincroni, per molte operazioni di fatturazione comuni. Ti consigliamo vivamente di tenere aperta una connessione BillingClient attiva contemporaneamente per evitare più callback PurchasesUpdatedListener per un singolo evento.

Per creare un BillingClient, usa newBuilder(). Puoi passare qualsiasi contesto a newBuilder(), che BillingClient lo utilizza per ottenerne uno. Ciò significa che non devi preoccuparti di perdite di memoria. Per ricevere aggiornamenti sugli acquisti, devi anche chiamare setListener(), passando un riferimento a PurchasesUpdatedListener. Questo listener riceve aggiornamenti per tutti gli acquisti nella tua app.

Kotlin

private val purchasesUpdatedListener =
   PurchasesUpdatedListener { billingResult, purchases ->
       // To be implemented in a later section.
   }

private var billingClient = BillingClient.newBuilder(context)
   .setListener(purchasesUpdatedListener)
   .enablePendingPurchases()
   .build()

Java

private PurchasesUpdatedListener purchasesUpdatedListener = new PurchasesUpdatedListener() {
    @Override
    public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
        // To be implemented in a later section.
    }
};

private BillingClient billingClient = BillingClient.newBuilder(context)
    .setListener(purchasesUpdatedListener)
    .enablePendingPurchases()
    .build();

Collegati a Google Play

Dopo aver creato BillingClient, devi stabilire una connessione a Google Play.

Per connetterti a Google Play, chiama il numero startConnection(). Il processo di connessione è asincrono e devi implementare BillingClientStateListener per ricevere un callback quando la configurazione del client è completa e il client è pronto a effettuare ulteriori richieste.

Devi anche implementare la logica dei nuovi tentativi per gestire le connessioni perse a Google Play. Per implementare la logica di nuovo tentativo, sostituisci il metodo di callback onBillingServiceDisconnected() e assicurati che BillingClient chiami il metodo startConnection() per riconnettersi a Google Play prima di effettuare ulteriori richieste.

L'esempio seguente mostra come avviare una connessione e verificare che sia pronta per l'uso:

Kotlin

billingClient.startConnection(object : BillingClientStateListener {
    override fun onBillingSetupFinished(billingResult: BillingResult) {
        if (billingResult.responseCode ==  BillingResponseCode.OK) {
            // The BillingClient is ready. You can query purchases here.
        }
    }
    override fun onBillingServiceDisconnected() {
        // Try to restart the connection on the next request to
        // Google Play by calling the startConnection() method.
    }
})

Java

billingClient.startConnection(new BillingClientStateListener() {
    @Override
    public void onBillingSetupFinished(BillingResult billingResult) {
        if (billingResult.getResponseCode() ==  BillingResponseCode.OK) {
            // The BillingClient is ready. You can query purchases here.
        }
    }
    @Override
    public void onBillingServiceDisconnected() {
        // Try to restart the connection on the next request to
        // Google Play by calling the startConnection() method.
    }
});

Mostra i prodotti disponibili per l'acquisto

Dopo aver stabilito una connessione a Google Play, puoi eseguire una query relativa ai prodotti disponibili e mostrarli agli utenti.

Eseguire una query sui dettagli dei prodotti è un passaggio importante prima di mostrare i prodotti agli utenti, poiché restituisce informazioni localizzate sui prodotti. Per gli abbonamenti, assicurati che la visualizzazione del prodotto rispetti tutte le norme di Google Play.

Per eseguire una query sui dettagli del prodotto in-app, chiama queryProductDetailsAsync().

Per gestire il risultato dell'operazione asincrona, devi specificare anche un ascoltatore che implementa l'interfaccia ProductDetailsResponseListener. Puoi quindi eseguire l'override di onProductDetailsResponse(), che invia una notifica all'ascoltatore al termine della query, come mostrato nell'esempio seguente:

Kotlin

val queryProductDetailsParams =
    QueryProductDetailsParams.newBuilder()
        .setProductList(
            ImmutableList.of(
                Product.newBuilder()
                    .setProductId("product_id_example")
                    .setProductType(ProductType.SUBS)
                    .build()))
        .build()

billingClient.queryProductDetailsAsync(queryProductDetailsParams) {
    billingResult,
    productDetailsList ->
      // check billingResult
      // process returned productDetailsList
}

Java

QueryProductDetailsParams queryProductDetailsParams =
    QueryProductDetailsParams.newBuilder()
        .setProductList(
            ImmutableList.of(
                Product.newBuilder()
                    .setProductId("product_id_example")
                    .setProductType(ProductType.SUBS)
                    .build()))
        .build();

billingClient.queryProductDetailsAsync(
    queryProductDetailsParams,
    new ProductDetailsResponseListener() {
        public void onProductDetailsResponse(BillingResult billingResult,
                List<ProductDetails> productDetailsList) {
            // check billingResult
            // process returned productDetailsList
        }
    }
)

Quando esegui query sui dettagli del prodotto, trasmetti un'istanza di QueryProductDetailsParams che specifichi un elenco di stringhe di ID prodotto create in Google Play Console insieme a un ProductType. Il valore ProductType può essere ProductType.INAPP per i prodotti a pagamento singolo o ProductType.SUBS per gli abbonamenti.

Esecuzione di query con le estensioni Kotlin

Se utilizzi estensioni Kotlin, puoi eseguire una query sui dettagli dei prodotti in-app chiamando la funzione dell'estensione queryProductDetails().

queryProductDetails() sfrutta le coroutine Kotlin, in modo da non dover definire un listener separato. La funzione viene invece sospesa fino al completamento dell'esecuzione della query, dopodiché puoi elaborare il risultato:

suspend fun processPurchases() {
    val productList = ArrayList<String>()
    productList.add(
              QueryProductDetailsParams.Product.newBuilder()
                  .setProductId("product_id_example")
                  .setProductType(BillingClient.ProductType.SUBS)
                  .build()
           )
    val params = QueryProductDetailsParams.newBuilder()
    params.setProductList(productList)

    // leverage queryProductDetails Kotlin extension function
    val productDetailsResult = withContext(Dispatchers.IO) {
        billingClient.queryProductDetails(params.build())
    }

    // Process the result.
}

Raramente alcuni dispositivi non sono in grado di supportare ProductDetails e queryProductDetailsAsync(), generalmente a causa di versioni obsolete di Google Play Services. Per garantire un supporto adeguato per questo scenario, scopri come utilizzare le funzionalità di compatibilità con le versioni precedenti nella guida alla migrazione di Libreria Fatturazione Play 5.

Elabora il risultato

La Libreria Fatturazione Google Play archivia i risultati della query in un elemento List di ProductDetails oggetti. Puoi quindi chiamare diversi metodi su ogni oggetto ProductDetails dell'elenco per visualizzare le informazioni pertinenti su un prodotto in-app, come il prezzo o la descrizione. Per visualizzare le informazioni disponibili sui dettagli del prodotto, consulta l'elenco dei metodi nella classe ProductDetails.

Prima di mettere in vendita un articolo, verifica che l'utente non ne possieda già l'articolo. Se l'utente ha un elemento di consumo ancora presente nella raccolta di elementi, deve utilizzare l'elemento prima di poterlo acquistare di nuovo.

Prima di offrire un abbonamento, verifica che l'utente non sia già abbonato. Tieni inoltre presente quanto segue:

  • queryProductDetailsAsync() restituisce i dettagli del prodotto in abbonamento e un massimo di 50 offerte per abbonamento.
  • queryProductDetailsAsync() restituisce solo le offerte per le quali l'utente è idoneo. Se l'utente tenta di acquistare un'offerta per cui non è idoneo (ad esempio se l'app mostra un elenco obsoleto di offerte idonee), Google Play informa l'utente di non essere idoneo e può scegliere di acquistare il piano base.

Avviare il flusso di acquisto

Per avviare una richiesta di acquisto dalla tua app, chiama il metodo launchBillingFlow() dal thread principale dell'app. Questo metodo prende un riferimento a un oggetto BillingFlowParams contenente l'oggetto ProductDetails pertinente ottenuto dalle chiamate queryProductDetailsAsync(). Per creare un oggetto BillingFlowParams, utilizza la classe BillingFlowParams.Builder.

Kotlin

// An activity reference from which the billing flow will be launched.
val activity : Activity = ...;

val productDetailsParamsList = listOf(
    BillingFlowParams.ProductDetailsParams.newBuilder()
        // retrieve a value for "productDetails" by calling queryProductDetailsAsync()
        .setProductDetails(productDetails)
        // For One-time product, "setOfferToken" method shouldn't be called.
        // For subscriptions, to get an offer token, call ProductDetails.subscriptionOfferDetails()
        // for a list of offers that are available to the user
        .setOfferToken(selectedOfferToken)
        .build()
)

val billingFlowParams = BillingFlowParams.newBuilder()
    .setProductDetailsParamsList(productDetailsParamsList)
    .build()

// Launch the billing flow
val billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)

Java

// An activity reference from which the billing flow will be launched.
Activity activity = ...;

ImmutableList<ProductDetailsParams> productDetailsParamsList =
    ImmutableList.of(
        ProductDetailsParams.newBuilder()
             // retrieve a value for "productDetails" by calling queryProductDetailsAsync()
            .setProductDetails(productDetails)
            // For one-time products, "setOfferToken" method shouldn't be called.
            // For subscriptions, to get an offer token, call
            // ProductDetails.subscriptionOfferDetails() for a list of offers
            // that are available to the user.
            .setOfferToken(selectedOfferToken)
            .build()
    );

BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
    .setProductDetailsParamsList(productDetailsParamsList)
    .build();

// Launch the billing flow
BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams);

Il metodo launchBillingFlow() restituisce uno dei vari codici di risposta elencati in BillingClient.BillingResponseCode. Assicurati di controllare questo risultato per assicurarti che non si siano verificati errori durante l'avvio del flusso di acquisto. Un BillingResponseCode di OK indica che il lancio è andato a buon fine.

Durante una chiamata al numero launchBillingFlow(), il sistema mostra la schermata di acquisto di Google Play. La figura 1 mostra la schermata di acquisto di un abbonamento:

la schermata di acquisto di Google Play mostra un abbonamento
 disponibile per l&#39;acquisto
Figura 1. Nella schermata di acquisto di Google Play viene mostrato un abbonamento che è possibile acquistare.

Google Play chiama onPurchasesUpdated() per inviare il risultato dell'operazione di acquisto a un listener che implementa l'interfaccia PurchasesUpdatedListener. Il listener viene specificato utilizzando il metodo setListener() quando hai inizializzato il client.

Devi implementare onPurchasesUpdated() per gestire i possibili codici di risposta. L'esempio seguente mostra come eseguire l'override di onPurchasesUpdated():

Kotlin

override fun onPurchasesUpdated(billingResult: BillingResult, purchases: List<Purchase>?) {
   if (billingResult.responseCode == BillingResponseCode.OK && purchases != null) {
       for (purchase in purchases) {
           handlePurchase(purchase)
       }
   } else if (billingResult.responseCode == BillingResponseCode.USER_CANCELED) {
       // Handle an error caused by a user cancelling the purchase flow.
   } else {
       // Handle any other error codes.
   }
}

Java

@Override
void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
    if (billingResult.getResponseCode() == BillingResponseCode.OK
        && purchases != null) {
        for (Purchase purchase : purchases) {
            handlePurchase(purchase);
        }
    } else if (billingResult.getResponseCode() == BillingResponseCode.USER_CANCELED) {
        // Handle an error caused by a user cancelling the purchase flow.
    } else {
        // Handle any other error codes.
    }
}

Un acquisto andato a buon fine genera una schermata di successo dell'acquisto su Google Play, simile alla Figura 2.

schermata di acquisto di google play riuscita
Figura 2. Schermata di riuscita dell'acquisto di Google Play.

Un acquisto riuscito genera anche un token di acquisto, ovvero un identificatore univoco che rappresenta l'utente e l'ID prodotto del prodotto in-app acquistato. Le tue app possono archiviare il token di acquisto localmente, ma ti consigliamo di trasmetterlo al tuo server di backend sicuro, dove potrai verificare l'acquisto e proteggerti dalle frodi. Questo processo è descritto più approfonditamente nella sezione seguente.

All'utente viene inoltre inviata via email una ricevuta della transazione contenente un ID ordine o un ID univoco della transazione. Gli utenti ricevono un'email con un ID ordine univoco per ogni acquisto del prodotto una tantum, nonché per l'acquisto iniziale dell'abbonamento e i successivi rinnovi automatici ricorrenti. Puoi utilizzare l'ID ordine per gestire i rimborsi in Google Play Console.

Indica un prezzo personalizzato

Se la tua app può essere distribuita agli utenti nell'Unione Europea, usa il metodo setIsOfferPersonalized() per comunicare agli utenti che il prezzo di un articolo è stato personalizzato mediante processi decisionali automatizzati.

La schermata di acquisto di Google Play indica che il prezzo è stato personalizzato per l&#39;utente.
Figura 3. La schermata di acquisto di Google Play indica che il prezzo è stato personalizzato per l'utente.

Devi consultare l'articolo 6 (1) (ea) CRD della direttiva sui diritti dei consumatori (2011/83/UE) per determinare se il prezzo che offri agli utenti è personalizzato.

setIsOfferPersonalized() accetta un input booleano. Quando true, l'interfaccia utente di Google Play include l'informativa. Se false, la UI omette l'informativa. Il valore predefinito è false.

Per ulteriori informazioni, visita il Centro assistenza per i consumatori.

Elaborazione degli acquisti in corso...

Una volta che l'utente completa un acquisto, la tua app deve elaborarlo. Nella maggior parte dei casi, la tua app riceve una notifica degli acquisti tramite il tuo PurchasesUpdatedListener. Tuttavia, in alcuni casi la tua app viene segnalata agli acquisti chiamando il numero BillingClient.queryPurchasesAsync() come descritto nella sezione Recupero degli acquisti.

Inoltre, se hai un client Notifiche in tempo reale per lo sviluppatore nel tuo backend sicuro, puoi registrare i nuovi acquisti ricevendo un subscriptionNotification o un oneTimeProductNotification (solo per gli acquisti in attesa) che ti avvisano di un nuovo acquisto. Dopo aver ricevuto queste notifiche, chiama l'API Google Play Developer per ottenere lo stato completo e aggiornare il tuo stato del backend.

L'app dovrebbe elaborare un acquisto nel seguente modo:

  1. Verifica l'acquisto.
  2. Fornisci contenuti all'utente e conferma la consegna dei contenuti. Se vuoi, contrassegna l'articolo come consumato in modo che l'utente possa acquistarlo di nuovo.

Per verificare un acquisto, controlla innanzitutto che lo stato di acquisto sia PURCHASED. Se l'acquisto è PENDING, devi elaborarlo come descritto in Gestione delle transazioni in sospeso. Per gli acquisti ricevuti da onPurchasesUpdated() o queryPurchasesAsync(), devi verificare ulteriormente l'acquisto per garantire la legittimità prima che l'app conceda il diritto. Per scoprire come verificare correttamente un acquisto, vedi Verificare gli acquisti prima di concedere i diritti.

Una volta verificato l'acquisto, la tua app sarà pronta a concedere il diritto all'utente. L'account utente associato all'acquisto può essere identificato con il ProductPurchase.obfuscatedExternalAccountId restituito da Purchases.products:get per gli acquisti di prodotti in-app e con il SubscriptionPurchase.obfuscatedExternalAccountId restituito da Purchases.subscriptions:get per gli abbonamenti sul lato server o con obfuscatedAccountId da Purchase.getAccountIdentifiers() sul lato client, se impostato con setObfuscatedAccountId{/2

Dopo aver concesso il diritto, la tua app deve confermare l'acquisto. Questa conferma comunica a Google Play che hai concesso il diritto per l'acquisto.

La procedura per concedere il diritto e confermare l'acquisto dipende dal fatto che l'acquisto sia un prodotto di consumo, un non consumabile o un abbonamento.

Prodotti di consumo

Per i materiali di consumo, se la tua app ha un backend sicuro, ti consigliamo di utilizzare Purchases.products:consume per consumare gli acquisti in modo affidabile. Assicurati che l'acquisto non sia già stato utilizzato controllando il consumptionState dal risultato della chiamata al numero Purchases.products:get. Se la tua app è solo client senza un backend, utilizza consumeAsync() dalla Libreria Fatturazione Google Play. Entrambi i metodi soddisfano il requisito di conferma e indicano che la tua app ha concesso il diritto all'utente. Questi metodi consentono inoltre all'app di rendere disponibile per il riacquisto il prodotto una tantum corrispondente al token di acquisto di input. Con consumeAsync() devi anche passare un oggetto che implementa l'interfaccia ConsumeResponseListener. Questo oggetto gestisce il risultato dell'operazione di consumo. Puoi eseguire l'override del metodo onConsumeResponse(), che la Libreria Fatturazione Google Play chiama al completamento dell'operazione.

L'esempio seguente illustra l'utilizzo di un prodotto con la Libreria Fatturazione Google Play con il token di acquisto associato:

Kotlin

suspend fun handlePurchase(purchase: Purchase) {
    // Purchase retrieved from BillingClient#queryPurchasesAsync or your PurchasesUpdatedListener.
    val purchase : Purchase = ...;

    // Verify the purchase.
    // Ensure entitlement was not already granted for this purchaseToken.
    // Grant entitlement to the user.

    val consumeParams =
        ConsumeParams.newBuilder()
            .setPurchaseToken(purchase.getPurchaseToken())
            .build()
    val consumeResult = withContext(Dispatchers.IO) {
        client.consumePurchase(consumeParams)
    }
}

Java

void handlePurchase(Purchase purchase) {
    // Purchase retrieved from BillingClient#queryPurchasesAsync or your PurchasesUpdatedListener.
    Purchase purchase = ...;

    // Verify the purchase.
    // Ensure entitlement was not already granted for this purchaseToken.
    // Grant entitlement to the user.

    ConsumeParams consumeParams =
        ConsumeParams.newBuilder()
            .setPurchaseToken(purchase.getPurchaseToken())
            .build();

    ConsumeResponseListener listener = new ConsumeResponseListener() {
        @Override
        public void onConsumeResponse(BillingResult billingResult, String purchaseToken) {
            if (billingResult.getResponseCode() == BillingResponseCode.OK) {
                // Handle the success of the consume operation.
            }
        }
    };

    billingClient.consumeAsync(consumeParams, listener);
}

Prodotti non consumabili

Per riconoscere gli acquisti non consumabili, se la tua app ha un backend sicuro, ti consigliamo di utilizzare Purchases.products:acknowledge per confermare gli acquisti in modo affidabile. Assicurati che l'acquisto non sia stato confermato in precedenza controllando il acknowledgementState in seguito alla chiamata a Purchases.products:get.

Se la tua app è solo client, utilizza BillingClient.acknowledgePurchase() della Libreria Fatturazione Google Play nell'app. Prima di confermare un acquisto, l'app deve verificare se è già stato confermato utilizzando il metodo isAcknowledged() nella Libreria Fatturazione Google Play.

L'esempio seguente mostra come confermare un acquisto utilizzando la Libreria Fatturazione Google Play:

Kotlin

val client: BillingClient = ...
val acknowledgePurchaseResponseListener: AcknowledgePurchaseResponseListener = ...

suspend fun handlePurchase() {
    if (purchase.purchaseState === PurchaseState.PURCHASED) {
        if (!purchase.isAcknowledged) {
            val acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder()
                    .setPurchaseToken(purchase.purchaseToken)
            val ackPurchaseResult = withContext(Dispatchers.IO) {
               client.acknowledgePurchase(acknowledgePurchaseParams.build())
            }
        }
     }
}

Java

BillingClient client = ...
AcknowledgePurchaseResponseListener acknowledgePurchaseResponseListener = ...

void handlePurchase(Purchase purchase) {
    if (purchase.getPurchaseState() == PurchaseState.PURCHASED) {
        if (!purchase.isAcknowledged()) {
            AcknowledgePurchaseParams acknowledgePurchaseParams =
                AcknowledgePurchaseParams.newBuilder()
                    .setPurchaseToken(purchase.getPurchaseToken())
                    .build();
            client.acknowledgePurchase(acknowledgePurchaseParams, acknowledgePurchaseResponseListener);
        }
    }
}

Iscrizioni

Gli abbonamenti vengono gestiti in modo simile ai non consumabili. Se possibile, utilizza Purchases.subscriptions.acknowledge dell'API Google Play Developer per confermare in modo affidabile l'acquisto dal tuo backend sicuro. Verifica che l'acquisto non sia stato confermato in precedenza controllando il acknowledgementState nella risorsa per gli acquisti di Purchases.subscriptions:get. In alternativa, puoi confermare un abbonamento utilizzando BillingClient.acknowledgePurchase() dalla Libreria Fatturazione Google Play dopo aver selezionato isAcknowledged(). Tutti gli acquisti iniziali dell'abbonamento devono essere confermati. I rinnovi dell'abbonamento non devono essere confermati. Per ulteriori informazioni su quando è necessario confermare gli abbonamenti, consulta l'argomento Vendere abbonamenti.

Recupero acquisti in corso...

Ascoltare gli aggiornamenti sugli acquisti utilizzando un PurchasesUpdatedListener non è sufficiente per garantire che la tua app elabori tutti gli acquisti. È possibile che la tua app non sia a conoscenza di tutti gli acquisti effettuati da un utente. Di seguito sono riportati alcuni scenari in cui la tua app potrebbe perdere traccia o non essere a conoscenza degli acquisti:

  • Problemi di rete durante l'acquisto: un utente effettua un acquisto e riceve conferma da Google, ma il suo dispositivo perde la connettività di rete prima che il dispositivo riceva la notifica dell'acquisto tramite il PurchasesUpdatedListener.
  • Più dispositivi: un utente acquista un articolo su un dispositivo e si aspetta di vederlo quando cambia dispositivo.
  • Gestione degli acquisti effettuati al di fuori dell'app: alcuni acquisti, ad esempio l'utilizzo di promozioni, possono essere effettuati al di fuori della tua app.

Per gestire queste situazioni, assicurati che l'app chiami BillingClient.queryPurchasesAsync() nel metodo onResume() per assicurarti che tutti gli acquisti vengano elaborati correttamente come descritto nella sezione Elaborazione degli acquisti.

L'esempio seguente mostra come recuperare gli acquisti degli abbonamenti di un utente. Tieni presente che queryPurchasesAsync() restituisce solo abbonamenti attivi e acquisti una tantum non consumati.

Kotlin

val params = QueryPurchasesParams.newBuilder()
               .setProductType(ProductType.SUBS)

// uses queryPurchasesAsync Kotlin extension function
val purchasesResult = billingClient.queryPurchasesAsync(params.build())

// check purchasesResult.billingResult
// process returned purchasesResult.purchasesList, e.g. display the plans user owns

Java

billingClient.queryPurchasesAsync(
    QueryPurchasesParams.newBuilder()
      .setProductType(ProductType.SUBS)
      .build(),
    new PurchasesResponseListener() {
      public void onQueryPurchasesResponse(BillingResult billingResult, List purchases) {
        // check billingResult
        // process returned purchase list, e.g. display the plans user owns

      }
    }
);

Recupero cronologia acquisti in corso...

queryPurchaseHistoryAsync() restituisce l'acquisto più recente effettuato dall'utente per ogni prodotto, anche se l'acquisto è scaduto, annullato o consumato.

Se usi le estensioni Kotlin, puoi usare la funzione di estensione queryPurchaseHistory().

Kotlin

val params = QueryPurchaseHistoryParams.newBuilder()
               .setProductType(ProductType.SUBS)

// uses queryPurchaseHistory Kotlin extension function
val purchaseHistoryResult = billingClient.queryPurchaseHistory(params.build())

// check purchaseHistoryResult.billingResult
// process returned purchaseHistoryResult.purchaseHistoryRecordList, e.g. display purchase

Java

billingClient.queryPurchaseHistoryAsync(
    QueryPurchaseHistoryParams.newBuilder()
        .setProductType(ProductType.SUBS)
        .build(),
    new PurchaseHistoryResponseListener() {
      public void onPurchaseHistoryResponse(
        BillingResult billingResult, List purchasesHistoryList) {
          // check billingResult
          // process returned purchase history list, e.g. display purchase history
        }
    }
);

Gestione degli acquisti effettuati al di fuori dell'app

Alcuni acquisti, ad esempio l'utilizzo delle promozioni, possono avvenire al di fuori della tua app. Quando un utente effettua un acquisto al di fuori della tua app, si aspetta che nella tua app venga mostrato un messaggio in-app o utilizzi un qualche tipo di meccanismo di notifica per comunicare che l'app ha ricevuto ed elaborato correttamente l'acquisto. Ecco alcuni meccanismi accettati:

  • Mostra un popup in-app.
  • Invia il messaggio a una casella di messaggio in-app e indica chiaramente che è presente un nuovo messaggio.
  • Utilizza un messaggio di notifica del sistema operativo.

Tieni presente che l'app può trovarsi in qualsiasi stato quando viene riconosciuto l'acquisto. È anche possibile che l'app non venga neanche installata al momento dell'acquisto. Gli utenti si aspettano di ricevere l'acquisto quando ripristinano l'app, indipendentemente dallo stato in cui si trova.

Devi rilevare gli acquisti indipendentemente dallo stato in cui si trova l'app al momento dell'acquisto. Tuttavia, ci sono alcune eccezioni in cui può essere consentito non informare immediatamente l'utente della ricezione dell'articolo. Ecco alcuni esempi:

  • Durante l'azione di un gioco, in cui mostrare un messaggio può distrarre l'utente. In questo caso, devi inviare una notifica all'utente al termine dell'azione.
  • Durante gli intermezzi, in cui mostrare un messaggio può distrarre l'utente. In questo caso, devi avvisare l'utente al termine della scena.
  • Durante il tutorial iniziale e le parti del gioco per la configurazione dell'utente. Ti consigliamo di informare i nuovi utenti del premio subito dopo aver aperto il gioco o durante la configurazione iniziale dell'utente. Tuttavia, è accettabile attendere che la sequenza principale di gioco sia disponibile per informare l'utente.

Tieni sempre presente l'utente quando decidi quando e come informare gli utenti degli acquisti effettuati al di fuori della tua app. Se un utente non riceve immediatamente una notifica, potrebbe confondersi e smettere di utilizzare l'app, contattare l'assistenza per gli utenti o lamentarti sui social media. Nota: PurchasesUpdatedListener è registrato nel contesto della tua applicazione per gestire gli aggiornamenti relativi agli acquisti, inclusi gli acquisti avviati al di fuori della tua app. Ciò significa che se la procedura di richiesta non è disponibile, la tua PurchasesUpdatedListener non verrà informata. Questo è il motivo per cui la tua app dovrebbe chiamare BillingClient.queryPurchasesAsync() nel metodo onResume(), come menzionato in Recupera acquisti.

Gestione delle transazioni in sospeso

Google Play supporta le transazioni in sospeso o quelle che richiedono uno o più passaggi aggiuntivi tra il momento in cui un utente avvia un acquisto e il momento in cui viene elaborato il metodo di pagamento per l'acquisto. La tua app non dovrebbe concedere diritti a questi tipi di acquisti finché Google non ti comunicherà che l'addebito è stato effettuato sul metodo di pagamento dell'utente.

Ad esempio, un utente può creare un acquisto PENDING di un articolo in-app scegliendo la forma di pagamento in contanti. L'utente può quindi scegliere un negozio fisico in cui completare la transazione e ricevere un codice sia tramite notifica che via email. Quando l'utente arriva al negozio fisico, può riscattare il codice con il cassiere e pagare in contanti. Google informa te e l'utente dell'avvenuta ricezione del denaro. L'app potrà quindi concedere il diritto all'utente.

La tua app deve supportare le transazioni in sospeso chiamando enablePendingPurchases() durante l'inizializzazione dell'app.

Quando la tua app riceve un nuovo acquisto, tramite PurchasesUpdatedListener o in seguito a una chiamata a queryPurchasesAsync(), utilizza il metodo getPurchaseState() per determinare se lo stato di acquisto è PURCHASED o PENDING.

Se la tua app è in esecuzione quando l'utente completa l'acquisto, il tuo PurchasesUpdatedListener viene richiamato e il valore PurchaseState ora è PURCHASED. A questo punto, l'app può elaborare l'acquisto utilizzando il metodo standard per gli acquisti una tantum. La tua app deve chiamare queryPurchasesAsync() anche nel metodo onResume() dell'app per gestire gli acquisti che sono passati allo stato PURCHASED mentre l'app non era in esecuzione.

La tua app può usare anche le Notifiche in tempo reale per lo sviluppatore con acquisti in attesa ascoltando OneTimeProductNotifications. Quando l'acquisto passa da PENDING a PURCHASED, la tua app riceve una notifica ONE_TIME_PRODUCT_PURCHASED. Se l'acquisto viene annullato, la tua app riceve una notifica ONE_TIME_PRODUCT_CANCELED. Ciò può accadere se il cliente non completa il pagamento nel periodo di tempo richiesto. Quando ricevi queste notifiche, puoi usare l'API Google Play Developer, che include uno stato PENDING per Purchases.products.

Puoi trovare la procedura dettagliata su come testare questo scenario nella pagina Testare gli acquisti in attesa.

Gestione degli acquisti di più quantità

Supportata nelle versioni 4.0 e successive di Libreria Fatturazione Google Play, Google Play consente ai clienti di acquistare più di uno stesso prodotto in-app in un'unica transazione specificando una quantità dal carrello degli acquisti. La tua app dovrebbe gestire gli acquisti di più quantità e concedere il diritto in base alla quantità di acquisto specificata.

Per rispettare gli acquisti di più quantità, la logica di provisioning dell'app deve controllare una quantità di articoli. Puoi accedere a un campo quantity da una delle seguenti API:

Dopo avere aggiunto una logica per gestire gli acquisti di più quantità, devi attivare la funzionalità per più quantità per il prodotto corrispondente nella pagina di gestione del prodotto in-app in Google Play Console.

Esegui una query sulla configurazione di fatturazione dell'utente

getBillingConfigAsync() indica il paese utilizzato dall'utente per Google Play.

Puoi eseguire query sulla configurazione di fatturazione dell'utente dopo aver creato un BillingClient. Lo snippet di codice riportato di seguito descrive come effettuare una chiamata a getBillingConfigAsync(). Per gestire la risposta, implementa BillingConfigResponseListener. Questo listener riceve aggiornamenti per tutte le query di configurazione di fatturazione avviate dalla tua app.

Se l'elemento BillingResult restituito non contiene errori, puoi controllare il campo countryCode nell'oggetto BillingConfig per ottenere il paese in Google Play dell'utente.

Kotlin

// Use the default GetBillingConfigParams.
val getBillingConfigParams = GetBillingConfigParams.newBuilder().build()
billingClient.getBillingConfigAsync(getBillingConfigParams,
    object : BillingConfigResponseListener {
        override fun onBillingConfigResponse(
            billingResult: BillingResult,
            billingConfig: BillingConfig?
        ) {
            if (billingResult.responseCode == BillingResponseCode.OK
                && billingConfig != null) {
                val countryCode = billingConfig.countryCode
                ...
            } else {
                // TODO: Handle errors
            }
        }
    })

Java

// Use the default GetBillingConfigParams.
GetBillingConfigParams getBillingConfigParams = GetBillingConfigParams.newBuilder().build();
billingClient.getBillingConfigAsync(getBillingConfigParams,
    new BillingConfigResponseListener() {
      public void onBillingConfigResponse(
          BillingResult billingResult, BillingConfig billingConfig) {
        if (billingResult.getResponseCode() == BillingResponseCode.OK
            && billingConfig != null) {
            String countryCode = billingConfig.getCountryCode();
            ...
         } else {
            // TODO: Handle errors
        }
      }
    });