Products id script failed (pls help)

Ok, so i have been making Guess The Anime game for a few weeks.
i got to part that i need to make skip stage for robux, but something went wrong.
when i buy skip stage it doesn’t teleport to the next stage, its purchasing and doesn’t teleport
but then i saw that the problem was with my the donation board which is a free model.
when i delete the Donation board script Products the skip stage works.
so the problem is related to Products id, but i don’t know how to fix it.
Please help!
this is the link for the board-- https://www.roblox.com/library/3266631920/Update-Donation-Board
and this is the Checkpoint script – ROBLOX Scripting | Server Script | Skip Stage Checkpoints - Pastebin.com

The exact reason that one or the other works is because you are using 2 different handler functions for marketplaceService.ProcessReceipt which is not possible. I am not terribly sure whether or not the board has a way to easily handle developer products given that it takes up a ProcessReceipt slot. If it does not you’d have to code that. In order to code that you should go into the source of the donation board and search for ProcessReceipt then using a bindable event you could fire that bindable and then listen for when it is fired to somewhat distribute the ProcessReceipt callback.

I cant find the source of the donation board.
I’d be happy if you help me please.

So I hopped into studio and loaded in the board directly from toolbox. Inside of that there is a products module which says the following:

--[[
For the more advanced scripters, READ THIS!
if you're already using the function ProcessReceipt then you must add custom code for this board to work,
as only one of these functions may be used in a game.

to disable the ProcessReceipt function from this board, unquote this above the 'return module' line:
module.AbortCustomPurchases = true

you can update the boards datastore with this line:
game:GetService("DataStoreService"):GetOrderedDataStore("TopDonators"):IncrementAsync(PlayerId, ProductPrice)
-PlayerId, the id from the player who bought the pruduct.
-ProductPrice, the developer products price (In Rs!)
--]]

By my understanding you’d have to actually make the backend of the ProcessReceipt in combination with your current code. That should not be terribly hard although if you need help just let me know.

actually im a new scripter and i need help.
Thank you.
this is the skip stage tutorial – SKIP STAGES - OBBY CHECKPOINTS | Roblox Scripting Tutorial - YouTube

Alright so I wrote up some code, be sure to read the comments so you can somewhat understand how it works. This code is not tested and therefore it can fail. Anyways here it is, replace the ProcessReceipt in your code with this and in the products module set the module.AbortCustomPurchases to true

MarketplaceService.ProcessReceipt = function(recieptInfo)
	local player = Players:GetPlayerByUserId(recieptInfo.PlayerId)
	
	-- Don't grant purchase if the player left or is not here for whatever reason
	if not player then
		return Enum.ProductPurchaseDecision.NotProcessedYet
	end
	
	if recieptInfo.ProductId == ProductId then
		CurrentStage[player.UserId] = CurrentStage[player.UserId] + 1
		local leaderstats = player:FindFirstChild("leaderstats")
		if leaderstats ~= nil then
			local Stage = leaderstats:FindFirstChild("Stage")
			if Stage ~= nil then
				Stage.Value = CurrentStage[player.UserId]
			end
		end
		local TempChar = player.Character
		if TempChar ~= nil then
			NewCharacter(player, TempChar)
		end
		return Enum.ProductPurchaseDecision.PurchaseGranted
	end
	
	-- Loop through the product data
	for _, productData in ipairs(Products) do
		-- if the productData's productId matches the prouct being purchased's id then continue
		if productData.ProductId == recieptInfo.ProductId then
			-- Since IncrementAsync can error we wrap it in a pcall (protected call)
			local success, err = pcall(function()
				game:GetService("DataStoreService"):GetOrderedDataStore("TopDonators"):IncrementAsync(player.UserId, productData.ProductPrice)
			end)
			-- If it errored we wanna know what went wrong
			if success then
				return Enum.ProductPurchaseDecision.PurchaseGranted
			else
				warn("Failed to increment amount donated. Error thrown: " .. err)
				return Enum.ProductPurchaseDecision.NotProcessedYet
			end
		end
	end
	
	return Enum.ProductPurchaseDecision.NotProcessedYet
end

i didnt get it. where i put this code?

Replace the processReceipt function in the checkpoint code with what I sent there. The checkpoint code should look like this:

--[[
Made by Tweakified, Neonblox Games
Video: https://www.youtube.com/watch?v=Yki2Y-IuNnA
Client Script: https://pastebin.com/b3J3fjvC

Script Type: Regular Script
Script Parent: ServerScriptService
--]]

local Players = game:GetService("Players")
local MarketplaceService = game:GetService("MarketplaceService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local SkipStage = ReplicatedStorage:WaitForChild("SkipStage")

local Checkpoints = workspace:WaitForChild("Checkpoints")
local inGameStartupPlayers = {}
local CurrentStage = {}
local TouchDb = {}

local ProductId = 1135733177
local Products = {
	{
		ProductPrice = 5, --The price from the Developer Product.
		ProductId = 33152750 -- The ID from the Developer Product.	
	},
	{
		ProductPrice = 10, --The price from the Developer Product.
		ProductId = 33152755 -- The ID from the Developer Product.	
	},
	{
		ProductPrice = 50, --The price from the Developer Product.
		ProductId = 33152758 -- The ID from the Developer Product.	
	},
	{
		ProductPrice = 100, --The price from the Developer Product.
		ProductId = 33152760 -- The ID from the Developer Product.	
	},
}


local function NewCharacter(player, char)
	local TempCurrentStage = CurrentStage[player.UserId]
	if TempCurrentStage ~= nil then
		local TempCheckpoint = Checkpoints:FindFirstChild(TempCurrentStage)
		if TempCheckpoint ~= nil then
			repeat wait(0.1) until char.PrimaryPart ~= nil
			char:SetPrimaryPartCFrame(CFrame.new(TempCheckpoint.Position + Vector3.new(0, 3, 0)) * CFrame.Angles(0, math.rad(TempCheckpoint.Orientation.Y) + math.rad(90), 0))
		end
	end
end

local function NewPlayer(player)
	CurrentStage[player.UserId] = 1

	local leaderstats = Instance.new("Folder", player)
	leaderstats.Name = "leaderstats"
	local Stage = Instance.new("IntValue", leaderstats)
	Stage.Name = "Stage"
	Stage.Value = 1

	local TempChar = player.Character
	if TempChar ~= nil then
		NewCharacter(player, TempChar)
	end
	player.CharacterAdded:Connect(function(char)
		NewCharacter(player, char)
	end)
end

Players.PlayerAdded:Connect(function(player)
	if inGameStartupPlayers[player] == nil then
		NewPlayer(player)
	end
end)

Players.PlayerRemoving:Connect(function(player)
	CurrentStage[player.UserId] = nil
end)

SkipStage.OnServerInvoke = function(player)
	local connection
	local leaderstats = player:FindFirstChild("leaderstats")
	if leaderstats ~= nil then
		local Stage = leaderstats:FindFirstChild("Stage")
		if Stage ~= nil then
			if #Checkpoints:GetChildren() ~= Stage.Value then
				local PurchaseResult = "Purchase Failed"
				connection = MarketplaceService.PromptProductPurchaseFinished:Connect(function(userId, productId, purchased)
					if player.UserId == userId and productId == ProductId then
						if purchased == true then
							PurchaseResult = "Success"
						end
					end
					connection:Disconnect()
				end)
				MarketplaceService:PromptProductPurchase(player, ProductId)
				repeat wait(0.1) until connection.Connected == false or Players:GetPlayerByUserId(player.UserId) == nil
				return PurchaseResult
			else
				return "You have reached the highest stage!"
			end
		end
	end
end

MarketplaceService.ProcessReceipt = function(recieptInfo)
	local player = Players:GetPlayerByUserId(recieptInfo.PlayerId)
	
	-- Don't grant purchase if the player left or is not here for whatever reason
	if not player then
		return Enum.ProductPurchaseDecision.NotProcessedYet
	end
	
	if recieptInfo.ProductId == ProductId then
		CurrentStage[player.UserId] = CurrentStage[player.UserId] + 1
		local leaderstats = player:FindFirstChild("leaderstats")
		if leaderstats ~= nil then
			local Stage = leaderstats:FindFirstChild("Stage")
			if Stage ~= nil then
				Stage.Value = CurrentStage[player.UserId]
			end
		end
		local TempChar = player.Character
		if TempChar ~= nil then
			NewCharacter(player, TempChar)
		end
		return Enum.ProductPurchaseDecision.PurchaseGranted
	end
	
	-- Loop through the product data
	for _, productData in ipairs(Products) do
		-- if the productData's productId matches the prouct being purchased's id then continue
		if productData.ProductId == recieptInfo.ProductId then
			-- Since IncrementAsync can error we wrap it in a pcall (protected call)
			local success, err = pcall(function()
				game:GetService("DataStoreService"):GetOrderedDataStore("TopDonators"):IncrementAsync(player.UserId, productData.ProductPrice)
			end)
			-- If it errored we wanna know what went wrong
			if success then
				return Enum.ProductPurchaseDecision.PurchaseGranted
			else
				warn("Failed to increment amount donated. Error thrown: " .. err)
				return Enum.ProductPurchaseDecision.NotProcessedYet
			end
		end
	end
	
	return Enum.ProductPurchaseDecision.NotProcessedYet
end

for i,v in pairs(Checkpoints:GetChildren()) do
	local StageNum = tonumber(v.Name)
	v.Touched:Connect(function(hit)
		local char = hit.Parent
		if char ~= nil then
			local Humanoid = char:FindFirstChildOfClass("Humanoid")
			if Humanoid ~= nil and Humanoid.Health > 0 then
				local player = Players:GetPlayerFromCharacter(char)
				if player ~= nil and (TouchDb[player.UserId] or 0) + 1 <= os.time() then
					TouchDb[player.UserId] = os.time()
					local TempCurrentStage = CurrentStage[player.UserId]
					if TempCurrentStage == StageNum - 1 then
						CurrentStage[player.UserId] = StageNum
						local TempLeaderstats = player:FindFirstChild("leaderstats")
						if TempLeaderstats ~= nil then
							local TempStage = TempLeaderstats:FindFirstChild("Stage")
							if TempStage ~= nil then
								TempStage.Value = StageNum
							end
						end
					end
				end
			end
		end
	end)
end

inGameStartupPlayers = Players:GetPlayers()
for i,v in pairs(inGameStartupPlayers) do
	spawn(function()
		NewPlayer(v)
	end)
end

inGameStartupPlayers = {}

OMG ITS WORK.
Thank you so much

Hey, I’m the original creator of that script. This is the first time we have seen one of our scripts publically on a dev forum so I’m very happy :slight_smile:

Unfortunately, we can’t write scripts that work under all circumstances (due to interference from other scripts you have) and the issue for the failure this time was as tobias said, you can’t have multiple ProcessReceipt functions.

Thank you for making this script :smiley: