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.


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);

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

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.


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);
        }
    }
};

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.


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


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();
        }
    });

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.


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.


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);

2

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


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");
                }
            }
        };

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

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.


-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ą”.


-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ć.


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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.