I am learning to implement an in-app billing for my app such that people can for example, donate $ when press the donate button.
The user is allowed to donate more than one time, i.e. the purchase is consumable.
The codes below are sourced from the TrivalDrive sample and some tutorials from the 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:
Yet I keep on receiving E/IabHelper(13392): In-app billing error: Unable to buy item, Error response: 7:Item Already Owned
error and that the payment dialog of the Google Play just does not popup.
I have researched and found out many similar situations, some suggested to wait for a few minute and then the purchase will be reset by itself, but I have waited for almost an hour but it still sucks.
I have also found that someone suggest to change the IabResult public boolean isSuccess() { return mResponse == IabHelper.BILLING_RESPONSE_RESULT_OK; }
to return also the BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED
as isSuccess = true, yet i dont know how to amend such...
How could the problem be fixed? Thanks!!
You can use Google Play "FINANCIAL REPORTS"->"Visit your merchant account for more details"->"Orders" to View and Cancel any order to "consume it". Then you need to restart your device. =)
I managed to "consume the purchase" simply by restarting the device.
Check my below code here:
I don't understand in your code why have you used query inventory in purchase finish listener. ConsumeAsync() method should be call while you getting the sku same as your requested sku.
startSetup method
// you have forgot to call query inventory method in startSetup method.
QueryInventoryFinishedListener
Explaination why it happends:
Whenever you purchased consumable item google play store will not be managed it's product purchased detail and other things in the Google play console. That's why we have to call consumeAsync() method. when we purchased item, Google play store keep record item has been purchased for the one time and allow you to purchased second time.
Hope it will solve your problem.
You purchased "android.test.purchased" but did not consume it. However, if you forgot to consume it immediately, it is not easy to consume it again. We can wait for 14 days. The fake purchase will be cleared automatically. But it is not acceptable.
I spent a lot of time finding the solution:
Add this line to get debug info.
Run the app. In LogCat, you will see a json string like
Consume it manually (Replace THAT_JSON_STRING with your json string)
_iabHelper is mHelper.