Android letting me purchase a non-consumable product more than 1 time

I’m using the following setup to make an in app purchase.

I’m able to make the purchase in my app. I have a button setup. When i hit the button, google shows a test card and I’m able to make the purchase - No problem!

However, after making the purchase when i hit the button again, Android does not say user already owns the item. I’m able to make another transaction. I’m setting the “is consumable” boolean value to false.

How do I make/setup a non-consumable purchase that goes through only once.

I’m on 4.26.1

Any thoughts on this behavior?

3 Likes

Use an int or a byte not a bool if you want to do it more than once.

I dont want to do it more than once though. It is letting me do it more than once. I want it to say player already owns this item.

I fixed this finally. Problem lies within the engine itself. According to Google, all purchases need to be “acknowledged” after the successful purchase event. I checked the GooglePlayStoreHelper.java file at Engine → Plugins → Online → Android → OnlineSubsytemGooglePlay → Source → Java → BillingApiV2 → com → EpicGames → ue4 → GooglePlayStoreHelper.java.

Check the OnPurchaseResult method. There is no code for acknowledgement. In fact without acknowledgement, Google play will refund the purchase within a week. So make sure you add this code before the line that says…

nativePurchaseComplete(BillingClient.BillingResponseCode.OK, sku, f_purchase.getPurchaseToken(), receipt, f_purchase.getSignature());

This is the line that says purchase is a success. It makes sense to acknowledge the purchase before this line.

Add these lines.

//Ashy Custom Code
AcknowledgePurchaseParams acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder().setPurchaseToken(f_purchase.getPurchaseToken()).build();

  				AcknowledgePurchaseResponseListener acknowledgePurchaseResponseListener = new AcknowledgePurchaseResponseListener() {
  				@Override
  					public void onAcknowledgePurchaseResponse(BillingResult billingResult) {             
  						//getMessage("Purchase acknowledged");               
  					}
  				};

  				mBillingClient.acknowledgePurchase(acknowledgePurchaseParams,acknowledgePurchaseResponseListener);

//End of Ashy Custom Code

Purchase is acknowledged and Google is showing an error saying you already own this item when i attempt the purchase again.

I hope Epic fixes this soon. Purchases getting refunded after a week could spell disaster for some people.

2 Likes

Hello, thank you very much for posting the solution, it just works. However, I am still unable to check whether the user owns an IAP. In one of your replies under another post you’ve mentioned that you’ve fixed this problem as well. Is there any chance you could post the solution? I’ve been trying to do this myself with no success… Thank you in advance.

to Stanger:
I am not a good programmer so take what I say with a grain of salt; but I do it this whay, is a variation from this old post:

so in GooglePlayStoreHelper.java I modify QueryInAppPurchases()
to show in the blueprint node readInAppPurchaseInformation2
offer id string if that product is Owned. I will include screen captures. I selected the text in the captures by error thats not the only lines that changes. in the blueprint capture just use v2 node;
and offer id string If im not wrong.

1 Like

In my case your solution works but only if I skip the consumePurchase function in that same file, for example leaving the function empty, of removing the two lines in both .cpp files that use that function (onlinePurchaseGooglePlay.cpp and/or OnlineStoreInterfaceGooglePlay.cpp with source compiled engine obiously) I am launching to android. (and for sure there are better ways to do it)

1 Like

Thank you, you’re a live saver! Your solution works, and since you were able to find it I wouldn’t say you’re a bad programmer :wink: I can’t believe I didn’t try to modify this function, I’ve modified literally every other function in this file…

If you do that, you will most likely no longer be able to create consumable items. Basically this would solve a problem but create another. I think that if you add the aknowledge purchase node to the java library like Ashyankee said, and removed finalizePurchase() function from your code(assuming that you make the purchase in CPP), both would work. I have not tested this (yet) but i belive that this is the best way to do it.

Edit: For clarifications, if you look at the onlinesubsystemgoogleplay code, finalizePurchase() consumes the purchase instead of acknowledging it.

I’ve raised a feature request for this

Not sure if they’ll fix it. I’m surprised they haven’t noticed it yet. Is there no one out there making android games with UE4 and offering in app purchases?

This seems like a major oversight and it’s weird that Unreal offers IAP functionality at all without this important feature.

If it’s impossible to check whether or not a user already purchased an IAP, then it’s impossible to carry over his purchases if he installs the app on other devices. Or just resets his device.

@Arturogalaxy It would be very helpful if you could provide the modified version of your GooglePlayStoreHelper.java instead of screenshots. This way it will be easier to understand what you did and easier to add it to our own GooglePlayStoreHelper.java using Diff.

Here is my modified version of GooglePlayStoreHelper.java. With this the Read in App Purchase Information V2 returns [Owned] in the offer id information if the IAP has already been purchased.
Tested in UE 4.26

GooglePlayStoreHelper.java (28.7 KB)

1 Like

Thank you for attaching the file!

I have been struggling all year trying to keep my app maintained under these circumstances, it’s very frustrating. Thanks to those in this thread sharing solutions, it is a godsend.