MarketplaceService Too Slow

Hello,

I have a game like “pls donate” where players can purchase game passes from each other. If a player changes the price of their game pass before another person buys it, using
MarketplaceService:GetProductInfo(13195518, Enum.InfoType.GamePass) will get the old price. This allows players to trick the system into thinking they bought a game pass for millions of robux.

Since MarketplaceService seems to update every 60 seconds, what’s a quicker way of getting the price of a game pass?

Thank you!

Just cache the original price of the devproduct/gamepass on the callback when the player purchases it. Then save it to a datastore and when you’re displaying the price, get from the datastore and boom ez

Hello, can you please clarify what you mean by “cache the original price on the callback?”
-Thanks!

1 Like

Are you trying to prompt a purchase or get information on the gamepass?

I’m trying to get the information on the game pass once prompt purchase has finished.

1 Like
local MPS = game:GetService("MarketplaceService")


ID = "your Id"

wait(2)
MPS:PromptPurchase(game.Players.LocalPlayer,ID)
MPS.PromptPurchaseFinished:Connect(function()
	if MPS:PlayerOwnsAsset(game.Players.LocalPlayer,ID) then
		local A = MPS:GetProductInfo(ID, Enum.InfoType.GamePass)
		print(A)
	end
end)


this should work when the player purchases the item

Uh, why would you do that anyways?

Correct me if I’m wrong but you’re using the following property of MarketPlaceService to handle the purchases, right? ProcessReceipt

I don’t mean to come off snarky, but:
If so… Read the documentation on it thoroughly next time.
chrome_AWdOu3bJHm

“CurrencySpent” is a 100% accurate value of how much was actually spent.

Ngl, this seems a bit confusing.

Confusing? Yes. It has to be implemented as a single callback (You cannot connect more, it’s a property.) You can always make a function call other callbacks to make it more organized but that’s complex.

ProcessReceipt is the only reliable way to get the amount of currency spent on any given purchase prompt in a game. Don’t rely on cached info for prices in a multi-variable purchase, that’s just silly. And a good way to go broke/undercut people.

Dont you usually use :PlayerOwnsAsset? to make sure they dont get prompted again?

Edit: im stupid, didnt read right

Let me make my concept tl;dr:

Are you getting a price from :PlayerOwnsAsset?

Doesnt Prompting a Purchase Automatically tell you how much youre spending, how much robux is taken, and the result of the purchase?

Not only that, what if the funds run out or the donation amount we’re processing is more than the funds we have? What if we want to implement a max donation amount, and stop purchases that go above it?

Well, ProcessReceipt allows us to effectively decline a transaction like a bank can decline a card.

-- Here's a snippet of a ProcessReceipt callback I wrote for a club.
local function HandleReceipt(Info)
	local UserID = Info.PlayerId
	local ProductID = Info.ProductId
	if DevProducts["CurrencyAmt"][ProductID] ~= nil then
		if not FindPlayer(UserID) then return Enum.ProductPurchaseDecision.NotProcessedYet end
		local Player = FindPlayer(UserID)
		local Profile = Profiles[Player]
		if not Profile then return Enum.ProductPurchaseDecision.NotProcessedYet end
		local Test = GrantCurrency(Player, Profile, DevProducts["CurrencyAmt"][ProductID])
		if not Test then
			return Enum.ProductPurchaseDecision.NotProcessedYet -- If this is returned, the purchase is effectively cancelled and the user has no robux deducted from their balance.
		else
			return Enum.ProductPurchaseDecision.PurchaseGranted
		end
	else
		DonorDataStore:UpdateAsync(UserID, function(oldValue)
			if (oldValue ~= nil) then
				return oldValue + Info.CurrencySpent -- See this? It's the main use for ProcessReceipt in donation boards.
			end
			return Info.CurrencySpent
		end)

		return Enum.ProductPurchaseDecision.PurchaseGranted
	end
end

And:

Technically yes, but also no. They don’t have any method of returning how much was spent other than through the receipt processing callback. Funnily enough, the result is also dependent on that callback! Woohoo.
So, you’d need to find out how to read the text on the PurchasePrompt (a CoreGui), then you can rely on that workaround until Roblox patches it since it’s technically an exploit.

Reminder: We’re using a script here to make a game like Donate pls; I can read but I’d dare say it’s rather hard to script that on Roblox.

Isn’t ProcessReceipt for developer products, not game passes?

2 Likes

Isn’t doing that the same as

MarketplaceService:GetProductInfo(assetId, Enum.InfoType.Asset).PriceInRobux

1 Like

I don’t believe it is. Edit: No, it doesn’t work for game passes, but seemingly only gamepasses. It works for both developer products and clothing, and possibly even more.

Maybe, except it’ll be one less API call and not cached (which will result in it giving the actual price instead of an older one).

Edit: It would be the same if the alternative actually worked.

processreceipt only works for developer products

1 Like

The ProcessReceipt callback, for whatever reason in the name of Builderman, does not work with gamepasses! I feel like this is almost a bug, it is never explicitly mentioned anywhere on ProcessReceipt's section of the API that it doesn’t work with gamepasses!

ProcessReceipt callback (only PromptGamePassPurchase will work due to gamepasses having different IDs, my gamepass ID as an asset ID points to a Classic Shirt):

(nothing prints)

PromptGamePassPurchaseFinished event (the only one that seems to work, but only gives the gamepass ID):

image

So, unfortunately, it seems like the only way to get a gamepasses’ price is to use :GetProduceInfo.


Back to OP’s problem, I don’t think you should be using gamepasses in the first place. Why not use developer products or t-shirts (like that “Starving Artists” game does) instead if this is such a big issue? I’m not entirely sure there’s a fix for this issue.

Ah my draft didn’t send in reply to @Play_MazeOfHeck: This was my bad. I don’t know how I overlooked the literal reason ProcessReceipt exists (to reward players with in-game items), perhaps I was just too sleepy.

Either way, I’m not entirely positive how Pls Donate sanity checks their donations, but I’ll see if I can find anything relevant and let you know if I do. (If this isn’t solved by then.)

Edit: Also, possible solutions include donation cooldowns, sanity checks, etc.
Another note I have (that I think would be most helpful) is only using :GetProductInfo() after they’ve bought it, since the API should be quicker than they can swap prices.