Test rozliczeń w aplikacji: android.test.purchased już posiadany

122

Obecnie testuję rozliczanie w aplikacji dla przyszłej aplikacji i po pomyślnym „kupieniu” elementu testowego „android.test.purchased” za pierwszym razem otrzymuję teraz kod odpowiedzi 7 za każdym razem, gdy próbuję go kupić ponownie, co oznacza, że ​​mam już ten przedmiot.

12-15 23: 02: 14.149: E / IabHelper (19829): Błąd rozliczeniowy w aplikacji: nie można kupić przedmiotu, odpowiedź błędu: 7: Przedmiot jest już posiadany

Z tego co rozumiem ten zakup ma być zawsze możliwy, prawda? Aby programista mógł przetestować swoją aplikację?

Jeśli nie, jak mogę „zresetować” jego stan do stanu, w którym nie jest właścicielem? Używam pakietu narzędzi z próbki rozliczeń Google w aplikacji.

psykhi
źródło
1
moja rekrutacja to vise verses .. Potrzebuję wiadomości już posiadanej, ale za każdym razem pozwala na zakup
Sandeep P

Odpowiedzi:

109

Dodaj ten kod do wątku, aby zainicjować żądanie wykorzystania.

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

Tutaj dla testu zakupu zakupToken to

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

I

if (response == 0)

wtedy konsumpcja się powiedzie.

nie zapomnij też o publicznym udostępnieniu mService w

IabHelper.Java

wtedy byłby możliwy dostęp w ten sposób:

int response = mHelper.mService.consumePurchase(3, getPackageName(), purchaseToken);
Aashutosh Sharma
źródło
2
Legenda, że ​​to działa, @psykhi naprawdę powinno dać ci punkty. Próbowałem go skonsumować, ale nie mogłem obliczyć tokena zakupu. Dzięki
Blundell
1
Dziękuję Ci! @prasharonnet
Y2i,
1
To ogromna oszczędność czasu. Idealny. Dzięki.
PrivusGuru
13
Co to jest mService? mHelper? Ale nie mogę znaleźć consumePurchase ()
Bagusflyer
1
mService jest obiektem interfejsu IInAppBillingService.aidl, który jest powiązany z usługą zakupu zainicjowaną w celu zakupu w aplikacji.
Aashutosh Sharma
93

Nie ma potrzeby pisania żadnego specjalnego kodu zużycia. Po prostu użyj polecenia adb, aby wyczyścić dane Sklepu Google Play:

adb shell pm clear com.android.vending
mttmllns
źródło
1
dzięki, że załatwiło sprawę, po prostu musiałem wyczyścić aplikację, więc udostępniłem pełną odpowiedź. To jest dla mnie właściwe podejście.
sivi
To jest właściwe podejście dla wielu ludzi. Dodawanie kodu do aplikacji i ponowne wdrażanie jest bardziej czasochłonne (gra słów zamierzona).
Michael Labbé
9
To dobre rozwiązanie dla urządzenia testowego, ale uważaj: zresetuje wszystkie ustawienia w aplikacji Sklep Google Play. Wolałbym więc nie robić tego na moim urządzeniu osobistym.
wyścigi
7
Nie! to zły pomysł, straciłeś zakup w aplikacji innego produktu i innych aplikacji, dobry jest to, że musisz skonsumować produkt, jeśli chcesz przetestować zakup w aplikacji, scenariusz polega po prostu na utworzeniu dwóch rzeczy, jednej do zakupu, a drugiej do zakupu pozycja.
Rahul Mandaliya
2
@RahulMandaliya Twoja aplikacja powinna być odporna na czyszczenie pamięci podręcznej, korzystając z API getPurchases (), aby wiedzieć, co zostało już zakupione.
mttmllns
66

Okazuje się, że element android.test.purchased zachowuje się jak zwykły identyfikator. Oznacza to, że jeśli chcesz móc go ponownie kupić, musisz go skonsumować gdzieś w swoim kodzie. Myślę, że dokumentacja Google jest myląca w tej sprawie i że powinni dodać kolejny statyczny identyfikator, który można kupować bez końca w celach testowych.

psykhi
źródło
Użyj wywołania ekwipunku, aby pobrać przedmiot Zakupu, a następnie go skonsumować - jest to całkiem łatwe, gdy się obejrzysz.
szczelina
3
Spójrz na poniższą odpowiedź z @mttmlins lub przeczytaj vvse.com/blog/blog/2016/08/26/…
IgorGanapolsky
Nie całkiem prawda, mam sprawę, gdzie istnieje nieużyte poz test, ale billingClient.queryPurchases()nie zwraca tę niespożytą przedmiot, więc teraz nie mogę spożywać pozycję, ponieważ nie mogę dostać purchaseTokenod niego
Jemshit Iskenderov
28

Wersja 3 w aplikacji:

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
źródło
Ponieważ obraz jest wart tysiąca słów, cały działający fragment kodu gołej kości jest wart tysiąca. Dodaj ten kod do wątku. . . ”.
Androidcoder,
11

Wersja 3 - Najszybszy sposób rozwiązania : wyczyszczenie pamięci podręcznej sklepu Google Play sprawi, że „android.test.purchased” będzie ponownie dostępny.

Denis
źródło
Czy nie wpłynęłoby to również na inne aplikacje zainstalowane w systemie?
IgorGanapolsky
1
@IgorGanapolsky, nie. Wpłynie to tylko na symulowane zakupy. „Prawdziwe” zakupy są przechowywane na serwerze Google i nie będą modyfikowane.
Denis
1
Wyczyściłem dane aplikacji z Google Play, ale nie zadziałało. Szczegóły zakupu testowego nadal istnieją.
Srikar Reddy
2
@Richard poprzez „ustawienia / menadżer aplikacji /” lub przeciągając ikonę sklepu Google Play z menu do przycisku „Informacje” (u góry ekranu). Na koniec wystarczy kliknąć przycisk „Wyczyść pamięć podręczną”.
Denis,
1
Najlepsza odpowiedź dla mnie. Wszystkie inne są dobre, ale ten zdecydowanie jest najszybszym sposobem na rozwiązanie
Ignacio Roda
10

użyłem powłoki adb:

adb shell pm clear com.android.vending
Shwarz Andrei
źródło
9

W ten sposób możemy skonsumować przedmiot

 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
źródło
Zadziałało dla mnie - użyłem android.test.purchasew pewnym momencie, co powodowało problemy - zadanie inwentaryzacji w rozliczeniach w aplikacji po prostu wyrzuciło mnóstwo błędów i nigdy się nie skończyło. Uruchomienie tego jako jednorazowe rozwiązało problem, więc mogłem wznowić używanie mojego rzeczywistego kodu SKU i kontynuować tak, jak wcześniej. Dzięki
Jon
1
Doskonała odpowiedź. Działa z odpowiedziami statycznymi = zanim apk z włączonym rozliczaniem w aplikacji zostanie przesłany do Google Play.
infero
Dzięki! Pracował dla mnie.
AndroidMechanic - Viral Patel
6

Moim zdaniem, jeśli twój program nie jest przeznaczony do zużywania produktu, nie musisz modyfikować kodu, aby wyczyścić pamięć zewnętrznego dostawcy. Dzięki temu Twój kod będzie bardziej kruchy i będziesz musiał spędzić dużo czasu na dodawaniu i usuwaniu kodu, który nie należy do twojego oprogramowania, więc wdrażanie takiego rozwiązania jest złym projektem.

Najlepszym rozwiązaniem, które zadziałało, aby wyczyścić android.test.purchased, był

adb uninstall com.yourapp.name

i wtedy

adb shell pm clear com.android.vending

Nie musiałem kasować gotówki i przeglądać ustawień aplikacji ani zmieniać w tym celu kodu. Musiałem dodać adb do zmiennych ścieżki systemu Windows, co było dość proste. Więc tak, musisz użyć adb, którego prawdopodobnie i tak potrzebujesz, więc ...

Po prostu dodaj swój C: \ ... \ android-sdk \ platform-tools; w ścieżce systemu Windows w zmiennych środowiskowych i wyobrażam sobie, że jest to całkiem proste również w systemie Mac i Linux. Mam nadzieję, że pomoże to komuś spędzić kilka dni mniej na wdrażaniu Androida w rozliczeniach aplikacji.

sivi
źródło
uninstallnie trzeba czyścić sku android.test.purchased .
IgorGanapolsky
4

Głównym problemem jest to, że musisz skonsumować android.test.purchasedprzedmiot. Ale ten element nie będzie dostępny w Twoim magazynie zapytań, więc nie możesz korzystać z normalnego przepływu.

Tak więc, jeśli używasz IabHelper w IabHelperklasie, możesz tymczasowo zmienić IInAppBillingServicemService na publiczny, aby był dostępny z Twojego IabHelper.

Wtedy w klasie możesz konsumować w ten sposób,

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

Jeśli się powiedzie, odpowiedź będzie wynosić 0.

Mam nadzieję że to pomoże.

Tang Tung Ai
źródło
Tangent: czy możesz dokonać zwrotu kosztów za zarządzany przedmiot (z kontem testowym - nie wydaje się, aby wyświetlał się na pulpicie nawigacyjnym)?
Ed Lee
Możesz zadzwonić consumeAsync()pod numer android.test.purchased . Nie ma z tym problemu.
Igor Ganapolsky
W przypadku prostego testu jest to najlepszy możliwy sposób, jeśli używasz IabHelper. Pomogło mi.
Rúben
2

Do celów testowych sugeruję również wstawienie fragmentu kodu, który wyczyści wszystkie zakupione produkty przed wywołaniem metody inicjującej przepływ zakupów gp. Jest to szczególnie wygodne, gdy w danej chwili testujesz tylko jedną pozycję. Np. W ten sposób:

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);
sodu azotan
źródło
2

przejdź do konsoli Google Play i otwórz zakładkę Zarządzanie zamówieniami. Tam możesz zwrócić / anulować zakupy testowe.

Sai Nadh
źródło
1

Jeśli jesteś w środowisku testowym

1) W przypadku android.test.purchased, mogę zresetować fałszywą płatność, ponownie uruchamiając urządzenie z Androidem (zużyte zapasy).

2) W narzędziu InApp jest plik o nazwie Security.java, aby tymczasowo wyglądać następująco. Ponieważ płatność testowa (fałszywa) zawsze zwraca fałsz z powodu wyjątku bezpieczeństwa.

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

Następnie w Twoim OnIabPurchaseFinishedListener wywołaj 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

            }

        }
    };

Funkcja fechInvForconsumeItem () to

    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 to

    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
źródło
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
źródło
-1

W moim przypadku wygląda na to, że Google nie rejestruje zakupu przedmiotu. Zamiast tego lokalna kopia Usług Google Play przechowuje zakup w pamięci podręcznej. W ten sposób, gdy drugie żądanie zostanie wysłane na to samo urządzenie, android.test.purchased already ownedpojawi się. Jednak użycie innego urządzenia lub zresetowanie urządzenia powoduje wyczyszczenie pamięci podręcznej i umożliwia powtórzenie zakupu.

Berbeć
źródło
-1

W moim przypadku wystarczyło wyczyścić pamięć podręczną aplikacji. Po wyczyszczeniu pamięci podręcznej mogłem ponownie zainicjować proces zakupu.

Z mojego urządzenia (4.4.2) przeszedłem do „Ustawienia-> Menedżer aplikacji”. Następnie wybrałem aplikację z zakładki „POBRANE”, a następnie „Wyczyść pamięć podręczną”.

user6089948
źródło
-2

Na tym polega różnica między materiałami eksploatacyjnymi i nieużywalnymi; Stan przedmiotów nieużywalnych (z czym wydaje się, że masz do czynienia) jest stale śledzony, podczas gdy przedmioty jednorazowe można kupować wielokrotnie. Będziesz musiał przejść do konsoli zarządzania Play i anulować / zwrócić sprzedaż, aby ponownie ją przetestować.

dodatek
źródło
1
Ale rzecz w tym, że nie mam żadnej "mocy" na tych "fałszywych" przedmiotach i nie widzę, gdzie mógłbym zmienić status sprzedaży, ponieważ nie są to prawdziwe zakupy. Dokument Google mówi o android.test.purchased: gdy wysyłasz żądanie rozliczenia w aplikacji z tym identyfikatorem produktu, Google Play reaguje tak, jakbyś kupił przedmiot. Więc jestem dość zdezorientowany: /
psykhi
Czy nadal wykonujesz statyczne testy odpowiedzi? Jeśli tak, wystarczy zmienić wysyłaną odpowiedź statyczną. Wygląda na to, że jesteś gotowy do „testowania zakupów w aplikacji przy użyciu własnych identyfikatorów produktów”, co oznacza prawdziwe zakupy z anulowanymi zamówieniami.
dodatek
Nadal utknąłem ze statycznymi identyfikatorami. Chciałbym móc przetestować zakup w aplikacji za pomocą identyfikatora android.test.purchased. Po prostu zadziałało za pierwszym razem, kiedy powinno zawsze działać z tego, co rozumiem z dokumentu Google. Przepraszam, jeśli nie było jasne!
psykhi
Przepraszam, moja błędna interpretacja. W takim razie ... nie wiem. Zdecydowanie powinien przynosić sukces za każdym razem, nie widziałem sprawy, którą widzisz. Przepraszam.
dodatek
Spróbuję jeszcze raz przyjrzeć się problemowi po dobrze przespanej nocy :) Dzięki za pomoc!
psykhi