Every time I buy a dev product unless it’s Plus Wins, it gives me this error: “Transform function error: Callbacks cannot yield.” Then, when I buy another product that’s Plus Wins, it gives me the error again. What did I do wrong?
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 = {}
-- ProductId 1634262175 for Kill Everyone
productFunctions[1634262175] = function(_receipt, player)
game.ReplicatedStorage.Events.DevProductPurchase:FireClient(player)
game.ReplicatedStorage.Events.KillEveryoneMessageEvent:FireAllClients({Text = player.DisplayName .. " (@" .. player.Name ..")" .. " has bought Kill Everyone", Color = Color3.new(1, 0, 0), Font = Enum.Font.SourceSansBold, FontSize = Enum.FontSize.Size24})
for i,v in pairs(game.Players:GetPlayers()) do
if (v.UserId ~= player.UserId and v.Character and v.Character:FindFirstChild("Humanoid")) then
v.Character:FindFirstChild("Humanoid").Health = 0
end
end
return true
end
-- ProductId 1634262146 for Reset Winners
productFunctions[1634262146] = function(_receipt, player)
game.ReplicatedStorage.Events.DevProductPurchase:FireClient(player)
game.ReplicatedStorage.Events.ResetWinnersMessageEvent:FireAllClients({Text = player.DisplayName .. " (@" .. player.Name ..")" .. " has bought Reset Winners", Color = Color3.new(0, 0.682353, 1), Font = Enum.Font.SourceSansBold, FontSize = Enum.FontSize.Size24})
game.Workspace.End.AllowTeamChangeOnTouch = false
for i,v in pairs(game.Players:GetPlayers()) do
if (v.Character and v.Character:FindFirstChild("Humanoid")) then
if v.Team.Name == "Winners" then
v.Character:FindFirstChild("Humanoid").Health = 0
for i = 20, 0, -1 do
v.Team = game.Teams:FindFirstChild("Climbers")
wait(0.1)
end
game.ReplicatedStorage.ResetConfettiEvent:FireClient(v)
v.debounces.CanWin.Value = true
end
end
end
game.Workspace.End.AllowTeamChangeOnTouch = true
return true
end
-- ProductId 1634262176 for Skip To End
productFunctions[1634262176] = function(_receipt, player)
game.ReplicatedStorage.Events.DevProductPurchase:FireClient(player)
game.ReplicatedStorage.Events.SkipToEndMessageEvent:FireAllClients({Text = player.DisplayName .. " (@" .. player.Name ..")" .. " has bought Skip To End", Color = Color3.new(1, 0.588235, 0), Font = Enum.Font.SourceSansBold, FontSize = Enum.FontSize.Size24})
if player.Character and player.Character:FindFirstChild("Humanoid") then
player.Character:FindFirstChild("Humanoid").Health = 0
for i = 20, 0, -1 do
player.Team = game.Teams:FindFirstChild("Winners")
wait(0.1)
end
end
return true
end
-- ProductId 1635129013 for 1 Win
productFunctions[1635129013] = function(_receipt, player)
game.ReplicatedStorage.Events.DevProductPurchase:FireClient(player)
local stats = player:FindFirstChild("leaderstats")
local Wins = stats and stats:FindFirstChild("Wins")
if Wins then
Wins.Value = Wins.Value + 1
-- Indicate a successful purchase
return true
end
end
-- ProductId 1635129010 for 5 Win
productFunctions[1635129010] = function(_receipt, player)
game.ReplicatedStorage.Events.DevProductPurchase:FireClient(player)
local stats = player:FindFirstChild("leaderstats")
local Wins = stats and stats:FindFirstChild("Wins")
if Wins then
Wins.Value = Wins.Value + 5
-- Indicate a successful purchase
return true
end
end
-- ProductId 1635129009 for 10 Win
productFunctions[1635129009] = function(_receipt, player)
game.ReplicatedStorage.Events.DevProductPurchase:FireClient(player)
local stats = player:FindFirstChild("leaderstats")
local Wins = stats and stats:FindFirstChild("Wins")
if Wins then
Wins.Value = Wins.Value + 10
-- Indicate a successful purchase
return true
end
end
-- ProductId 1635129011 for 25 Win
productFunctions[1635129011] = function(_receipt, player)
game.ReplicatedStorage.Events.DevProductPurchase:FireClient(player)
local stats = player:FindFirstChild("leaderstats")
local Wins = stats and stats:FindFirstChild("Wins")
if Wins then
Wins.Value = Wins.Value + 25
-- Indicate a successful purchase
return true
end
end
-- ProductId 1635129008 for 50 Win
productFunctions[1635129008] = function(_receipt, player)
game.ReplicatedStorage.Events.DevProductPurchase:FireClient(player)
local stats = player:FindFirstChild("leaderstats")
local Wins = stats and stats:FindFirstChild("Wins")
if Wins then
Wins.Value = Wins.Value + 50
-- Indicate a successful purchase
return true
end
end
-- ProductId 1635129581 for +3 RoundsUntilReset
productFunctions[1635129581] = function(_receipt, player)
game.ReplicatedStorage.Events.DevProductPurchase:FireClient(player)
game.ReplicatedStorage.Events.Rounds3MessageEvent:FireAllClients({Text = player.DisplayName .. " (@" .. player.Name ..")" .. " has bought +3 Rounds", Color = Color3.new(0.0901961, 0.898039, 0), Font = Enum.Font.SourceSansBold, FontSize = Enum.FontSize.Size24})
local ReplicatedStorage = game.ReplicatedStorage
local RoundsUntilReset = ReplicatedStorage.RoundsUntilReset
if RoundsUntilReset then
RoundsUntilReset.Value = RoundsUntilReset.Value + 3
-- Indicate a successful purchase
return true
end
end
-- ProductId 1635129581 for +10 RoundsUntilReset
productFunctions[1635129583] = function(_receipt, player)
game.ReplicatedStorage.Events.DevProductPurchase:FireClient(player)
game.ReplicatedStorage.Events.Rounds3MessageEvent:FireAllClients({Text = player.DisplayName .. " (@" .. player.Name ..")" .. " has bought +10 Rounds", Color = Color3.new(0.0901961, 0.898039, 0), Font = Enum.Font.SourceSansBold, FontSize = Enum.FontSize.Size24})
local ReplicatedStorage = game.ReplicatedStorage
local RoundsUntilReset = ReplicatedStorage.RoundsUntilReset
if RoundsUntilReset then
RoundsUntilReset.Value = RoundsUntilReset.Value + 10
-- Indicate a successful purchase
return true
end
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