Help with DevProducds Receipt info

You can write your topic however you want, but you need to answer these questions:

  1. 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
  2. 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

1 Like

Yeah I still Don’t know how to solve

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.

1 Like

Well. same thing still happens

Does it give you any errors or something?

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

1 Like

nope, it still fires more than once there is no error or something like that in output

We solved it on DM, it was an issue with a Module table

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

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.