Je teste actuellement mon mécanisme de facturation InApp (en utilisant l'API InApp Billing version 3, prenant donc l'exemple TrivialDrive comme référence).
J'ai un élément géré, qui est une mise à niveau vers la version premium.
Maintenant, l'achat de l'article avec mon compte de test fonctionne, mais lorsque j'annule la totalité de la commande dans Google Checkout par la suite, mon code me dit toujours que l'article est acheté et accorde donc les fonctionnalités premium.
Voici comment je vérifie l'achat dans ma MainActivity. Je n'enregistre pas l'état d'achat localement quelque part, car j'ai compris qu'avec l'API de facturation v3, vous pouvez interroger les achats au besoin.
@Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
iabHelper = new IabHelper(this, Helper.getPKey());
iabHelper.enableDebugLogging(true);
iabHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
@Override
public void onIabSetupFinished(IabResult result) {
Log.d("IAB", "SETUP FINISHED");
if(!result.isSuccess())
{
Log.d("IAB", "SETUP NOT OK");
return;
}
else
Log.d("IAB", "SETUP OK");
iabHelper.queryInventoryAsync(
new QueryInventoryFinishedListener() {
@Override
public void onQueryInventoryFinished(IabResult result, Inventory inv) {
Log.d("IAB", "Query inventory finished.");
if (result.isFailure()) {
Log.d("IAB","Failed to query inventory: " + result);
return;
}
Log.d("IAB", "Query inventory was successful.");
// Do we have the premium upgrade?
boolean mIsPremium = inv.hasPurchase(Helper.premiumSku);
Purchase p = inv.getPurchase(Helper.premiumSku);
if(p != null)
Log.d("IAB PURCHASE STATE", IabHelper.getResponseDesc(p.getPurchaseState()));
else
Log.d("IAB PURCHASE STATE", "Purchase is null");
Log.d("IAB", "User is " + (mIsPremium ? "PREMIUM" : "NOT PREMIUM"));
}
}
);
}
});
}
Je reçois toujours getPurchaseState = 0, ce qui signifie qu'il est acheté, même une heure après avoir annulé la commande. Pourquoi?
Après avoir attendu environ 12 heures et avoir essayé tout ce qui est suggéré ici, j'étais toujours confronté au même problème. Ce qui m'a fait l'affaire, c'est la commande adb suivante:
adb Shell pm clear com.Android.vending
Je sais que cela a un an, mais aucune des réponses/astuces présentées ne m'a aidé, alors j'ai pensé ajouter ma solution.
Tout d'abord, je rencontrais le même problème. À savoir, a effectué un achat test, l'a annulé, a toujours reçu un état d'achat indiquant un achat valide.
Ce que j'ai oublié, c'est que j'ai récemment changé le champ "Réponse au test de licence" dans le volet des paramètres de la console développeur de Google Play de "RESPOND_NORMALLY" à "LICENSED"
Après l'avoir redéfini sur 'RESPOND_NORMALLY', l'état d'achat de l'achat annulé a été correctement renvoyé en tant que tel.
Donc, vous voudrez peut-être vérifier cela avant d'essayer d'attendre des jours
Ce problème se produit également lors de l'utilisation de l'application sur un autre appareil avec le même compte. L'article n'est pas reçu tel qu'il a été acheté avant le redémarrage de l'appareil, même après des heures. Si vous essayez de faire un nouvel achat, la boîte de dialogue Google Wallet indique "l'élément déjà détenu". Le code retour de l'iabHelper est toujours "annulé par l'utilisateur" car la réponse réelle de l'activité d'achat n'est pas restituée, juste écrite dans le journal de débogage.
else if (resultCode == Activity.RESULT_CANCELED) {
logDebug("Purchase canceled - Response: " + getResponseDesc(responseCode));
result = new IabResult(IABHELPER_USER_CANCELLED, "User canceled.");
if (mPurchaseListener != null) mPurchaseListener.onIabPurchaseFinished(result, null);
}
Il n'est donc pas possible de réagir à cette boîte de dialogue de facturation Google, car nous obtenons toujours le même résultat IABHELPER_USER_CANCELED, même si la boîte de dialogue indique "l'élément déjà détenu".
Éditer:
Je le corrige avec ceci:
else if (resultCode == Activity.RESULT_CANCELED) {
logDebug("Purchase canceled - Response: " + getResponseDesc(responseCode));
if(responseCode == 7)
result = new IabResult(BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED, "Item already owned.");
else
result = new IabResult(IABHELPER_USER_CANCELLED, "User canceled.");
if (mPurchaseListener != null) mPurchaseListener.onIabPurchaseFinished(result, null);
}
Alors maintenant, si la réponse de la boîte de dialogue de facturation est 7 comme "Article déjà possédé", je le signale à mon auditeur.
Étape 1. Attendez environ 10 minutes; Jusqu'à ce que la "commande annulée" soit livrée. dans votre portefeuille Google.
15 sept. 11:28 AM Annulée La commande a été livrée.
15 sept. 11:18 AM Annulé Vous avez annulé cette commande. Motif: demande du client d'annuler.
Étape 2. Déconnectez votre compte Google test sur l'appareil, puis reconnectez-vous.
Au moins, cela a résolu mon problème.
Ce que vous pouvez utiliser est le champ autoRenewing
des données d'achat. Selon la documentation :
autoRenewing: indique si l'abonnement se renouvelle automatiquement. Si vrai, l'abonnement est actif et sera automatiquement renouvelé à la prochaine date de facturation. Si faux, indique que l'utilisateur a annulé l'abonnement .
Et ce champ est mis à jour immédiatement après l'annulation.
si je vois correctement le code de référence dans le trivialdrivesample est faux, ce serait dommage pour le projet de référence officiel pour la facturation via l'application.
si achat == null, cela signifie simplement qu'il n'a jamais été acheté. Pour obtenir les vraies informations que vous devez appeler
purchase.getPurchaseState()
selon ici
purchaseState L'état d'achat de la commande. Les valeurs possibles sont 0 (acheté), 1 (annulé), 2 (remboursé) ou 3 (expiré, pour les achats d'abonnement uniquement).
Il est déjà bien répondu dans les documents officiels de Google. Copiez les mots ici.
Lorsque l'utilisateur annule un abonnement, Google Play n'offre pas de remboursement pour le cycle de facturation en cours. Au lieu de cela, il permet à l'utilisateur d'avoir accès à l'abonnement annulé jusqu'à la fin du cycle de facturation en cours, moment auquel il met fin à l'abonnement. Par exemple, si un utilisateur achète un abonnement mensuel et l'annule le 15e jour du cycle, Google Play considérera que l'abonnement est valable jusqu'à la fin du 30e jour (ou un autre jour, selon le mois).
Cela devrait tout expliquer. getPurchase()
renverra toujours les données d'achat jusqu'à la fin du cycle d'abonnement en cours.
J'ai trouvé la section suivante dans la documentation (IAB API v2), mais je ne sais pas si cela peut être utilisé pour IAB API v3. L'émission pourrait néanmoins être envoyée.
"... votre application peut recevoir une intention de diffusion IN_APP_NOTIFY lorsque Google Play reçoit une notification de remboursement de Google Wallet. Dans ce cas, Google Play envoie un message IN_APP_NOTIFY à votre application. Votre application peut gérer ce message de la même manière qu'elle gère les réponses de un message REQUEST_PURCHASE initié par l'application afin que votre application reçoive finalement un message PURCHASE_STATE_CHANGED qui comprend des informations sur l'article qui a été remboursé. Les informations de remboursement sont incluses dans la chaîne JSON qui accompagne l'intention de diffusion PURCHASE_STATE_CHANGED. De plus, le champ PurchaseState dans le JSON la chaîne est définie sur 2. "
de: http://developer.Android.com/google/play/billing/v2/api.html#billing-action-notify