Help with handling 2 Developer Products

I’m making 2 developer products for my game and they’re very broken

  1. What do you want to achieve?
    Have something happen when a product is bought
  2. What is the issue?
  • Only 1 product is working at a time (when i try to buy the controller product, the asteroid one does not work at all and vice-versa)

  • If one of the 2 products do work, one of two things will happen: it will work or not do anything at all.

  1. What solutions have you tried so far?
    I’ve looked for answers but all i found is that i had to merge 2 scripts into 1 in order to work, but even that didnt work

Please help, im not the best at scripting.

-- Reference to MarketplaceService
local MarketplaceService = game:GetService("MarketplaceService")

-- Developer Product ID
local PRODUCT_ID = 1863487307

-- Function to handle product purchases
local function onProductPurchased1(receiptInfo)
    -- Find the player who made the purchase
    local player = game.Players:GetPlayerByUserId(receiptInfo.PlayerId)
    
    if not player then
        -- Player not found, postpone receipt handling
        return Enum.ProductPurchaseDecision.NotProcessedYet
    end

    -- Check if the purchased product is the one we're interested in
	if receiptInfo.ProductId == PRODUCT_ID then
		print("purchase sucessful")
		for i,v in ipairs(game:GetService("Players"):GetPlayers()) do
			local startergui = v:WaitForChild("PlayerGui")	
			local label = startergui:FindFirstChild("Summoned"):FindFirstChild("Frame"):FindFirstChild("TextLabel")
			label.Text = "omg ".. player.Name .." summoned a asteroid😃😃👍"
		end
		local asteroid = game.ReplicatedStorage.disasterfolder.asteroid:Clone()
		asteroid.Parent = workspace
		wait(60)
		for i,v in ipairs(game:GetService("Players"):GetPlayers()) do
			local startergui = v:WaitForChild("PlayerGui")	
			local label = startergui:FindFirstChild("Summoned"):FindFirstChild("Frame"):FindFirstChild("TextLabel")
			label.Text = "controller is choosing"
		end
        return Enum.ProductPurchaseDecision.PurchaseGranted
    end
    
    -- For other products, return PurchaseGranted as well
    return Enum.ProductPurchaseDecision.PurchaseGranted
end

-- Set the ProcessReceipt callback
MarketplaceService.ProcessReceipt = onProductPurchased1

local PRODUCT_ID2 = 1863487886

-- Function to handle product purchases
local function onProductPurchased2(receiptInfo)
	-- Find the player who made the purchase
	local player = game.Players:GetPlayerByUserId(receiptInfo.PlayerId)

	if not player then
		-- Player not found, postpone receipt handling
		return Enum.ProductPurchaseDecision.NotProcessedYet
	end

	-- Check if the purchased product is the one we're interested in
	if receiptInfo.ProductId == PRODUCT_ID then
		print("purchase sucessful")
		_G.nextController = player
		return Enum.ProductPurchaseDecision.PurchaseGranted
	end

	-- For other products, return PurchaseGranted as well
	return Enum.ProductPurchaseDecision.PurchaseGranted
end

-- Set the ProcessReceipt callback
MarketplaceService.ProcessReceipt = onProductPurchased2

1 Like

You should only have one function to handle the receipts

This value should only be set once, by setting it once you set it to a function, but by then setting it again you override the original value

1 Like

So how could i do that? Like this?

MarketplaceService.ProcessReceipt = onProductPurchased1, onProductPurchased2
1 Like

No ProcessReceipt only takes one argument.

ProcessReceipt is in charge of handling all of the purchases in your game Only set it once, with one function, that one function, should handle all of the purchases.

3 Likes

No, like @thyswedishviking said you only set it to one function, so combine both of the functions into one

2 Likes

Hmm. So would this work?

-- Reference to MarketplaceService
local MarketplaceService = game:GetService("MarketplaceService")

-- Developer Product ID
local PRODUCT_ID = 1863487307
local PRODUCT_ID2 = 1863487886
-- Function to handle product purchases
local function onProductPurchased1(receiptInfo)
    -- Find the player who made the purchase
    local player = game.Players:GetPlayerByUserId(receiptInfo.PlayerId)
    
    if not player then
        -- Player not found, postpone receipt handling
        return Enum.ProductPurchaseDecision.NotProcessedYet
    end
	if receiptInfo.ProductId == PRODUCT_ID2 then
		print("purchase sucessful")
		_G.nextController = player
		return Enum.ProductPurchaseDecision.PurchaseGranted
	end
    -- Check if the purchased product is the one we're interested in
	if receiptInfo.ProductId == PRODUCT_ID then
		print("purchase sucessful")
		for i,v in ipairs(game:GetService("Players"):GetPlayers()) do
			local startergui = v:WaitForChild("PlayerGui")	
			local label = startergui:FindFirstChild("Summoned"):FindFirstChild("Frame"):FindFirstChild("TextLabel")
			label.Text = "omg ".. player.Name .." summoned a asteroid😃😃👍"
		end
		local asteroid = game.ReplicatedStorage.disasterfolder.asteroid:Clone()
		asteroid.Parent = workspace
		wait(60)
		for i,v in ipairs(game:GetService("Players"):GetPlayers()) do
			local startergui = v:WaitForChild("PlayerGui")	
			local label = startergui:FindFirstChild("Summoned"):FindFirstChild("Frame"):FindFirstChild("TextLabel")
			label.Text = "controller is choosing"
		end
		return Enum.ProductPurchaseDecision.PurchaseGranted

    end
    
    -- For other products, return PurchaseGranted as well
    return Enum.ProductPurchaseDecision.PurchaseGranted
end

-- Set the ProcessReceipt callback
MarketplaceService.ProcessReceipt = onProductPurchased1
1 Like

Yes, that should work properly now.

2 Likes

Ok, im going to test it now and i wll let you guys know if it works.

3 Likes

Sounds good, hope it works! :crossed_fingers: (Min characters)

2 Likes

this is just a suggestion to simplify your code

Like the others said, you should only be assigning ProcessReceipt once. I’d recommend following the structure on the Roblox documentation, it’s a lot simpler!

local mps = game:GetService("MarketplaceService")
local players = game:GetService("Players")

local productFunctions = {} --store all the things products do

--replace '000000' with your product ID
productFunctions[000000] = function(player:Player)
    --what you want the product to do
end

--you can add this as many times as needed for each product. It may need to be moved to a module if it becomes too big.
productFunctions[exampleId] = function(player:Player)
end

--process the receipt
local function processReceipt(info)
    --get the player and the handler
    local player = players:GetPlayerByUserId(info.PlayerId)
    local handler = productFunctions[info.ProductId]

    --run the handler in protected mode
    local success, result = pcall(handler, player)
    if success then --It worked. Let Roblox know the purchase is handled.
        return Enum.ProductPurchaseDecision.PurchaseGranted
    else --it didn't work. Let Roblox know to retry on next join.
        return Enum.ProductPurchaseDecision.NotProcessedYet
    end
end

--set the callback
--this can only be done once
mps.ProcessReceipt = processReceipt

This is just an easier system to help simplify your code, it’s a lot easier to read as well. There’s also a few other things I would recommend changing:

  • You are doing to if statements; consider doing an if ... elseif instead.
  • You are using _G, which is generally considered bad practice.
1 Like

Thank you guys so much for helping me, it worked :smiley: This was my first time posting, i think i wont have to struggle anymore! :sweat_smile:

1 Like

I’d agree with this, however _G is necessary in some places, so I wouldn’t really critique that, though I’d probably go with making your own Globals by having a empty module return just {}, since it provides the same functionality as the built in _G at better performance.

Essentially how returning {} works, is it caches values and when you require that module, and do module.something = setTheValue, it’ll update the cached value.

3 Likes

Yeah, I was going along the lines of creating a custom globals module as well. Thanks for explaining the details of it, I didn’t quite know how to phrase that part :sweat_smile:

No worries, I kind of assumed that was what you were saying, I just didn’t want him to mis interpret it.

3 Likes

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