Dev product menu not adding money correctly

I’m trying to make a developer product menu, but every time you buy a product, it gives you more then specified. What happens is(the best example i can make):
Normal amount: 5k,
1 Buy: 5k,
2 Buy 15k,
3 Buy 30k.
It seems to add the bought money to one value and then always gives that to the player for some reason.
Video of it happening:


Also this happens with every product, not just the 500 one.
Server sided code: (client just fires a event)

game.ReplicatedStorage.PromptPurchase.OnServerEvent:Connect(function(plr, ID, money)
	ms:PromptProductPurchase(plr, ID)
	ms.PromptProductPurchaseFinished:Connect(function(plrID, product, purchased)
		if plrID == plr.UserId then
			if product == ID and purchased == true then
				plr.leaderstats.Money.Value += money
			end
		end
	end)
end)

Thanks for reading.

1 Like

did you forget to return Enum.ProductPurchaseDecision.PurchaseGranted?

But it does the purchase fully on the server, all the client does is fire a event with the product ID and the amount of money. (Just realized exploiters can use this to their advantage, gotta fix that)

Just found out that PromptProductPurchaseFinished fires multiple times.

Can you share the server side of the code? specifically the ProcessReceipt part

The code i sent is the server code.

Based of the code he’s given I think this is the serversided code…

You should do some research and use ProcessReciept to finish the transaction

It’s the server code.

charchar

you are using developer products for this right? Where is your processreceipt function?
You cannot handle developer products without one.

1 Like

oh my god… :worried: this isnt how you handle dev products Check the documentation which gives you an in-depth explanation and example code Developer Products | Documentation - Roblox Creator Hub

1 Like

This code is very unreliable and can easily be exploited. For example, a exploiter could just change the “money” value as you rely on the client to determine how much money to give.

Also exploiters can fire the PromptProductPurchaseFinished as purchased without actually purchasing it. Using processReciept is crucial to actually verify that the product was purchased.

I’m deeply sorry for the abomonation of code i sent, ill look into it right away!

Thank you for letting me know that i should use this, instead of my old code!

I know you’ve already assigned a solution but this might make it more clear.

You are using PromptProductPurchaseFinished to handle the purchase.
However like the docs says this is not the correct way to handle them.

Instead, you should use ProcessReceipt.

In the ProcessReceipt function, once you’ve successfully granted the purchase, you need to return Enum.ProductPurchaseDecision.PurchaseGranted. If something goes wrong like a datastore error and you were not able to give the player it’s reward you should return Enum.ProductPurchaseDecision.NotProcessedYet. This tells Roblox to retry the function later.

Right now, you don’t have a ProcessReceipt function, which means you never returned Enum.ProductPurchaseDecision.PurchaseGranted and Roblox never got confirmation that the purchase was granted. So the next time they buy 500 cash, the function runs twice once for the new purchase and once for the previous one that wasn’t confirmed giving them 1000 cash instead.

1 Like