ProcessReceipt only working in studio?

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")

does anyone know how to fix this?

im confused, this doesnt look very right on my end

what’s wrong with it? is it because result isn’t used?

it looks like you’re defining 4 variables for one pcall

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:


Even though I am not using DataStores anymore, those still fire. Is there any way to fix this?

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```

You’re certain that you published your game and committed the script right?

Yes, I am sure I published the game

try this

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)
2 Likes

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)

And also use character:MoveTo() because it will break the character if you move its rootpart

(While this may not be the answer, its just a fyi cause its really painful not to know

There is nothing wrong with moving the HumanoidRootPart.

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

It’s probably something you did somewhere else in the place because for me it works fine, nothing wrong in the server.

1 Like

THANK YOU SO MUCH! It finally works!

1 Like

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