Do not cache results of UserOwnsGamePassAsync

Currently Roblox will cache the results of UserOwnsGamePassAsync. This is a pain and just forces developers to manually track when players buy a gamepass. The results should not be cached and should return the most recent status on whether or not the gamepass is owned.

For example I have a car that requires a gamepass to own. The player tries to spawn it so I check if they own it and they dont, so they get prompted to buy the gamepass. They buy it but the result of UserOwnsGamePassAsync is cached so now I have to set up a whole different system to track gamepass purchases. There’s no good reason to cache UserOwnsGamePassAsync, Roblox can afford the network costs.

22 Likes

related: Update the UserOwnsGamePassAsync cached value when PromptGamePassPurchaseFinished fires

7 Likes

Bump. It is currently too annoying to handle gamepass purchases as players must rejoin to benefit off the purchase. It’d be much better if there was an option to disable the cache when calling UserOwnsGamePassAsync or disabling it completely.

4 Likes

This needs to be implemented, currently the only valid way to validate gamepass purchases is by having players rejoin.

  • The wasPurchased argument in PromptGamePassPurchaseFinished is unreliable as it can be sent as true.
  • Roblox Recommends to use UserOwnsGamePassAsync but the problem is it’s cached since the player joins, so it would return false instead of true if the player just bought the gamepass.
  • So when checking UserOwnsGamePassAsync it would be better if it had a no cache option like GetAsync that returns the latest gamepass state.
2 Likes

This isn’t true for gamepasses.
You can use that boolean to determine wether or not a purchase went through successfully. Roblox has an example of it in the docs.

Devproducts should be handled using the ProcessReceipt callback.

the issue is that exploiters can spoof it to make it seem like they purchased a pass when they didn’t.

MarketplaceService:SignalPromptGamePassPurchaseFinished(..., ..., true)

hence, you can’t rely on this Boolean, and if the user rejoins it’ll return the outdated, cached value. This means there’s no real reliable way to determine if a user actually bought the pass or not.

3 Likes

They can’t do this for gamepasses. That callback is secured (assuming you listen to it on the server).

It only affects DevProducts, where listening to the callback isn’t a correct way to handle purchases.

actually… it’s still spoofable for gamepasses.

notice how it said “purchased!”
this was the server code used.

local mps = game:GetService("MarketplaceService")

mps.PromptGamePassPurchaseFinished:Connect(function(player: Player, id: number, purchased: boolean)
	if (purchased) then
		print("purchased!")
	end
end)
7 Likes

This seems relevant: It's impossible to safely grant rewards for gamepasses bought in-game - #8 by xonae

They can spam it basically. Like they can do with remotes.

I assume you own the gamepass you’re testing on (default behavior).

No, I made sure to delete it first. The pass was group owned too.

Roblox has no way to verify the authenticity of a purchase because it relies on the client to tell it when the purchase finished. Not caching the results of this function is the quickest fix for this.

There’s no real point in continuing this argument considering neither of us will believe each other until we see proof in game servers and neither of us are willing to download executors.

1 Like

roblox can we please get a follow-up?

2 Likes

bumping this, as this would be very useful

1 Like

this would be very useful for my current game!!!

Well, since you are allowed to cheat in your own games, I checked and while Roblox DOES check if you own the gamepass, you can repeat the signal, which could be abused in some cases.