Hello, I am trying to make a DevProduct that gives an in game value (+1), but the script makes it give that value even without the purchase being confirmed. what happens is that the purchase screen shows up, but the value is added at the same time, so the player can just cancel the purchase and get the value… (I tried adding a video but it didn’t work…)
Here is the code I used:
MPS = game:GetService("MarketplaceService")
id = 967538409
local player = game.Players.LocalPlayer
function ButtonClicked()
local NewTicket = script.Parent.Parent.Parent.Parent.Menu.Frame.NewTicket
MPS:PromptProductPurchase(player, id)
-- RegularTicketAmount is a value stored in the player
-- The Line bellow is the one that gives that value... Does it need to be in an if/else or something?
game.Players.LocalPlayer.Tickets.RegularTicketAmount.Value = game.Players.LocalPlayer.Tickets.RegularTicketAmount.Value + 1
script.Parent.Parent.Parent.Enabled = false
NewTicket.Visible = true
end
script.Parent.MouseButton1Click:Connect(ButtonClicked)
I did some digging and I am fairly certain that you should use ProcessReceipt. People have mentioned that if a purchase never returns that it was granted in a ProcessReceipt callback, it will be refunded to the user after 3 days. Although this doesn’t seem to be wiki documented so I am only speaking on what others have said.
The general consensus seems to be you can use both if you’d like but you MUST use ProcessReceipt in some form to tell Roblox that you honored the purchase.
You make ProcessReceipt exclusively about processing the purchase, and use PromptPurchaseFinished for everything UI/Gameplay/awarding etc related.
You must return PurchaseGranted, but only when the purchase has been processed by you. This system is to ensure that players get what they purchased and if your game couldn’t process it due to an error or because the purchase wasn’t supported, then the player will get their Robux back.
In the ProcessReceipt callback, you should do things like checking that the purchase hasn’t already been saved (check your Datastore for the unique PurchaseId). You should then grant whatever the player has purchased (e.g. coins). And then you should save that the purchase has been granted by storing the unique PurchaseId in your Datastore. And finally return Enum.ProductPurchaseDecision.PurchaseGranted.
If, for example, the purchase already exists in your Datastore, you can go ahead and return Enum.ProductPurchaseDecision.PurchaseGranted immediately. If, for some reason, there’s an issue with the Datastore, you should return Enum.ProductPurchaseDecision.NotProcessedYet which will cause ProcessReceipt to fire again next time the player joins the game or makes another purchase, in the hope that whatever issue prevented it from being processed before is now working.
Granting coins or other items without ProcessReceipt means you might be giving it away for free. Incorrect handling of ProcessReceipt (by returning PurchaseGranted when it hasn’t been saved yet) will essentially be scamming your users as they won’t get what they paid for. Read the documentation carefully and ask further questions if you’re unsure.