I want to have a “skip cart ride” dev product that will teleport you to a part and the end of the cart ride.
When you buy the product in Studio, it works fine. However, when purchasing the product in a real server, you do not teleport to the end. I am using ProcessReceipt, and I got this code from the Roblox documentation. Here is my code below
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 123123 for a full heal
productFunctions[1628677296] = function(_receipt, player)
print("5")
player.Character.HumanoidRootPart.CFrame = game.Workspace.teleportPart.CFrame
end
-- The core 'ProcessReceipt' callback function
local function processReceipt(receiptInfo)
-- Determine if the product was already granted by checking the data store
print("1")
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
print("2")
-- 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
print("3")
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
print("4")
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 transaction 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!
print("6")
MarketplaceService.ProcessReceipt = processReceipt
print("7")
You forgot to return true in your productFunction.
Code (got rid of the purchaseHistoryStore because it’s unnecessary, if you want it, just add it back):
--//Services
local MarketplaceService = game:GetService("MarketplaceService")
local Players = game:GetService("Players")
--//Variables
local teleportPart = workspace.teleportPart
--//Tables
local productFunctions = {}
--//Functions
productFunctions[1628677296] = function(player)
local character = player.Character
local humanoidRootPart = character and character:FindFirstChild("HumanoidRootPart")
if humanoidRootPart then
humanoidRootPart.CFrame = teleportPart.CFrame
return true
end
end
local function processReceipt(receiptInfo)
local userId = receiptInfo.PlayerId
local productId = receiptInfo.ProductId
local player = Players:GetPlayerByUserId(userId)
if player then
-- Get the handler function associated with the developer product ID and attempt to run it
local handler = productFunctions[productId]
local success, result = pcall(handler, player)
if success then
-- The user has received their benefits!
-- return PurchaseGranted to confirm the transaction.
return Enum.ProductPurchaseDecision.PurchaseGranted
else
warn("Failed to process receipt:", receiptInfo, result)
end
end
-- the user's benefits couldn't be awarded.
-- return NotProcessedYet to try again next time the user joins.
return Enum.ProductPurchaseDecision.NotProcessedYet
end
-- Set the callback; this can only be done once by one script on the server!
MarketplaceService.ProcessReceipt = processReceipt
I tried adding some print()s, and none of them fire when I buy the product in-game, and I don’t teleport. In the F9 console, this is what I see after I buy the product:
That means you’re using DataStore requests somewhere or you didn’t copy the code correctly. It still says you’re using PurchaseHistory, so yeah, you’re using the wrong code.
--//Services
local MarketplaceService = game:GetService("MarketplaceService")
local Players = game:GetService("Players")
--//Variables
local teleportPart = workspace.teleportPart
--//Tables
local productFunctions = {}
--//Functions
productFunctions[1628677296] = function(player)
local character = player.Character
local humanoidRootPart = character and character:FindFirstChild("HumanoidRootPart")
print("yay!")
if humanoidRootPart then
humanoidRootPart.CFrame = teleportPart.CFrame
print("worked")
return true
end
end
local function processReceipt(receiptInfo)
local userId = receiptInfo.PlayerId
local productId = receiptInfo.ProductId
print("running")
local player = Players:GetPlayerByUserId(userId)
if player then
-- Get the handler function associated with the developer product ID and attempt to run it
local handler = productFunctions[productId]
local success, result = pcall(handler, player)
if success then
-- The user has received their benefits!
-- return PurchaseGranted to confirm the transaction.
print("granted")
return Enum.ProductPurchaseDecision.PurchaseGranted
else
warn("Failed to process receipt:", receiptInfo, result)
end
end
-- the user's benefits couldn't be awarded.
-- return NotProcessedYet to try again next time the user joins.
print("not processed")
return Enum.ProductPurchaseDecision.NotProcessedYet
end
-- Set the callback; this can only be done once by one script on the server!
MarketplaceService.ProcessReceipt = processReceipt```
local mps = game:GetService("MarketplaceService")
local productFunctions = {}
productFunctions[1628677296] = function(player)
local character = player.Character
local humanoidRootPart = character and character:FindFirstChild("HumanoidRootPart")
print("yay!")
if humanoidRootPart then
humanoidRootPart.CFrame = teleportPart.CFrame
print("worked")
return true
end
end
mps.PromptProductPurchaseFinished:Connect(function(userId, productId, purchased)
if not purchased then return end
local player = game.Players:GetPlayerByUserId(userId)
if not player then warn("Where is player?") return end
if not productFunctions[productId] then return end
productFunctions[productId](player)
end)
Hello, i had this problem before about script working in studio, thing is, if it works in studio but not in the game, this mean you are asking a local script or a server script to do something that it cant do, consider changing the scripts to the opposite of what they are now (example turn the server to local or local to script, disable the current script, make a local, copy all the stuff and move them so you dont lose anything)
Last time i did, it actually broke the welds, while the client saw that he was walking fine, the server saw him moving around bugged and whenever he died, he got tped to the position that he was in the server