Android In-App Billing, missing purchases
Asked Answered
U

3

10

I am using Google's In-App Billing for my Android app.

I used the IabHelper class from Google's how to, as their billing seems extremely complicated.

My issue is I want to know if the purchase is successful or not. I think I'm following the process correctly, but in my logs I see a lot of users that get the upgrade, but whose purchase never shows up in my Google Play payments account. (i.e. they get the upgrade for free).

I'm logging the GP order ids, sometimes its a number like,

GPA.1234-5678-9123-1234

But sometimes its like,

1234567891234.1234567891234

Normally I think its the non GPA orders that don't get charged.

Also I think you can put an order through, then cancel it, and still get the upgrade?

How do you ensure the user really paid?

Code:

IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() {
    public void onIabPurchaseFinished(IabResult result, final Purchase purchase) {
        if (result.isFailure()) {
            showMessage("Google Billing Purchase Error");                   
            return;
        } else if (purchase.getSku().equals(sku)) {
            IabHelper.QueryInventoryFinishedListener mReceivedInventoryListener = new IabHelper.QueryInventoryFinishedListener() {
                public void onQueryInventoryFinished(IabResult result, Inventory inventory) {
                    if (result.isFailure()) {
                        showMessage("Google Billing Error");
                        return;
                    } else {
                        if (inventory.hasPurchase(sku)) {
                            showMessage("Thank you for upgrading");
                            grantUpgrade();
                            // ** This line gets call, but no payment occurs.
                        }
                    }
                }
            };
            mHelper.queryInventoryAsync(mReceivedInventoryListener);
        }
    }
};
mHelper.launchPurchaseFlow(this, sku, 10001, mPurchaseFinishedListener, "");

*** updated to check "inventory.hasPurchase(sku)" but still see users who get the upgrade but don't pay.

** maybe the users are using Freedom hack? Anyway to prevent this?

Urger answered 27/4, 2016 at 19:12 Comment(5)
Do you want to review your order history in short?Heresiarch
If you're going to call out a particular hack, you may need to provide a link that describes it and what exactly it is instead of assuming that everyone knows what it is :)Lalia
See github.com/soomla/android-store/issues/47 or Google "Google Play in-app hack" or "Freedom hack"Urger
Hmm, there are some solutions here I think, #21966869, I will try these and see if they workUrger
Still no luck at preventing fraud on Google Play, I have tried everything, but still get fraud purchases every dayUrger
L
3
 if (result.isFailure()) {
    //If the user aborts or any other problems it will jump here 
  }
  else {
    //The user purchased some item, check out which it is 
    mIsPremium = inventory.hasPurchase(SKU_ANY_ITEM);        
  }

So concerning your question, this code already verify whether the user really purchased the item !

Lucrece answered 27/4, 2016 at 22:9 Comment(11)
Except is doesn't. The "Thank you" line is executed for purchases that never show up in Google payment.Urger
Do you mean you have to check for "hasPurchase" in the onQueryInventoryFinished, i.e. isFailure can be false, but still no purchase?Urger
If so, will "hasPurchase" always be true if they purchased the item, or is there a time lag?Urger
There is no time lag, you should check for "hasPurchase" and if it Returns true, you can be pretty sure he bought the item !Lucrece
Hmmm, that doesn't seem to fix it completely, I still see users able to get the upgrade, but who don't payUrger
Mh, to be honest I think this is a problem you can't fix on your own. Did you already contacted google in this case ?Lucrece
No, but I assume Google Payment works?? I guess you have to expect some fraud every so often, but I get many upgrades per day that do not make any payment, the transactions never have a GPA.1234-5678-9123-1234, but show 1234567891234.1234567891234, not sure what this ? master card vs google play account?Urger
It is strange, because you even double check if the payment has been done, so there is no Problem with the Code you use. Do you know, that the Upgrades you get reported are from different users ? Maybe the grantUpgrade() method just gets called multiple times for one user ?Lucrece
do you know what the account numbers mean? GPA. 1234 vs 1234.5678Urger
@Urger : Check this link for understanding these numbers : #31602734Heresiarch
Hmm, maybe the users getting the free purchases are using the Freedom hack, any way to prevent this?Urger
L
2
Purchase premiumPurchase = inventory.getPurchase(SKU);

boolean mIsPremium = (premiumPurchase != null 
           && verifyDeveloperPayload(premiumPurchase));

if(mIsPremium){
    ...
}
Latoshalatouche answered 12/5, 2016 at 8:38 Comment(0)
A
1

The Google Play Store keeps track of purchases for you, so you shouldn't assume that just because a purchase was successful, the item will stay purchased. It's possible for a user to get a refund for a purchase. For this reason, you need to query the user's inventory every time you launch and adjust your grants appropriately. You would need to do this check anyways in order to support users that expect to have the grant when they switch to a new device or uninstall/reinstall the app.

Armourer answered 11/5, 2016 at 16:13 Comment(2)
For point in time purchases check if they still have the purchase in the future does not help, they already got the item. Hard to use in-app purchasing if you can't trust it.Urger
You could consume the managed purchase, so that once it is consumed it cannot be refunded. Not sure if it supports your use case, but it may help.Armourer

© 2022 - 2024 — McMap. All rights reserved.