Hello everyone, i have a Skip Stage script and it only works in roblox studio, not in the actual game. When you buy it on studio, it works perfectly, you get teleported to the next stage/checkpoint, but when ingame, you buy it and nothing happens. I need help, anything is greatly loved and appreciated!
Skip stage text button ui script:
script.Parent.MouseButton1Down:Connect(function()
local marketPlaceService = game:GetService("MarketplaceService")
marketPlaceService:PromptProductPurchase(game.Players.LocalPlayer, 1884330488)
end)
Skip Stage script:
local marketPlaceService = game:GetService("MarketplaceService")
marketPlaceService.ProcessReceipt = function(receiptInfo)
local player = game.Players:GetPlayerByUserId(receiptInfo.PlayerId)
if receiptInfo.ProductId == 1884330488 then
player.leaderstats.Stage.Value += 1
wait(1)
player:LoadCharacter()
return Enum.ProductPurchaseDecision.PurchaseGranted
end
end
I think that’s all. There’s also a folder in workspace named: “Checkpoints” that contains numbered part that works as checkpoints.
That is the case, in my obby I use game:GetService("MarketplaceService").PromptProductPurchaseFinished:Connect(function(userID, productID, isPurchased) for my skip stages since I didn’t feel like changing the donation board.
My game had 25k mau and not a single purchase failed so it works good.
You are not supposed to use PromptProductPurchaseFinished for purchase handling as it is only meant to detect the closing of the prompt. There are also reports of it being exploitable from the UGC community.
Not only that, ProcessReceipt allows you to tell Roblox if the purchase was successful or not on your end, cancelling the purchase in case anything goes wrong (DataStore goes down, for example).
I made this script using the source code from the documentation page
local MarketplaceService = game:GetService("MarketplaceService")
local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")
-- Data store for tracking purchases that were successfully processed
local purchaseHistoryStore = DataStoreService:GetDataStore("PurchaseHistory")
-- Table setup containing product IDs and functions for handling purchases
local productFunctions = {}
productFunctions[1884330488 ] = function(_receipt, player)
player.leaderstats.Stage.Value += 1
wait(1)
player:LoadCharacter()
return Enum.ProductPurchaseDecision.PurchaseGranted
end
-- The core 'ProcessReceipt' callback function
local function processReceipt(receiptInfo)
-- Determine if the product was already granted by checking the data store
local playerProductKey = receiptInfo.PlayerId .. "_" .. receiptInfo.PurchaseId
local purchased = false
local success, result, errorMessage
success, errorMessage = pcall(function()
purchased = purchaseHistoryStore:GetAsync(playerProductKey)
end)
-- If purchase was recorded, the product was already granted
if success and purchased then
return Enum.ProductPurchaseDecision.PurchaseGranted
elseif not success then
error("Data store error:" .. errorMessage)
end
-- Determine if the product was already granted by checking the data store
local playerProductKey = receiptInfo.PlayerId .. "_" .. receiptInfo.PurchaseId
local success, isPurchaseRecorded = pcall(function()
return purchaseHistoryStore:UpdateAsync(playerProductKey, function(alreadyPurchased)
if alreadyPurchased then
return true
end
-- Find the player who made the purchase in the server
local player = Players:GetPlayerByUserId(receiptInfo.PlayerId)
if not player then
-- The player probably left the game
-- If they come back, the callback will be called again
return nil
end
local handler = productFunctions[receiptInfo.ProductId]
local success, result = pcall(handler, receiptInfo, player)
-- If granting the product failed, do NOT record the purchase in datastores.
if not success or not result then
error("Failed to process a product purchase for ProductId: " .. tostring(receiptInfo.ProductId) .. " Player: " .. tostring(player) .. " Error: " .. tostring(result))
return nil
end
-- Record the transcation in purchaseHistoryStore.
return true
end)
end)
if not success then
error("Failed to process receipt due to data store error.")
return Enum.ProductPurchaseDecision.NotProcessedYet
elseif isPurchaseRecorded == nil then
-- Didn't update the value in data store.
return Enum.ProductPurchaseDecision.NotProcessedYet
else
-- IMPORTANT: Tell Roblox that the game successfully handled the purchase
return Enum.ProductPurchaseDecision.PurchaseGranted
end
end
-- Set the callback; this can only be done once by one script on the server!
MarketplaceService.ProcessReceipt = processReceipt
You need to put your developer products from the donation board in here any and all developer products must go in here
I tried doing what you said i think but maybe i didn’t correctly do it and it didn’t work. I decided to use a GUI Donation board and it works. Thanks to everyone, if anyone still has a way to fix it reply to me!
The reason why the donation board and the skip stage script were not working simultaneously is probably because the donation board and the skip stage script both use processReceipt in two or more scripts. Remember, you can only use processReceipt one time in one script. This means you need one script to handle all developer products in one place.
The good thing about donation products is that there is no extra code needed. You buy the product and you’ve donated. That is why the Gui donation method works. All you’re doing is prompting them to buy a product, that’s it.
I would recommend reading this and using the source code it provides