You can write your topic however you want, but you need to answer these questions:
What do you want to achieve? Keep it simple and clear!
Okay so I am trying to give 100 coins to player after they purchase the DevProduct
What is the issue? Include screenshots / videos if possible!
the first time they buy it it gives 100 coins
second time 200 coins
third time 300 coins
fourth time 400 coins
etc.
local ModuleFolder= game:GetService("ServerStorage"):WaitForChild("Modules")
local PassManager = require(ModuleFolder:WaitForChild("PassManager"))
local function BuyingProductV3(ReceiptInfo)
local player = Players:GetPlayerByUserId(ReceiptInfo.PlayerId)
if not player then return Enum.ProductPurchaseDecision.NotProcessedYet
else
local Handler = PassManager.Handler(player,ReceiptInfo.ProductId)
if not Handler then return Enum.ProductPurchaseDecision.NotProcessedYet
else
local success, message = pcall(Handler,ReceiptInfo,player)
if success and message then
return Enum.ProductPurchaseDecision.PurchaseGranted
else
return Enum.ProductPurchaseDecision.NotProcessedYet
end
end
end
end
MarketPlaceService.ProcessReceipt = BuyingProductV3
This is the PassManager I used on first script
local PassConfig = require(ReplicatedStorage.PassConfig)
local module = {}
local function getConfig(productId)
for i,v in pairs(PassConfig) do
for _,d in ipairs(v) do
if (d.PassID and d.PassID == productId) or (d.DevID and d.DevID == productId) then
return i, d
end
end
end
end
function module.Handler(player,ProductId)
local i, d = getConfig(ProductId)
if not i or not d then return end
if i == "DevProducts" then
print(d.ObtainAmouth) -- This part fires 2 times at 2nd buy
--and 3 times at 3rd buy
--etc.
return d.ObtainAmouth
end
end
return module
it seems like it returns d.ObtainAmouth again and again but I have no idea why or how to solve it I am open to every Idea
Hello, It seems like the issue is due to the function Handler being called multiple times for each purchase, instead of just once. To fix this, you can modify the BuyingProductV3 function to ensure that Handler is only called once per purchase. Please let me know If this resolves your problem!
local function BuyingProductV3(ReceiptInfo)
local player = Players:GetPlayerByUserId(ReceiptInfo.PlayerId)
if not player then
return Enum.ProductPurchaseDecision.NotProcessedYet
else
if player:GetAttribute("ProcessingProduct") then
-- If the player is already processing a product, return NotProcessedYet
return Enum.ProductPurchaseDecision.NotProcessedYet
else
player:SetAttribute("ProcessingProduct", true) -- Set the attribute to indicate the product is being processed
local Handler = PassManager.Handler(player, ReceiptInfo.ProductId)
if not Handler then
player:SetAttribute("ProcessingProduct", false) -- Reset the attribute
return Enum.ProductPurchaseDecision.NotProcessedYet
else
local success, message = pcall(Handler, ReceiptInfo, player)
player:SetAttribute("ProcessingProduct", false) -- Reset the attribute
if success and message then
return Enum.ProductPurchaseDecision.PurchaseGranted
else
return Enum.ProductPurchaseDecision.NotProcessedYet
end
end
end
end
end
This modified function uses an attribute ProcessingProduct to track whether a player is currently processing a product or not. If the player is already processing a product, the function will return Enum.ProductPurchaseDecision.NotProcessedYet without calling the Handler function again. This should prevent the issue of the function being called multiple times for each purchase.
Don’t forget to grant the player their coins in the Handler function:
if i == "DevProducts" then
print(d.ObtainAmouth)
player.Coins.Value = player.Coins.Value + d.ObtainAmouth -- Grant the coins to the player
return true -- Return true to indicate success
end
Make sure to replace player.Coins.Value with the correct reference to the player’s coins in their instance.
no but after a few test it seems like pcall part makes handler fire more than 1 time because and
Changing
the one you writed
local function BuyingProductV3(ReceiptInfo)
local player = Players:GetPlayerByUserId(ReceiptInfo.PlayerId)
if not player then
return Enum.ProductPurchaseDecision.NotProcessedYet
else
if player:GetAttribute("ProcessingProduct") then
-- If the player is already processing a product, return NotProcessedYet
return Enum.ProductPurchaseDecision.NotProcessedYet
else
player:SetAttribute("ProcessingProduct", true) -- Set the attribute to indicate the product is being processed
local Handler = PassManager.Handler(player, ReceiptInfo.ProductId)
if not Handler then
player:SetAttribute("ProcessingProduct", false) -- Reset the attribute
return Enum.ProductPurchaseDecision.NotProcessedYet
else
local success, message = pcall(Handler, ReceiptInfo, player)
player:SetAttribute("ProcessingProduct", false) -- Reset the attribute
if success and message then
return Enum.ProductPurchaseDecision.PurchaseGranted
else
return Enum.ProductPurchaseDecision.NotProcessedYet
end
end
end
end
end
to this
makes it avaible to buy 1 time but it doesn’t reset so client can’t buy it 2nd time ıdk but this seems closer to what you mentioned
-- Just added player:SetAttribute("ProcessingProduct", false) after succes and message
local function BuyingProductV3(ReceiptInfo)
local player = Players:GetPlayerByUserId(ReceiptInfo.PlayerId)
if not player then
return Enum.ProductPurchaseDecision.NotProcessedYet
else
if player:GetAttribute("ProcessingProduct") then
-- If the player is already processing a product, return NotProcessedYet
return Enum.ProductPurchaseDecision.NotProcessedYet
else
player:SetAttribute("ProcessingProduct", true) -- Set the attribute to indicate the product is being processed
local Handler = PassManager.Handler(player, ReceiptInfo.ProductId)
if not Handler then
player:SetAttribute("ProcessingProduct", false) -- Reset the attribute
return Enum.ProductPurchaseDecision.NotProcessedYet
else
local success, message = pcall(Handler, ReceiptInfo, player)
if success and message then
return Enum.ProductPurchaseDecision.PurchaseGranted
player:SetAttribute("ProcessingProduct", false) -- Reset the attribute
else
return Enum.ProductPurchaseDecision.NotProcessedYet
end
end
end
end
end
It seems that the pcall part is causing the handler to fire more than once. Modifying the BuyingProductV3 function as follows allows the purchase to occur only once, but it does not reset to allow the client to buy it a second time. This might be closer to what you mentioned. The only addition is player:SetAttribute(“ProcessingProduct”, false) after success and message. Let’s try this one and see what It will do, also If It will have any errors in console please let me know:
local function BuyingProductV3(ReceiptInfo)
local player = Players:GetPlayerByUserId(ReceiptInfo.PlayerId)
if not player then
return Enum.ProductPurchaseDecision.NotProcessedYet
else
if player:GetAttribute("ProcessingProduct") then
-- If the player is already processing a product, return NotProcessedYet
return Enum.ProductPurchaseDecision.NotProcessedYet
else
player:SetAttribute("ProcessingProduct", true) -- Set the attribute to indicate the product is being processed
local Handler = PassManager.Handler(player, ReceiptInfo.ProductId)
if not Handler then
player:SetAttribute("ProcessingProduct", false) -- Reset the attribute
return Enum.ProductPurchaseDecision.NotProcessedYet
else
local success, message = pcall(Handler, ReceiptInfo, player)
if success and message then
player:SetAttribute("ProcessingProduct", false) -- Reset the attribute
return Enum.ProductPurchaseDecision.PurchaseGranted
else
player:SetAttribute("ProcessingProduct", false) -- Reset the attribute
return Enum.ProductPurchaseDecision.NotProcessedYet
end
end
end
end
end
For the many people who will check this in the future,
"Heres the issue.
In the original Roblox Receipt script, they created a table of functions and you decided to upgrade that as a module.
Originally the Handler variable only contains the function/instructions, then the pcall() grabs that Handler variable to run it securely.
With your modification, Handler is not holding a function, it literally asked a module to run the function and return if it went right. So Handler has the result to tell roblox. But, you did grab Handler reply and runned it on a pcall() again, like the original Receipt Script.
Then, not efficient at all, doing the Loop you did on the Products Module, the GetConfig() function, iterating one by one all products in your game. The idea of the original script was “plug and play” you have the ID from the receipt, then just grab from the table specifically that function/instructions without doing unnecessary loops."
so we Changed
local function BuyingProductV3(ReceiptInfo)
local player = Players:GetPlayerByUserId(ReceiptInfo.PlayerId)
if not player then return Enum.ProductPurchaseDecision.NotProcessedYet
else
local Handler = PassManager.Handler(player,ReceiptInfo.ProductId)
if not Handler then return Enum.ProductPurchaseDecision.NotProcessedYet
else
local success, message = pcall(Handler,ReceiptInfo,player)
if success and message then
return Enum.ProductPurchaseDecision.PurchaseGranted
else
return Enum.ProductPurchaseDecision.NotProcessedYet
end
end
end
end
MarketPlaceService.ProcessReceipt = BuyingProductV3
part to this
local function BuyingProductV3(ReceiptInfo)
local player = Players:GetPlayerByUserId(ReceiptInfo.PlayerId)
if not player then return Enum.ProductPurchaseDecision.NotProcessedYet
else
local Handler = PassConfig.Handler(player,ReceiptInfo.ProductId)
if not Handler then
return Enum.ProductPurchaseDecision.NotProcessedYet
else
return Enum.ProductPurchaseDecision.PurchaseGranted
end
end
end
and then additionaly she suggest me change unnecessary for loops in PassManager
but since this is not about the main problem. it is not neccessary to post that part