user3458859
user3458859

Reputation: 11

In App Billing Error: Item already owned (BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED)

I am working on Android Product which supports in app purchase and have large quantity of users doing in app purchases , out of all users some users are facing "BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED" error and the response returned is 7 . I am calling consume call after every purchase being awarded , and also verifying my inventory when the InApp is setup on the start of application and check for any owned item and call the consume on it. Any recommendation's to solve the issue .

Upvotes: 1

Views: 2868

Answers (1)

Uwe Post
Uwe Post

Reputation: 515

See here. Google says that you MUST consume managed inapp items. If you don't, the user cannot purchase another one. After successful purchase, use:

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

You get the token from the purchaseData JSON object:

final String token = jo.getString("purchaseToken");

But if you for some reason did not consume a purchase, you are stuck.

I ran into the same problem because I upgraded to iap api v3 and in v2 this was not a problem.

When you get this error, try to consume all purchases of the given productId. Or just consume everything purchased during setup of the service. Note that you might want to actually provision the purchase after consumePurchase() successfully returns depending on the semantics of your application.

Call the following code after the service is connected (in onServiceConnected()) and of course execute it in background:

String continuationToken="";
boolean hasMorePurchases=false;
do {
    try {
        Bundle purchases = mService.getPurchases(3, activity.getPackageName(), "inapp", continuationToken);
        int response = purchases.getInt("RESPONSE_CODE");
        if (response == 0) {
            continuationToken = purchases.getString("INAPP_CONTINUATION_TOKEN");
            if(!TextUtils.isEmpty(continuationToken)) hasMorePurchases=true;
            final ArrayList<String> purchaseDataList = purchases.getStringArrayList("INAPP_PURCHASE_DATA_LIST");
            for(String purchaseJSON : purchaseDataList) {
                JSONObject object = new JSONObject(purchaseJSON);
                String productId = object.getString("productId");
                String orderId = object.getString("orderId");
                String purchaseToken = object.getString("purchaseToken");
                Log.i(getClass().getSimpleName(),"consuming purchase of " + productId + ", orderId " + orderId);
                mService.consumePurchase(3, activity.getPackageName(), purchaseToken);
            }
        } else {
            Log.e(getClass().getSimpleName(), "could not get purchases: " + response);
        }
    } catch (RemoteException e) {
        Log.e(getClass().getSimpleName(), "RemoteException during getPurchases:", e);
    } catch (JSONException e) {
        Log.e(getClass().getSimpleName(), "JSONException during getSkuDetails:", e);
    }
} while(hasMorePurchases);

Note that each call to getPurchases returns a maximum of 700 purchases, so you need to use the continuation token to get more.

You can of course just use this code if you get the ALREADY_OWNED error code and only for the productId involved. Afterwards, try start the purchase again.

Upvotes: 1

Related Questions