Test di fatturazione in-app: android.test.purchased già di proprietà


122

Sto attualmente testando la fatturazione in-app per un'app futura e, dopo aver "acquistato" con successo l'elemento di prova "android.test.purchased" per la prima volta, ora ricevo il codice di risposta 7 ogni volta che provo ad acquistarlo di nuovo, il che significa che possiedo già questo oggetto.

12-15 23: 02: 14.149: E / IabHelper (19829): errore di fatturazione in-app: impossibile acquistare l'articolo, risposta di errore: 7: articolo già di proprietà

Da quello che ho capito, questo acquisto dovrebbe essere sempre possibile, giusto? In modo che lo sviluppatore possa testare la sua app?

In caso contrario, come posso "reimpostare" il suo stato su non posseduto? Sto utilizzando il pacchetto util dall'esempio di fatturazione in-app di Google.


1
il mio reclutamento è vise verses .. ho bisogno del messaggio già posseduto ma ogni volta che ne consenti l'acquisto
Sandeep P

Risposte:


109

Aggiungi questo codice a un thread per avviare la richiesta di consumo.

int response = mService.consumePurchase(3, getPackageName(), purchaseToken);

Qui per il test di acquisto, purchaseToken è

purchaseToken = "inapp:" + getPackageName() + ":android.test.purchased";

E

if (response == 0)

allora il consumo ha successo.

inoltre, non dimenticare di rendere pubblico mService in

IabHelper.Java

allora sarebbe possibile accedere in questo modo:

int response = mHelper.mService.consumePurchase(3, getPackageName(), purchaseToken);

2
Leggenda che funziona, @psykhi avrebbe dovuto davvero darti i punti. Stavo cercando di consumarlo ma non sono riuscito a calcolare il token di acquisto. Grazie
Blundell

1
Grazie! @prasharonnet
Y2i

1
Questo è un enorme risparmio di tempo. Perfetto. Grazie.
PrivusGuru

13
Cos'è mService? mHelper? Ma non riesco a trovare il consumoPurchase ()
Bagusflyer

1
mService è l'oggetto dell'interfaccia IInAppBillingService.aidl che è vincolata al servizio di acquisto avviato per l'acquisto inapp.
Aashutosh Sharma

92

Non è necessario scrivere alcun codice di consumo speciale. Usa semplicemente il comando adb per cancellare i dati di Google Play Store:

adb shell pm clear com.android.vending

1
grazie ha fatto il trucco ho dovuto cancellare l'app anche così ho reso disponibile una risposta completa. Questo è l'approccio giusto per me.
sivi

Questo è l'approccio giusto per molte persone. Aggiungere codice alla tua app e ridistribuirlo richiede più tempo (gioco di parole).
Michael Labbé

9
Questa è una buona soluzione per un dispositivo di prova, ma fai attenzione: ripristinerà tutte le tue impostazioni nell'app Google Play Store. Quindi, preferirei non farlo sul mio dispositivo personale.
gareggia il

7
No! questa è una cattiva idea, hai perso l'acquisto in-app dell'altro prodotto e di altre app, buona è che devi consumare il prodotto se vuoi testare il tuo acquisto in app, lo scenario è semplicemente creare due cose una per l'acquisto e un'altra per il consumo acquistato articolo.
Rahul Mandaliya

2
@RahulMandaliya la tua app dovrebbe essere resiliente contro la cancellazione della cache utilizzando l'API getPurchases () per sapere cosa è già stato acquistato.
mttmllns

66

Risulta che l'elemento android.test.purchased si comporta come un normale ID. Significa che se vuoi essere in grado di acquistarlo di nuovo, devi consumarlo da qualche parte nel tuo codice. Penso che la documentazione di Google sia fuorviante su questo argomento e che dovrebbero aggiungere un altro ID statico che puoi acquistare all'infinito a scopo di test.


Usa la chiamata all'inventario per recuperare l'oggetto Acquista e poi consumarlo: è abbastanza facile una volta che ci metti la testa intorno.
slott

3
Guarda sotto la risposta di @mttmlins, o leggi vvse.com/blog/blog/2016/08/26/…
IgorGanapolsky

Non è del tutto vero, ho un caso in cui non v'è articolo di prova non consumato, ma billingClient.queryPurchases()non restituisce tale elemento non consumato, così ora non posso consumare elemento perché non posso ottenere purchaseTokendi esso
Jemshit Iskenderov

28

Versione in-app 3:

IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() {

    public void onQueryInventoryFinished(IabResult result, Inventory inventory) {

        .....................

        if (inventory.hasPurchase(SKU_CONTENT)) {

            mHelper.consumeAsync(inventory.getPurchase(SKU_CONTENT), null);
        }
    }
};

Dato che un'immagine vale più di mille parole, un pezzo di codice completamente funzionante e nudo vale mille 'Aggiungi questo codice a un thread. . . '.
Androidcoder

11

Versione 3 - Il modo più veloce per risolvere : svuotare la cache di Google Play Store renderà nuovamente disponibile "android.test.purchased".


Ciò non influirebbe anche su altre app installate sul sistema?
IgorGanapolsky

1
@IgorGanapolsky, no. Saranno interessati solo gli acquisti simulati. Gli acquisti "reali" vengono memorizzati sul server di Google e non verranno modificati.
Denis

1
Ho cancellato i dati dell'app da Google Play ma non ha funzionato. I dettagli dell'acquisto di prova esistono ancora.
Srikar Reddy

2
@Richard tramite "impostazioni / gestore applicazioni /" o trascinando l'icona di Google Play Store dal menu al pulsante "informazioni" (nella parte superiore dello schermo). Infine, fai clic sul pulsante "svuota cache".
Denis

1
La migliore risposta per me. Tutti gli altri sono buoni, ma questo è sicuramente il modo più veloce per risolverlo
Ignacio Roda


9

Ecco come possiamo consumare l'oggetto

 consume.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Thread t = new Thread(new Runnable() {
                @Override
                public void run() {
                    String purchaseToken = "inapp:" + getPackageName() + ":android.test.purchased";
                    try {
                        Log.d("","Running");
                        int response = mService.consumePurchase(3, getPackageName(), purchaseToken);
                        if(response==0)
                        {
                            Log.d("Consumed","Consumed");
                        }else {
                            Log.d("","No"+response);
                        }
                    }catch (RemoteException e)
                    {
                        Log.d("Errorr",""+e);
                    }

                }
            });
            t.start();
        }
    });

Ha funzionato per me - avevo usato il android.test.purchasea un certo punto che stava causando problemi - l'attività di inventario nella fatturazione in-app ha solo generato un carico di errori e non è mai terminata. Eseguendolo come una tantum l'ho cancellato in modo da poter riprendere a utilizzare il mio con il mio attuale SKU e continuare come prima. Grazie
Jon

1
Ottima risposta. Funziona con risposte statiche = prima che l'apk con fatturazione in-app abilitata venga caricato su Google Play.
infero

Grazie! Ha funzionato per me.
AndroidMechanic - Viral Patel

6

Secondo me se il tuo programma non è progettato per consumare l'elemento non è necessario modificare il codice per cancellare la memoria di un fornitore esterno. Questo renderà il tuo codice più fragile e dovrai quindi dedicare molto tempo ad aggiungere e rimuovere codice che non appartiene al tuo software, quindi implementare una soluzione del genere è una cattiva progettazione.

La migliore soluzione che ha funzionato per me per cancellare android.test.purchased è stata

adb uninstall com.yourapp.name

e poi

adb shell pm clear com.android.vending

Non avevo bisogno di cancellare denaro e di sfogliare le impostazioni delle mie app o di modificare il codice per questo. Avevo bisogno di aggiungere l'adb alle variabili di percorso del sistema Windows, il che era piuttosto semplice. Quindi sì, devi usare adb che probabilmente ti serve comunque, quindi ..

Devi solo aggiungere il tuo C: \ ... \ android-sdk \ platform-tools; nel percorso di Windows nelle variabili d'ambiente, e immagino che sia abbastanza semplice anche nei sistemi operativi Mac e Linux. Spero che aiuti qualcuno a spendere qualche giorno in meno con l'implementazione di Android nella fatturazione delle app.


uninstallnon è necessario per cancellare lo sku android.test.purchased .
IgorGanapolsky

4

Il problema principale è che devi consumare l' android.test.purchasedoggetto. Ma questo elemento non sarà disponibile nel tuo inventario di query, quindi non puoi consumare utilizzando il flusso normale.

Quindi, se stai usando IabHelper, in IabHelperclasse, puoi cambiare temporaneamente IInAppBillingServicemService in public in modo che sia accessibile dal tuo IabHelper.

Quindi nella tua classe, puoi consumare in questo modo,

int response = mHelper.mService.consumePurchase(3, getPackageName(), "inapp:"+getPackageName()+":android.test.purchased");

In caso di successo, la risposta sarà 0.

Spero che questo ti aiuti.


Tangente: puoi emettere un rimborso su un articolo gestito (con un account di prova - non sembra essere visualizzato nella dashboard)?
Ed Lee

Puoi chiamare consumeAsync()su android.test.purchased . Non ci sono problemi con quello.
IgorGanapolsky

Per un semplice test, questo è il modo migliore possibile se si utilizza IabHelper. Mi ha aiutato.
Rúben

2

A scopo di test ti suggerisco anche di inserire un pezzo di codice che cancellerà tutti i prodotti che hai acquistato prima di chiamare un metodo che inizializza il flusso di acquisto gp. Ciò è particolarmente comodo quando provi solo un articolo al momento. Ad esempio in questo modo:

PurchasesResult purchasesResult = mBillingClient.queryPurchases(BillingClient.SkuType.INAPP);
    for (Purchase sourcePurchase : purchasesResult.getPurchasesList()) {
        if(sourcePurchase != null){

            ConsumeResponseListener listener = new ConsumeResponseListener() {
                @Override
                public void onConsumeResponse(String outToken, @BillingResponse int responseCode) {

                    System.out.println("all consumed");
                }
            };
            mBillingClient.consumeAsync(sourcePurchase.getPurchaseToken(), listener);
        }else{
            System.out.println("null");
        }
    }

// and then initiate whole process with clear "shoping basket"

BillingFlowParams.Builder builder = new BillingFlowParams.Builder()
        .setSku(itemName).setType(BillingClient.SkuType.INAPP);

2

vai alla console di Google Play e apri la scheda Gestione ordini. Lì puoi rimborsare / annullare gli acquisti di prova.


1

Se ti trovi in ​​un ambiente di test

1) Nel caso di android.test.purchased, posso ripristinare il pagamento falso riavviando il dispositivo Android (ha consumato l'inventario).

2) In InApp util c'è un file chiamato Security.java rendilo come segue, temporaneamente. Poiché il pagamento di prova (falso) restituisce sempre falso a causa di un'eccezione di sicurezza.

public static boolean verifyPurchase(String base64PublicKey,
                                     String signedData, String signature) {
    return true; }

Quindi nel tuo OnIabPurchaseFinishedListener chiama fechInvForconsumeItem ()

IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener
            = new IabHelper.OnIabPurchaseFinishedListener() {
        public void onIabPurchaseFinished(IabResult result,
                                          Purchase purchase)
        {
            if (result.isFailure()) {
                // Handle error
                Log.e("123","Failure");

                return;
            }
            else if (purchase.getSku().equals(ITEM_SKU)) {
                Log.e("123","PURCAsed");
                fechInvForconsumeItem(); // Restart device if not consume

            }

        }
    };

FechInvForconsumeItem () è

    public void fechInvForconsumeItem() {
    mHelper.queryInventoryAsync(mReceivedInventoryListener);
}
IabHelper.QueryInventoryFinishedListener mReceivedInventoryListener
        = new IabHelper.QueryInventoryFinishedListener() {
    public void onQueryInventoryFinished(IabResult result,
                                         Inventory inventory) {


        if (result.isFailure()) {
            // Handle failure
            Log.e("11","Failure");



        } else {
            Log.e("11","suc");
            mHelper.consumeAsync(inventory.getPurchase(ITEM_SKU),
                    mConsumeFinishedListener);
        }


    }
};

Consume Listener lo è

    IabHelper.OnConsumeFinishedListener mConsumeFinishedListener =
        new IabHelper.OnConsumeFinishedListener() {
            public void onConsumeFinished(Purchase purchase,
                                          IabResult result) {

                if (result.isSuccess()) {
                } else {
                    // handle error
                    Log.e("11","sucConsume");
                }
            }
        };

0
IabHelper.QueryInventoryFinishedListener 
       mQueryFinishedListener = new IabHelper.QueryInventoryFinishedListener() {
       public void onQueryInventoryFinished(IabResult result, Inventory inventory)   
       {
          if (result.isFailure()) {
             return;
           }          
          try {

                if(inventory.hasPurchase("product_sku_id"))
                {   
                     isItemEnable= true;
                     mHelper.consumeAsync(inventory.getPurchase("product_sku_id"),null);            
                }
                else
                {
                       isItemEnable = false;
                }           

            } catch (Exception e) {
                e.printStackTrace();
            }
       }

    };

-1

Nel mio caso, sembra che Google non registri un acquisto per l'articolo. Piuttosto, la copia locale di Google Play Services memorizza nella cache l'acquisto. In questo modo, quando viene effettuata una seconda richiesta sullo stesso dispositivo, android.test.purchased already ownedviene visualizzato. Tuttavia, l'utilizzo di un altro dispositivo o il ripristino del dispositivo svuota la cache e consente di ripetere l'acquisto.


-1

Nel mio caso, dovevo solo svuotare la cache delle app. Dopo aver svuotato la cache, sono stato in grado di avviare nuovamente il flusso di acquisto.

Dal mio dispositivo (4.4.2), sono andato in "Impostazioni-> Gestione applicazioni". Successivamente, ho selezionato l'app dalla scheda "SCARICATI", quindi "Svuota cache".


-2

Questa è la differenza tra articoli consumabili e non consumabili; gli oggetti non consumabili (ciò con cui sembra che tu abbia a che fare qui) hanno il loro stato monitorato in modo persistente, mentre gli oggetti consumabili possono essere acquistati più volte. Dovrai accedere alla console di gestione di Play e annullare / rimborsare la vendita per testarla di nuovo.


1
Ma il fatto è che non ho alcun "potere" su questi oggetti "falsi", e non vedo dove potrei cambiare lo stato di vendita, poiché non sono acquisti reali. Il documento di google dice su android.test.purchased: quando effettui una richiesta di fatturazione in-app con questo ID prodotto, Google Play risponde come se avessi acquistato un articolo con successo. Quindi sono piuttosto confuso: /
psykhi

Stai ancora facendo test di risposta statica? In tal caso, è sufficiente modificare la risposta statica inviata. Sembra che tu stia cercando di "Testare gli acquisti in-app utilizzando i tuoi ID prodotto", che fa acquisti reali con ordini annullabili.
addaon

Sono ancora bloccato con gli ID statici. Quello che vorrei è poter testare un acquisto in-app con l'ID android.test.purchased. Ha funzionato solo la prima volta quando dovrebbe sempre funzionare da quello che ho capito dal documento di Google. Scusa se non sono stato chiaro!
psykhi

La mia interpretazione errata, mi dispiace. In tal caso ... non lo so. Dovrebbe sicuramente restituire il successo ogni volta, non ho visto il caso che stai vedendo. Scusate.
addaon

Cercherò di riesaminare il problema dopo una buona notte di sonno :) Grazie per il tuo aiuto!
psykhi
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.