Test de facturation dans l'application: android.test.purchased déjà détenu


122

Je teste actuellement la facturation intégrée à une application pour une future application, et après avoir "acheté" avec succès l'élément de test "android.test.purchased" la première fois, je reçois maintenant le code de réponse 7 chaque fois que j'essaye de l'acheter à nouveau, ce qui signifie que je possède déjà cet article.

12-15 23: 02: 14.149: E / IabHelper (19829): erreur de facturation dans l'application: impossible d'acheter l'article, réponse d'erreur: 7: article déjà possédé

D'après ce que j'ai compris, cet achat est censé être toujours possible, non? Pour que le développeur puisse tester son application?

Sinon, comment puis-je "réinitialiser" son état pour ne pas être possédé? J'utilise le package util de l'exemple de facturation Google In-App.


1
mon recrutement se fait à l'inverse .. j'ai besoin du message déjà possédé mais à chaque fois il permet d'acheter
Sandeep P

Réponses:


109

Ajoutez ce code à un thread pour lancer la demande de consommation.

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

Ici pour le test d'achat, purchaseToken est

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

Et

if (response == 0)

alors la consommation est réussie.

n'oubliez pas non plus de rendre mService public dans

IabHelper.Java

alors il serait possible d'accéder comme ceci:

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

2
Légende cela fonctionne, @psykhi aurait vraiment dû vous donner les points. J'essayais de le consommer mais je n'ai pas pu trouver le jeton d'achat. Merci
Blundell

1
Je vous remercie! @prasharonnet
Y2i

1
Cela permet un immense gain de temps. Parfait. Merci.
PrivusGuru

13
Qu'est-ce que mService? mHelper? Mais je ne trouve pas le consommerPurchase ()
Bagusflyer

1
mService est l'objet de l'interface IInAppBillingService.aidl qui est liée au service d'achat lancé pour l'achat inapp.
Aashutosh Sharma

92

Pas besoin d'écrire un code de consommation spécial. Utilisez simplement la commande adb pour effacer les données du Google Play Store:

adb shell pm clear com.android.vending

1
merci, il a fait le truc, je devais simplement effacer l'application également, donc j'ai rendu une réponse complète disponible. C'est la bonne approche pour moi.
sivi

C'est la bonne approche pour beaucoup de gens. L'ajout de code à votre application et le redéploiement prennent plus de temps (jeu de mots).
Michael Labbé

9
C'est une bonne solution pour un appareil de test, mais attention: il réinitialisera tous vos paramètres dans l'application Google Play Store. Donc, je préfère ne pas le faire sur mon appareil personnel.
courses du

7
Non! c'est une mauvaise idée, vous avez perdu l'achat in-app de votre autre produit et d'autres applications, le bon est que vous devez consommer le produit si vous voulez tester votre achat intégré, le scénario consiste simplement à créer deux choses, une pour l'achat et une autre pour la consommation achetée article.
Rahul Mandaliya

2
@RahulMandaliya, votre application doit être résistante aux effacements de cache en utilisant l'API getPurchases () pour savoir ce qui a déjà été acheté.
mttmllns

66

Il s'avère que l'élément android.test.purchased se comporte comme un identifiant ordinaire. Cela signifie que si vous voulez pouvoir l'acheter à nouveau, vous devez le consommer quelque part dans votre code. Je pense que la documentation Google est trompeuse à ce sujet et qu'elle devrait ajouter un autre identifiant statique que vous pouvez acheter à l'infini à des fins de test.


Utilisez l'appel d'inventaire pour récupérer l'objet Achat, puis le consommer - c'est assez facile une fois que vous avez compris.
slott

3
Regardez la réponse ci-dessous de @mttmlins, ou lisez vvse.com/blog/blog/2016/08/26/…
IgorGanapolsky

Pas tout à fait vrai, j'ai un cas où il y a un objet de test non consommé, mais billingClient.queryPurchases()ne retourne pas cet élément non consommé, alors maintenant je ne peux pas consommer article parce que je ne peux pas obtenir purchaseTokende celui - ci
Jemshit Iskenderov

28

Version 3 intégrée à l'application:

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

Comme une image vaut mille mots, un morceau de code complet et fonctionnel vaut mille 'Ajoutez ce code à un fil de discussion. . . '.
Androidcoder

11

Version 3 - Le moyen le plus rapide de résoudre : la suppression du cache de Google Play Store rendra "android.test.purchased" disponible à nouveau.


Cela n'affecterait-il pas également les autres applications installées sur le système?
IgorGanapolsky

1
@IgorGanapolsky, non. Seuls les achats simulés seront affectés. Les "vrais" achats sont stockés sur le serveur de Google et ne seront pas modifiés.
Denis

1
J'ai effacé les données de l'application sur Google Play, mais cela n'a pas fonctionné. Les détails de l'achat test existent toujours.
Srikar Reddy

2
@Richard via "Paramètres / Gestionnaire d'applications /" ou en faisant glisser l'icône Google Play Store du menu vers le bouton "Informations" (en haut de l'écran). Enfin, cliquez simplement sur le bouton "Vider le cache".
Denis

1
Meilleure réponse pour moi. Tous les autres sont bons, mais celui-ci est certainement le moyen le plus rapide de résoudre
Ignacio Roda


9

C'est ainsi que nous pouvons consommer l'article

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

A travaillé pour moi - j'avais utilisé le android.test.purchaseà un moment donné, ce qui posait des problèmes - la tâche d'inventaire dans la facturation intégrée à l'application a juste jeté une charge d'erreurs et n'a jamais été terminée. L'exécution de cela comme une seule fois l'a effacée afin que je puisse recommencer à utiliser mon SKU réel et continuer comme avant. Merci
Jon

1
Excellente réponse. Fonctionne avec les réponses statiques = avant le téléchargement de l'apk avec la facturation intégrée à l'application sur Google Play.
infero le

Merci! A travaillé pour moi.
AndroidMechanic - Viral Patel

6

À mon avis, si votre programme n'est pas conçu pour consommer l'article, vous n'avez pas besoin de modifier le code pour effacer la mémoire d'un fournisseur extérieur. Cela rendra votre code plus fragile et vous devrez alors passer beaucoup de temps à ajouter et supprimer du code qui n'appartient pas à votre logiciel donc c'est une mauvaise conception d'implémenter une telle solution.

La meilleure solution qui a fonctionné pour moi pour effacer android.test.purchased était

adb uninstall com.yourapp.name

puis

adb shell pm clear com.android.vending

Je n'avais pas besoin de vider de l'argent et de parcourir les paramètres de mes applications ou de modifier le code pour cela. J'ai eu besoin d'ajouter l'adb aux variables de chemin du système Windows, ce qui était assez simple. Alors oui, vous devez utiliser adb dont vous aurez probablement besoin de toute façon.

Vous ajoutez simplement votre C: \ ... \ android-sdk \ platform-tools; dans le chemin Windows dans les variables d'environnement, et j'imagine que c'est assez simple également sous mac et linux os. J'espère que cela aidera quelqu'un à passer quelques jours de moins avec la mise en œuvre d'Android dans la facturation des applications.


uninstalln'est pas nécessaire pour effacer la référence android.test.purchased .
IgorGanapolsky

4

Le principal problème est que vous devez consommer l' android.test.purchasedarticle. Mais cet élément ne sera pas disponible dans votre inventaire de requêtes, vous ne pouvez donc pas consommer en utilisant le flux normal.

Donc, si vous utilisez IabHelper, en IabHelperclasse, vous pouvez temporairement changer le IInAppBillingServicemService en public afin qu'il soit accessible depuis votre IabHelper.

Alors dans ta classe, tu peux consommer comme ça,

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

En cas de succès, la réponse sera 0.

J'espère que cela t'aides.


Tangent: pouvez-vous émettre un remboursement sur un élément géré (avec un compte de test - il ne semble pas apparaître dans le tableau de bord)?
Ed Lee

Vous pouvez appeler consumeAsync()sur android.test.purchased . Il n'y a pas de problème avec ça.
IgorGanapolsky

Pour un test simple, c'est la meilleure façon possible si vous utilisez IabHelper. M'a aidé.
Rúben

2

À des fins de test, je vous suggère également d'insérer un morceau de code qui effacera tous les produits que vous avez achetés avant d'appeler une méthode qui initialise le flux d'achat gp. C'est particulièrement confortable lorsque vous ne testez qu'un seul élément pour le moment. Par exemple, comme ceci:

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

Accédez à la console Google Play et ouvrez l'onglet Gestion des commandes. Là, vous pouvez rembourser / annuler les achats de test.


1

Si vous êtes dans un environnement de test

1) Dans le cas de android.test.purchased, je peux réinitialiser le faux paiement en redémarrant l'appareil Android (consommé l'inventaire).

2) Dans InApp util, il y a un fichier appelé Security.java, faites-le comme suit, pour temporaire. Étant donné que le paiement de test (faux) renvoie toujours faux en raison d'une exception de sécurité.

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

Ensuite, dans votre OnIabPurchaseFinishedListener, appelez 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

            }

        }
    };

Le fechInvForconsumeItem () est

    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 est

    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

Dans mon cas, il semble que Google n'enregistre pas d'achat pour l'article. Au contraire, la copie locale des services Google Play met en cache l'achat. De cette façon, lorsqu'une deuxième demande est faite sur le même appareil, android.test.purchased already ownedapparaît. Cependant, l'utilisation d'un autre appareil ou la réinitialisation de l'appareil efface le cache et permet de répéter l'achat.


-1

Dans mon cas, j'avais juste besoin de vider le cache des applications. Après avoir vidé le cache, j'ai pu relancer le flux d'achat.

Depuis mon appareil (4.4.2), j'ai accédé à "Paramètres-> Gestionnaire d'applications". Ensuite, j'ai sélectionné l'application dans l'onglet «TÉLÉCHARGÉ», puis «Vider le cache».


-2

C'est la différence entre les articles consommables et non consommables; Les articles non consommables (ce dont vous semblez avoir affaire ici) ont leur état constamment suivi, tandis que les articles consommables peuvent être achetés plusieurs fois. Vous devrez accéder à votre console de gestion Play et annuler / rembourser la vente pour la tester à nouveau.


1
Mais le fait est que je n'ai pas de "pouvoir" sur ces "faux" articles, et je ne vois pas où je pourrais changer le statut de la vente, car ce ne sont pas de vrais achats. Le document google dit à propos de android.test.purchased: Lorsque vous effectuez une demande de facturation via l'application avec cet ID de produit, Google Play répond comme si vous aviez acheté un article avec succès. Donc je suis assez confus: /
psykhi

Faites-vous encore des tests de réponse statique? Si tel est le cas, il vous suffit de modifier la réponse statique envoyée. Il semble que vous soyez prêt à "tester les achats intégrés à l'aide de vos propres identifiants de produit", ce qui permet d'effectuer des achats réels avec des commandes annulables.
Ajout du

Je suis toujours coincé avec les identifiants statiques. Ce que je souhaiterais, c'est pouvoir tester un achat intégré avec l'identifiant android.test.purchased. Cela a juste fonctionné la première fois alors que cela devrait toujours fonctionner d'après ce que je comprends du document Google. Désolé si je n'étais pas clair!
psykhi

Ma mauvaise interprétation, désolé. Dans ce cas ... je ne sais pas. C'est définitivement censé retourner le succès à chaque fois, je n'ai pas vu le cas que vous voyez. Désolé.
Ajout du

Je vais essayer de revoir le problème après une bonne nuit de sommeil :) Merci pour votre aide!
psykhi
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.