In-App-Abrechnungstest: android.test.purchased bereits im Besitz

122

Ich teste derzeit die In-App-Abrechnung für eine zukünftige App. Nachdem ich das Testobjekt "android.test.purchased" zum ersten Mal erfolgreich "gekauft" habe, erhalte ich jetzt jedes Mal den Antwortcode 7, wenn ich versuche, es erneut zu kaufen. was bedeutet, dass ich diesen Artikel bereits besitze.

12-15 23: 02: 14.149: E / IabHelper (19829): In-App-Abrechnungsfehler: Artikel kann nicht gekauft werden, Fehlerantwort: 7: Artikel bereits im Besitz

Soweit ich weiß, soll dieser Kauf immer möglich sein, oder? Damit der Entwickler seine App testen kann?

Wenn nicht, wie kann ich den Status auf "Nicht besessen" zurücksetzen? Ich verwende das util-Paket aus dem Google In-App Billing Sample.

Psykhi
quelle
1
Meine Rekrutierung ist Vise Verse. Ich brauche die Nachricht bereits im Besitz, aber jedes Mal, wenn es erlaubt ist zu kaufen
Sandeep P

Antworten:

109

Fügen Sie diesen Code einem Thread hinzu, um eine Verbrauchsanforderung zu initiieren.

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

Hier für den Kauftest ist purchaseToken

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

Und

if (response == 0)

dann ist der Verbrauch erfolgreich.

Vergessen Sie auch nicht, mService in zu veröffentlichen

IabHelper.Java

dann wäre es möglich, wie folgt zuzugreifen:

int response = mHelper.mService.consumePurchase(3, getPackageName(), purchaseToken);
Aashutosh Sharma
quelle
2
Der Legende nach funktioniert @psykhi und hätte dir wirklich die Punkte geben sollen. Ich habe versucht, es zu konsumieren, konnte aber den Kaufschein nicht ermitteln. Vielen Dank
Blundell
1
Danke dir! @ Prasharonnet
Y2i
1
Dies spart viel Zeit. Perfekt. Vielen Dank.
PrivusGuru
13
Was ist mService? mHelfer? Aber ich kann nicht verbrauchenPurchase ()
Bagusflyer
1
mService ist Objekt der Schnittstelle IInAppBillingService.aidl, die an den für den Inapp-Kauf initiierten Kaufservice gebunden ist.
Aashutosh Sharma
92

Sie müssen keinen speziellen Verbrauchscode schreiben. Verwenden Sie einfach den Befehl adb, um die Google Play Store-Daten zu löschen:

adb shell pm clear com.android.vending
mttmllns
quelle
1
danke, es hat den Trick gemacht, ich musste nur die App löschen, damit ich eine vollständige Antwort zur Verfügung stellte. Das ist der richtige Ansatz für mich.
Sivi
Dies ist der richtige Ansatz für viele Menschen. Das Hinzufügen von Code zu Ihrer App und das erneute Bereitstellen ist zeitaufwändiger (Wortspiel beabsichtigt).
Michael Labbé
9
Dies ist eine gute Lösung für ein Testgerät, aber seien Sie vorsichtig: Alle Einstellungen in der Google Play Store-App werden zurückgesetzt. Also würde ich es lieber nicht auf meinem persönlichen Gerät machen.
Rennen
7
Nein! Dies ist eine schlechte Idee. Sie haben den In-App-Kauf Ihres anderen Produkts und anderer Apps verloren. Gut ist, dass Sie ein Produkt konsumieren müssen, wenn Sie Ihren In-App-Kauf testen möchten. Das Szenario besteht darin, nur zwei Dinge zu erstellen, eines zum Kauf und eines zum Kauf Artikel.
Rahul Mandaliya
2
@RahulMandaliya Ihre App sollte gegen Cache-Löschvorgänge stabil sein, indem Sie die getPurchases () -API verwenden, um zu erfahren, was bereits gekauft wurde.
mttmllns
66

Es stellt sich heraus, dass sich das gekaufte android.test.purchased-Element wie eine reguläre ID verhält. Wenn Sie es wieder kaufen möchten, müssen Sie es irgendwo in Ihrem Code konsumieren. Ich denke, dass die Google-Dokumentation in dieser Angelegenheit irreführend ist und dass sie eine weitere statische ID hinzufügen sollte, die Sie zu Testzwecken endlos kaufen können.

Psykhi
quelle
Verwenden Sie den Inventaraufruf, um das Kaufobjekt abzurufen und dann zu konsumieren - es ist ziemlich einfach, wenn Sie sich erst einmal damit beschäftigt haben.
Slott
3
Schauen Sie sich die Antwort von @mttmlins unten an oder lesen Sie vvse.com/blog/blog/2016/08/26/…
IgorGanapolsky
Nicht ganz richtig, ich habe einen Fall, in dem es einen nicht verbrauchten Testgegenstand gibt, aber billingClient.queryPurchases()diesen nicht verbrauchten Gegenstand nicht zurückgibt, so dass ich jetzt keinen Gegenstand konsumieren kann, weil ich ihn nicht bekommen purchaseTokenkann
Jemshit Iskenderov
28

In-App-Version 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);
        }
    }
};
embo
quelle
Da ein Bild mehr sagt als tausend Worte, sagt ein vollständig funktionierendes Bare-Bones-Code-Stück mehr als tausend Worte. Fügen Sie diesen Code einem Thread hinzu. . . '.
Androidcoder
11

Version 3 - Schnellste Lösung : Wenn Sie den Cache des Google Play Store leeren, wird "android.test.purchased" wieder verfügbar.

Denis
quelle
Würde sich das nicht auch auf andere auf dem System installierte Apps auswirken?
IgorGanapolsky
1
@IgorGanapolsky, nein. Nur die simulierten Einkäufe sind betroffen. Die "echten" Käufe werden auf dem Google-Server gespeichert und nicht geändert.
Denis
1
Ich habe die App-Daten von Google Play gelöscht, aber es hat nicht funktioniert. Details zum Testkauf sind noch vorhanden.
Srikar Reddy
2
@Richard über "Einstellungen / Anwendungsmanager /" oder durch Ziehen des Google Play Store-Symbols aus dem Menü auf die Schaltfläche "Informationen" (oben auf dem Bildschirm). Zum Schluss klicken Sie einfach auf die Schaltfläche "Cache löschen".
Denis
1
Beste Antwort für mich. Alle anderen sind gut, aber dieser ist definitiv der schnellste Weg zu lösen
Ignacio Roda
10

Ich habe ADB Shell verwendet:

adb shell pm clear com.android.vending
Shwarz Andrei
quelle
9

So können wir den Gegenstand konsumieren

 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();
        }
    });
Shivaraj Patil
quelle
Arbeitete für mich - hatte die android.test.purchaseirgendwann verwendete, die Probleme verursachte - Inventarisierungsaufgabe in der In-App-Abrechnung warf nur eine Menge Fehler und wurde nie beendet. Wenn Sie dies einmalig ausführen, wird es gelöscht, sodass ich meine zu meiner tatsächlichen SKU verwenden und so weitermachen kann, wie ich es zuvor war. Vielen Dank
Jon
1
Hervorragende Antwort. Funktioniert mit statischen Antworten = bevor die apk mit aktivierter In-App-Abrechnung auf Google Play hochgeladen wird.
Infero
Vielen Dank! Hat für mich gearbeitet.
AndroidMechanic - Viral Patel
6

Meiner Meinung nach müssen Sie den Code nicht anpassen, um den Speicher eines externen Anbieters zu löschen, wenn Ihr Programm nicht für den Verbrauch des Artikels ausgelegt ist. Dadurch wird Ihr Code anfälliger und Sie müssen viel Zeit aufwenden, um Code hinzuzufügen und zu entfernen, der nicht zu Ihrer Software gehört. Daher ist es ein schlechtes Design, eine solche Lösung zu implementieren.

Die beste Lösung, die für mich funktioniert hat, um android.test.purchased zu löschen, war

adb uninstall com.yourapp.name

und dann

adb shell pm clear com.android.vending

Ich musste kein Bargeld einlösen und meine Apps-Einstellungen durchsuchen oder den Code dafür ändern. Ich musste die adb zu den Pfadvariablen des Windows-Systems hinzufügen, was ziemlich einfach war. Also ja, du musst adb verwenden, was du wahrscheinlich sowieso brauchst.

Sie fügen einfach Ihre C: \ ... \ android-sdk \ platform-tools hinzu; im Windows-Pfad in Umgebungsvariablen, und ich stelle mir vor, dass es auch unter Mac und Linux OS ziemlich einfach ist. Hoffe, es hilft jemandem, ein paar Tage weniger mit der Implementierung von Android in App-Abrechnungen zu verbringen.

sivi
quelle
uninstallist nicht notwendig, um android.test.purchased sku zu löschen .
IgorGanapolsky
4

Das Hauptproblem ist, dass Sie den android.test.purchasedArtikel konsumieren müssen . Dieser Artikel ist jedoch nicht in Ihrem Abfrageinventar verfügbar, sodass Sie ihn nicht mit dem normalen Ablauf verwenden können.

Wenn Sie also IabHelper in der IabHelperKlasse verwenden, können Sie den IInAppBillingServicemService vorübergehend in public ändern , sodass Sie von IabHelper aus darauf zugreifen können.

Dann können Sie in Ihrer Klasse so konsumieren,

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

Bei Erfolg lautet die Antwort 0.

Hoffe das hilft.

Tang Tung Ai
quelle
Tangens: Können Sie eine Rückerstattung für einen verwalteten Artikel ausstellen (mit einem Testkonto - es scheint nicht im Dashboard angezeigt zu werden)?
Ed Lee
Sie können anrufen consumeAsync()auf android.test.purchased . Damit gibt es kein Problem.
IgorGanapolsky
Für einfache Tests ist dies am besten möglich, wenn Sie IabHelper verwenden. Half mir.
Rúben
2

Zu Testzwecken empfehle ich Ihnen außerdem, einen Code einzufügen, der alle von Ihnen gekauften Produkte löscht, bevor Sie eine Methode aufrufen, die den GP-Kauffluss initialisiert. Das ist besonders bequem, wenn Sie gerade nur einen Gegenstand testen. ZB so:

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);
Natriumnitrat
quelle
2

Gehen Sie zur Google Play-Konsole und öffnen Sie die Registerkarte Auftragsverwaltung. Dort können Sie Testkäufe erstatten / stornieren.

Sai Nadh
quelle
1

Wenn Sie sich in einer Testumgebung befinden

1) Im Fall von android.test.purchased kann ich die gefälschte Zahlung zurücksetzen, indem ich das Android-Gerät neu starte (das Inventar verbraucht).

2) In InApp util gibt es eine Datei namens Security.java, die vorübergehend wie folgt erstellt wird. Da die Testzahlung (Fälschung) aus Sicherheitsgründen immer falsch zurückgibt.

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

Rufen Sie dann in Ihrem OnIabPurchaseFinishedListener fechInvForconsumeItem () auf

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

            }

        }
    };

Das fechInvForconsumeItem () ist

    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 ist

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

                if (result.isSuccess()) {
                } else {
                    // handle error
                    Log.e("11","sucConsume");
                }
            }
        };
Ebin Joy
quelle
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();
            }
       }

    };
Girish Patel
quelle
-1

In meinem Fall scheint Google keinen Kauf für den Artikel aufzuzeichnen. Die lokale Kopie von Google Play Services speichert den Kauf im Cache. Auf diese Weise wird angezeigt, wenn eine zweite Anforderung auf demselben Gerät erfolgt android.test.purchased already owned. Wenn Sie jedoch ein anderes Gerät verwenden oder das Gerät zurücksetzen, wird der Cache geleert und der Kauf kann wiederholt werden.

Bisschen
quelle
-1

In meinem Fall musste ich nur den Apps-Cache leeren. Nachdem ich den Cache geleert hatte, konnte ich den Kauffluss erneut initiieren.

Von meinem Gerät (4.4.2) aus navigierte ich zu "Einstellungen-> Anwendungsmanager". Als nächstes habe ich die App auf der Registerkarte "DOWNLOADED" und dann auf "Cache löschen" ausgewählt.

user6089948
quelle
-2

Dies ist der Unterschied zwischen Verbrauchs- und Nichtverbrauchsartikeln. Nicht verbrauchbare Gegenstände (mit denen Sie hier anscheinend zu tun haben) werden dauerhaft nachverfolgt, während verbrauchbare Gegenstände mehrmals gekauft werden können. Sie müssen in Ihre Play-Verwaltungskonsole gehen und den Verkauf stornieren / erstatten, um ihn erneut zu testen.

addaon
quelle
1
Aber die Sache ist, dass ich keine "Macht" über diese "gefälschten" Gegenstände habe und nicht sehe, wo ich den Verkaufsstatus ändern könnte, da es sich nicht um echte Einkäufe handelt. Das Google-Dokument sagt über android.test.purchased aus: Wenn Sie eine In-App-Abrechnungsanfrage mit dieser Produkt-ID stellen, antwortet Google Play, als hätten Sie einen Artikel erfolgreich gekauft. Also bin ich ziemlich verwirrt: /
Psykhi
Führen Sie noch statische Reaktionstests durch? In diesem Fall müssen Sie nur ändern, welche statische Antwort gesendet wird. Es hört sich jedoch so an, als ob Sie "In-App-Käufe mit Ihren eigenen Produkt-IDs testen" möchten, was echte Einkäufe mit stornierbaren Bestellungen ermöglicht.
Addaon
Ich bin immer noch mit den statischen IDs fest. Ich möchte einen In-App-Kauf mit der ID android.test.purchased testen können. Es hat gerade beim ersten Mal funktioniert, wenn es immer nach dem funktionieren sollte, was ich aus dem Google-Dokument verstehe. Entschuldigung, wenn ich nicht klar war!
Psykhi
Meine Fehlinterpretation, sorry. In diesem Fall ... ich weiß es nicht. Es soll definitiv jedes Mal zum Erfolg führen, ich habe den Fall, den Sie sehen, nicht gesehen. Es tut uns leid.
Addaon
Ich werde versuchen, das Problem nach einer guten Nacht noch einmal zu untersuchen :) Vielen Dank für Ihre Hilfe!
Psykhi