Hmm yeah so i have been experimenting a bit but i keep getting an error. Maybe you can figure out why?
Here is the handle purchase script:
local MarketplaceService = game:GetService("MarketplaceService")
local itemAmount = 0
local function GivePlayerItemsFunction(player, itemAmount)
for i, v in pairs(player:FindFirstChild("leaderstats")) do
if v:FindFirstChild("Items") then
local Items = v:FindFirstChild("Items")
Items = Items + itemAmount
print("Found the right folder")
end
end
end
local function onProductPurchased(info)
local ReceivedProductID = info.ProductId
local Player = game.Players:GetPlayerByUserId(info.PlayerId)
if info.ReceivedProductID == 2657161178 then
for _, player in ipairs(game.Players:GetPlayers()) do
if player ~= Player then
player.Character:BreakJoints()
end
end
elseif ReceivedProductID == 2651257892 then
GivePlayerItemsFunction(Player, 5)
elseif ReceivedProductID == 2657163227 then
GivePlayerItemsFunction(Player, 10)
end
end
MarketplaceService.ProcessReceipt = function(receiptInfo)
print("Purchase Succeded")
onProductPurchased()
end
And here is one of the scripts thatās supposed to prompt:
local MarketplaceService = game:GetService("MarketplaceService")
local ProductId = 2651257892
script.Parent.MouseButton1Click:Connect(function()
MarketplaceService:PromptProductPurchase(game.Players.LocalPlayer, ProductId)
end)
What do you mean? Assigning onProductPurchase to ProcessReceipt means it will be called on ProcessReceipt. If we added parenthesis, it would assign the return result.
Donāt forget to make onProductPurchase return an Enum.ProductPurchaseDecision.
Try using this structure I sent. Itāll make it a lot easier.
Anyhow, you just need to return PurchaseGranted if it all went well and NotProcessedYet if it failed and something went wrong purchasing it. So, if anything goes wrong, return NotProcessedYet. You could use a pcall to help achieve this.
local ID = 000
game:GetService("MarketplaceService").PromptProductPurchaseFinished:Connect(function(userID, productID, isPurchased)
if isPurchased == false then return end
--Do Stuff
if productID == ID then
--kill
end
end)
Donāt use PromptProductPurchaseFinished to process product purchases - it even says so on the documentation. Itās vulnerable to exploits because exploiters can just call MarketplaceService:SignalPromptProductPurchaseFinished() to fake a purchase and get free stuff. Thereās also no way to signal to Roblox whether a purchase was successful or not.
Yes. So, basically, since exploiters have full control over their machine, they can call MarketplaceService:SignalPromptProductPurchaseFinished() (which is only callable by core scripts with a thread level of 8) with incorrect parameters to send to the server. They elevate the permissions level of a script to 8 and then call it through there.
So, they can do this:
MarketplaceService:SignalPromptProductPurchaseFinished(
game:GetService("Players").LocalPlayer.UserId,
0, --product ID
true
)
which tricks MarketplaceService into thinking a product prompt was just finished. The third parameter when they call it, true, is now referenced by isPurchased, even though they didnāt buy it. This tricks your script into giving them benefits they didnāt pay for.
MarketplaceService.ProcessReceipt doesnāt have this security flaw.
got it, il keep that in mind, i was thinking of switching to prompproductpurchasefinish cuz its easier, but i guess it will compromise my security, Thanks
Okay well I might be slightly stupid here (Im quite new to scripting) but where exactly am i supposed to write the new stuff? Like where in the script and how do i intergrate it?
Okay wait i might have figured it out although it doesnāt work. (Im probably doing something wrong here)
Here is my script in itās current state, am i forgetting smth? Like there is a place where it says string. Should that be changed?
local function GivePlayerItemsFunction(player, itemAmount)
for i, v in pairs(player:FindFirstChild("leaderstats")) do
if v:FindFirstChild("Items") then
local Items = v:FindFirstChild("Items")
Items = Items + itemAmount
print("Found the right folder")
end
end
end
local productFuncs = {}
productFuncs[2651257892] = function(player: Player)
for _, plr in ipairs(game.Players:GetPlayers()) do
if plr ~= player then
plr.Character:BreakJoints()
end
end
end
productFuncs[2651257892] = function(player: Player)
GivePlayerItemsFunction(player, 5)
end
productFuncs[2657163227] = function(player: Player)
GivePlayerItemsFunction(player, 10)
end
game:GetService("MarketplaceService").ProcessReceipt = function(info: {[string]: any}): Enum.ProductPurchaseDecision
local player = game:GetService("Players"):GetPlayerByUserId(info.PlayerId)
local callback = productFuncs[info.ProductId]
local success = pcall(callback, player)
return (if success then Enum.ProductPurchaseDecision.PurchaseGranted else Enum.ProductPurchaseDecision.NotProcessedYet)
end
That looks like it should work. Try adding some print statements at key points the code to help you figure out where it went wrong. If needed, you can take the error return from pcall and output it if the issueās there.
local success, err = pcall(callback, player)
print(err)
Hmmm well i added some prints and as far as i can see it never enters the for loop. Here is the updated script:
local function GivePlayerItemsFunction(player, itemAmount)
print("Entered GivePlayerItemsFunction")
for i, v in pairs(game.Players:FindFirstChild(player.Name):FindFirstChild("leaderstats")) do
print("Entered for loop")
if v:FindFirstChild("Items") then
local Items = v:FindFirstChild("Items")
Items = Items + itemAmount
print("Found the right folder")
end
end
end
local productFuncs = {}
productFuncs[2651257892] = function(player: Player)
print("Someone purchased Kill All!")
for _, plr in ipairs(game.Players:GetPlayers()) do
if plr ~= player then
plr.Character:BreakJoints()
end
end
end
productFuncs[2657161178] = function(player: Player)
GivePlayerItemsFunction(player, 5)
end
productFuncs[2657163227] = function(player: Player)
GivePlayerItemsFunction(player, 10)
end
game:GetService("MarketplaceService").ProcessReceipt = function(info: {[string]: any}): Enum.ProductPurchaseDecision
local player = game:GetService("Players"):GetPlayerByUserId(info.PlayerId)
local callback = productFuncs[info.ProductId]
local success = pcall(callback, player)
return (if success then Enum.ProductPurchaseDecision.PurchaseGranted else Enum.ProductPurchaseDecision.NotProcessedYet)
end
This was all it printed, never anything about print(āEntered for loopā):
10:50:36.701 Entered GivePlayerItemsFunction - Server - ProcessRecieptScript:37
Okay so i changed it up a bit and it seems to work fine now! Hereās the script for anyone wondering:
local function GivePlayerItemsFunction(player, itemAmount)
if not player then
warn("Player is nil in GivePlayerItemsFunction!")
return
end
print("Entered GivePlayerItemsFunction")
print("Player: "..player.Name)
-- Access player's leaderstats
local leaderstats = player:FindFirstChild("leaderstats")
if not leaderstats then
warn("Leaderstats not found for player: "..player.Name)
return
end
-- Iterate over leaderstats
for _, stat in pairs(leaderstats:GetChildren()) do
print("Checking stat: "..stat.Name)
-- Check for "Items" value
if stat.Name == "Items" and stat:IsA("IntValue") then
stat.Value = stat.Value + itemAmount
print("Updated Items for "..player.Name.." by "..itemAmount)
end
end
end
-- Product Functions
local productFuncs = {}
productFuncs[2651257892] = function(player)
print("Someone purchased Kill All!")
for _, plr in ipairs(game.Players:GetPlayers()) do
if plr ~= player then
plr.Character:BreakJoints()
end
end
end
productFuncs[2657161178] = function(player)
GivePlayerItemsFunction(player, 1)
end
productFuncs[2657163227] = function(player)
GivePlayerItemsFunction(player, 2)
end
-- Process Receipt
game:GetService("MarketplaceService").ProcessReceipt = function(info)
local player = game:GetService("Players"):GetPlayerByUserId(info.PlayerId)
if not player then
warn("Player not found for user ID: "..info.PlayerId)
return Enum.ProductPurchaseDecision.NotProcessedYet
end
local callback = productFuncs[info.ProductId]
if callback then
local success, err = pcall(callback, player)
if not success then
warn("Error in product callback: "..err)
return Enum.ProductPurchaseDecision.NotProcessedYet
end
return Enum.ProductPurchaseDecision.PurchaseGranted
else
warn("No product function found for ProductId: "..info.ProductId)
return Enum.ProductPurchaseDecision.NotProcessedYet
end
end