Teste de faturamento no aplicativo: android.test.purchased já possui

122

No momento, estou testando o faturamento no aplicativo para um aplicativo futuro e, depois de comprar com sucesso o item de teste "android.test.purchased" na primeira vez, agora recebo o código de resposta 7 toda vez que tento comprá-lo novamente, o que significa que eu já possuo este item.

12-15 23: 02: 14.149: E / IabHelper (19829): Erro de cobrança no aplicativo: não é possível comprar o item, Resposta de erro: 7: item já possui

Pelo que entendi, essa compra deve sempre ser possível, certo? Para que o desenvolvedor possa testar seu aplicativo?

Caso contrário, como posso "redefinir" seu estado para não possuído? Estou usando o pacote util do exemplo de cobrança no aplicativo do Google.

psykhi
fonte
1
meu recrutamento é vise versos .i precisa a mensagem já possuía, mas cada vez que a sua permitindo a comprar
Sandeep P

Respostas:

109

Adicione esse código a um encadeamento para iniciar a solicitação de consumo.

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

Aqui para o teste de compra, PurchaseToken é

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

E

if (response == 0)

então o consumo é bem sucedido.

Também não se esqueça de tornar público o mService em

IabHelper.Java

seria possível acessar assim:

int response = mHelper.mService.consumePurchase(3, getPackageName(), purchaseToken);
Aashutosh Sharma
fonte
2
Como funciona a lenda, o @psykhi deveria ter lhe dado os pontos. Eu estava tentando consumi-lo, mas não consegui descobrir o token de compra. Obrigado
Blundell
1
Obrigado! @prasharonnet
Y2i
1
Isso economiza muito tempo. Perfeito. Obrigado.
PrivusGuru
13
O que é mService? mHelper? Mas eu não posso encontrar o consumePurchase ()
Bagusflyer
1
mService é objeto da interface IInAppBillingService.aidl, que é vinculada ao serviço de compra iniciado para a compra inapp.
Aashutosh Sharma
92

Não há necessidade de escrever nenhum código de consumo especial. Basta usar o comando adb para limpar os dados da Google Play Store:

adb shell pm clear com.android.vending
mttmllns
fonte
1
obrigado, ele fez o truque, eu só tinha que limpar o aplicativo também, então disponibilizei uma resposta completa. Esta é a abordagem certa para mim.
Sivi 01/07
Essa é a abordagem correta para muitas pessoas. Adicionar código ao seu aplicativo e reimplementar consome mais tempo (trocadilhos).
Michael Labbé
9
Esta é uma boa solução para um dispositivo de teste, mas tenha cuidado: ele redefinirá todas as suas configurações no aplicativo Google Play Store. Portanto, prefiro não fazê-lo no meu dispositivo pessoal.
CCR
7
Não! isso é uma péssima idéia, você perdeu a compra no aplicativo de outro produto e de outros aplicativos; o melhor é que você precisa consumir o produto se quiser testar sua compra de aplicativo; o cenário é apenas criar duas coisas, uma para compra e outra para o consumo adquirido item.
Rahul Mandaliya
2
@RahulMandaliya, seu aplicativo deve ser resiliente contra a limpeza de cache usando a API getPurchases () para saber o que já foi comprado.
mttmllns
66

Acontece que o item android.test.purchased se comporta como um ID regular. Isso significa que, se você quiser comprá-lo novamente, precisará consumi-lo em algum lugar do seu código. Acho que a documentação do Google é enganosa sobre esse assunto e que eles devem adicionar outro ID estático que você pode comprar sem parar para fins de teste.

psykhi
fonte
Use a chamada de inventário para buscar o objeto Purchase e depois consumi-lo - é bem fácil assim que você o entender.
Slott
3
Veja abaixo a resposta de @mttmlins ou leia vvse.com/blog/blog/2016/08/26/…
IgorGanapolsky
Não totalmente verdade, eu tenho um caso onde há item de teste não consumida, mas billingClient.queryPurchases()não retorna esse item não consumida, então agora eu não posso consumir item porque eu não posso conseguir purchaseTokenisso
Jemshit Iskenderov
28

Versão 3 no aplicativo:

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
fonte
Como uma imagem vale mais que mil palavras, um código completo de ossos esquecidos vale mais que mil 'Adicione esse código a um tópico. . . '
Androidcoder
11

Versão 3 - Maneira mais rápida de resolver : limpar o cache da Google Play Store deixará "android.test.purchased" disponível novamente.

Denis
fonte
Isso não afetaria outros aplicativos instalados no sistema também?
IgorGanapolsky
1
@IgorGanapolsky, não. Somente as compras simuladas serão afetadas. As compras "reais" são armazenadas no servidor do Google e não serão modificadas.
Denis
1
Limpei os dados do aplicativo no Google Play, mas eles não funcionaram. Os detalhes da compra de teste ainda existem.
Srikar Reddy
2
@ Richard através de "gerenciador de configurações / aplicativos /" ou arrastando o ícone da Google Play Store do menu para o botão "informações" (na parte superior da tela). Por fim, basta clicar no botão "limpar cache".
Denis
1
Melhor resposta para mim. Todos os outros são bons, mas este é definitivamente o caminho mais rápido para resolver #
Ignacio Roda
10

eu usei adb shell:

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

É assim que podemos consumir o Item

 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
fonte
Trabalhou para mim - havia usado o android.test.purchaseem algum momento que estava causando problemas - a tarefa de inventário no faturamento no aplicativo apenas gerou uma carga de erros e nunca foi concluída. A execução como uma única limpeza a liberou para que eu pudesse continuar usando o meu no meu SKU real e continuar como estava antes. Obrigado
Jon
1
Excelente resposta. Funciona com respostas estáticas = antes do upload do apk com o faturamento no aplicativo ativado para o Google Play.
infero 23/02
Obrigado! Trabalhou para mim.
AndroidMechanic - Viral Patel
6

Na minha opinião, se o seu programa não foi projetado para consumir o item, você não precisa ajustar o código para limpar a memória de um fornecedor externo. Isso tornará seu código mais frágil e você precisará gastar muito tempo para adicionar e remover o código que não pertence ao seu software, por isso é um mau design implementar uma solução como essa.

A melhor solução que funcionou para eu limpar o android.test.purchased foi

adb uninstall com.yourapp.name

e depois

adb shell pm clear com.android.vending

Não precisei liberar dinheiro e navegar nas configurações de meus aplicativos ou alterar o código para isso. Eu precisava adicionar o adb às variáveis ​​de caminho do sistema Windows, o que foi bastante direto. Então, sim, você precisa usar o adb, o que você provavelmente precisa, de qualquer maneira.

Você acabou de adicionar seu C: \ ... \ android-sdk \ platform-tools; no caminho do windows em variáveis ​​de ambiente, e imagino que seja bem simples também nos sistemas operacionais mac e linux. Espero que ajude alguém a passar alguns dias a menos com a implementação do android no faturamento de aplicativos.

sivi
fonte
uninstallnão é necessário limpar o sku android.test.purchased .
IgorGanapolsky
4

O principal problema é que você precisa consumir o android.test.purchaseditem. Mas esse item não estará disponível no seu inventário de consultas, portanto você não pode consumir usando o fluxo normal.

Portanto, se você estiver usando o IabHelper, em IabHelpersala de aula, poderá alterar temporariamente o IInAppBillingServicemService para público, para que seja acessível a partir do seu IabHelper.

Então, na sua turma, você pode consumir assim,

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

Se for bem-sucedida, a resposta será 0.

Espero que isto ajude.

Tang Tung Ai
fonte
Tangente: você pode emitir um reembolso para um item gerenciado (com uma conta de teste - isso não aparece no painel)?
Ed Lee
Você pode ligar consumeAsync()para android.test.purchased . Não há problema com isso.
IgorGanapolsky
Para um teste simples, é a melhor maneira possível se estiver usando o IabHelper. Me ajudou.
Rúben
2

Para fins de teste, também sugiro que você insira um pedaço de código que limpará todos os produtos que você comprou antes de chamar um método que inicialize o fluxo de compra da gp. Isso é especialmente confortável quando você testa apenas um item no momento. Por exemplo:

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);
sódio-nitrato
fonte
2

acesse o console do Google Play e abra a guia Gerenciamento de pedidos. Lá você pode reembolsar / cancelar compras de teste.

Sai Nadh
fonte
1

Se você estiver no ambiente de teste

1) No caso de android.test.purchased, posso redefinir o pagamento falso reiniciando o dispositivo Android (consumido o inventário).

2) No InApp util, existe um arquivo chamado Security.java, que é o seguinte, temporariamente. Como o pagamento do teste (falso) sempre retorna falso devido a uma exceção de segurança.

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

Em seguida, na sua chamada OnIabPurchaseFinishedListener, 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

            }

        }
    };

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


    }
};

Consumir ouvinte é

    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
fonte
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
fonte
-1

No meu caso, parece que o Google não registra uma compra para o item. Em vez disso, a cópia local do Google Play Services armazena em cache a compra. Dessa forma, quando uma segunda solicitação é feita no mesmo dispositivo, android.test.purchased already ownedaparece. No entanto, usar outro dispositivo ou redefinir o dispositivo limpa o cache e permite que a compra seja repetida.

Tad
fonte
-1

No meu caso, eu só precisava limpar o cache dos aplicativos. Depois de limpar o cache, consegui iniciar o fluxo de compras novamente.

No meu dispositivo (4.4.2), naveguei para "Configurações-> Gerenciador de aplicativos". Em seguida, selecionei o aplicativo na guia "DOWNLOAD" e depois em "Limpar cache".

user6089948
fonte
-2

Essa é a diferença entre itens consumíveis e não consumíveis; itens não consumíveis (com o que você parece estar lidando aqui) têm seu estado rastreado persistentemente, enquanto itens consumíveis podem ser comprados várias vezes. Você precisará acessar o console de gerenciamento do Play e cancelar / reembolsar a venda para testá-lo novamente.

addaon
fonte
1
Mas o problema é que eu não tenho nenhum poder sobre esses itens "falsos" e não vejo onde eu poderia mudar o status da venda, pois eles não são compras reais. O documento do google diz sobre o android.test.purchased: quando você faz uma solicitação de cobrança no aplicativo com este ID do produto, o Google Play responde como se você tivesse comprado um item com êxito. Então, eu estou bastante confuso: /
psykhi
Você ainda está testando respostas estáticas? Nesse caso, você só precisa alterar a resposta estática enviada. Parece que você está disposto a "Testar compras no aplicativo usando seus próprios IDs de produto", que faz compras reais com pedidos canceláveis.
addaon
Ainda estou preso aos IDs estáticos. O que eu gostaria é de poder testar uma compra no aplicativo com o ID android.test.purchased. Funcionou apenas na primeira vez em que deve sempre funcionar com o que entendo no documento do Google. Desculpe se eu não estava claro!
Psykhi
Minha interpretação errada, desculpe. Nesse caso ... eu não sei. Definitivamente, é suposto retornar sucesso sempre que não vejo o caso que você está vendo. Desculpe.
addaon
Tentarei olhar novamente para o problema após uma boa noite de sono :) Obrigado pela ajuda!
Psykhi