android: facturation Inapp: réponse D'erreur: 7: élément déjà détenu
je suis en train d'apprendre à implémenter une facturation In-app pour mon application afin que les gens puissent par exemple faire un don de $ en appuyant sur le bouton don.
L'utilisateur est autorisé à donner plus d'une heure, c'est à dire l'achat de consommables.
les codes ci-dessous proviennent de L'échantillon de TrivalDrive et de quelques tutoriels du web:
Code:
IabHelper mHelper;
static final String ITEM_SKU = "android.test.purchased";
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_in_app_billing);
buy10Button = (Button) findViewById(R.id.buy10Button);
buy15Button = (Button) findViewById(R.id.buy15Button);
buy20Button = (Button) findViewById(R.id.buy20Button);
String base64EncodedPublicKey = "keykeykey";
mHelper = new IabHelper(this, base64EncodedPublicKey);
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener()
{
public void onIabSetupFinished(IabResult result)
{
if (!result.isSuccess())
{
Log.d(TAG, "In-app Billing setup failed: " + result);
return;
}
if (mHelper == null)
{
return;
}
Log.d(TAG, "In-app Billing is set up OK");
}
});
}
public void buy10Click(View view)
{
mHelper.launchPurchaseFlow(this, ITEM_SKU, 10001, mPurchaseFinishedListener, "");
}
public void buy15Click(View view)
{
}
public void buy20Click(View view)
{
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (mHelper == null) return;
if (!mHelper.handleActivityResult(requestCode, resultCode, data))
{
super.onActivityResult(requestCode, resultCode, data);
}
}
IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener()
{
public void onIabPurchaseFinished(IabResult result, Purchase purchase)
{
if (mHelper == null) return;
if (result.isFailure())
{
// Handle error
return;
}
else if ((purchase.getSku().equals(ITEM_SKU)))
{
consumeItem();
}
}
};
public void consumeItem()
{
mHelper.queryInventoryAsync(mReceivedInventoryListener);
}
IabHelper.QueryInventoryFinishedListener mReceivedInventoryListener = new IabHelper.QueryInventoryFinishedListener()
{
public void onQueryInventoryFinished(IabResult result, Inventory inventory)
{
if (mHelper == null) return;
if (result.isFailure())
{
// Handle failure
}
else
{
mHelper.consumeAsync(inventory.getPurchase(ITEM_SKU), mConsumeFinishedListener);
}
}
};
IabHelper.OnConsumeFinishedListener mConsumeFinishedListener = new IabHelper.OnConsumeFinishedListener()
{
public void onConsumeFinished(Purchase purchase, IabResult result)
{
if (mHelper == null) return;
if (result.isSuccess())
{
Toast.makeText(InAppBillingActivity.this, "Thank you for your donation!!", Toast.LENGTH_LONG).show();
}
else
{
// handle error
}
}
};
Question:
Pourtant, je continue à recevoir E/IabHelper(13392): In-app billing error: Unable to buy item, Error response: 7:Item Already Owned
erreur et que le dialogue de paiement de le Google Play ne vient pas de popup.
j'ai fait des recherches et découvert beaucoup de situations similaires, certains ont suggéré d'attendre quelques minutes, puis l'achat sera remis par lui-même, mais j'ai attendu pendant près d'une heure, mais il aspire toujours.
j'ai aussi constaté que quelqu'un suggère de modifier le IabResult public boolean isSuccess() { return mResponse == IabHelper.BILLING_RESPONSE_RESULT_OK; }
retour BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED
comme isSuccess = vrai, mais je ne sais pas comment les modifier...
comment résoudre le problème? Merci!!
4 réponses
Vérifier mon code ci-dessous ici:
Je ne comprends pas dans votre code pourquoi avez-vous utilisé query inventory dans purchase finish listener. La méthode ConsumeAsync() devrait être appelée pendant que vous obtenez le même sku que votre sku demandé.
// Callback for when a purchase is finished
IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() {
public void onIabPurchaseFinished(IabResult result, Purchase purchase) {
Log.d(TAG, "Purchase finished: " + result + ", purchase: "
+ purchase);
if (result.isFailure()) {
complain("Error purchasing: " + result);
return;
}
if (!verifyDeveloperPayload(purchase)) {
complain("Error purchasing. Authenticity verification failed.");
return;
}
Log.d(TAG, "Purchase successful.");
if (purchase.getSku().equals(SKU_GAS)) {
// remove query inventory method from here and put consumeAsync() directly
mHelper.consumeAsync(purchase, mConsumeFinishedListener);
}
}
};
startSetup method
/ / vous avez oublié d'appeler la méthode d'inventaire de requête dans la méthode startSetup.
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
public void onIabSetupFinished(IabResult result) {
Log.d(TAG, "Setup finished.");
if (!result.isSuccess()) {
// Oh noes, there was a problem.
complain("Problem setting up in-app billing: " + result);
return;
}
// Hooray, IAB is fully set up. Now, let's get an inventory of
// stuff we own.
Log.d(TAG, "Setup successful. Querying inventory.");
mHelper.queryInventoryAsync(mGotInventoryListener);
}
});
QueryInventoryFinishedListener
Et vérifiez également si l'achat de condition est la même que vous êtes demandé est n'égale pas à null et la charge utile du développeur est également la même dans votre requête fin de l'inventaire auditeur.
if (gasPurchase != null && verifyDeveloperPayload(gasPurchase)){ //code }
// Listener that's called when we finish querying the items and
// subscriptions we own
IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() {
public void onQueryInventoryFinished(IabResult result,
Inventory inventory) {
Log.d(TAG, "Query inventory finished.");
if (result.isFailure()) {
complain("Failed to query inventory: " + result);
return;
}
Log.d(TAG, "Query inventory was successful.");
/*
* Check for items we own. Notice that for each purchase, we check
* the developer payload to see if it's correct! See
* verifyDeveloperPayload().
*/
// // Check for gas delivery -- if we own gas, we should fill up the
// tank immediately
Purchase gasPurchase = inventory.getPurchase(SKU_GAS);
if (gasPurchase != null && verifyDeveloperPayload(gasPurchase)) {
Log.d(TAG, "We have gas. Consuming it.");
mHelper.consumeAsync(inventory.getPurchase(SKU_GAS),
mConsumeFinishedListener);
return;
}
}
};
Explication du pourquoi il se fait:
chaque fois que vous avez acheté article consommable google play store ne sera pas géré son produit acheté détail et d'autres choses dans la console Google play. C'est pourquoi nous devons appeler la méthode consumeAsync (). quand nous avons acheté article, Google Play store garder l'article a été acheté pour la seule fois et vous permettre d'acheter la deuxième fois.
J'espère que ça va résoudre votre problème.
vous avez acheté "android.test.acheté" mais ne le consomme pas. Toutefois, si vous avez oublié de le consommer immédiatement, il n'est pas facile à consommer de nouveau. On peut attendre 14 jours. Le faux achat sera automatiquement effacé. Mais il n'est pas acceptable.
j'ai passé beaucoup de temps à trouver la solution:
Ajouter cette ligne pour obtenir des informations de débogage.
_iabHelper.enableDebugLogging(true, "TAG");
Lancez l'application. Dans LogCat, vous verrez une chaîne json comme
{"packageName":"com.example","orderId":"transactionId.android.test.purchased","productId":"android.test.purchased","developerPayload":"123","purchaseTime":0,"purchaseState":0,"purchaseToken":"inapp:com.example:android.test.purchased"}
Consommer manuellement (Remplacez THAT_JSON_STRING par votre chaîne json)
Purchase purchase;
try {
purchase = new Purchase("inapp", THAT_JSON_STRING, "");
_iabHelper.consumeAsync(purchase, new OnConsumeFinishedListener() {
@Override
public void onConsumeFinished(Purchase purchase, IabResult result) {
Log.d("TAG", "Result: " + result);
}
});
} catch (JSONException e) {
e.printStackTrace();
}
_iabHelper is mHelper.
j'ai réussi à "consommer l'achat" simplement en redémarrant l'appareil.
vous pouvez utiliser Google Play "rapports financiers"->"visitez votre compte marchand pour plus de détails"->"commandes" pour afficher et annuler toute commande pour "le consommer". Ensuite, vous devez redémarrer votre appareil. =)