Making a 500 coins developer product on touch of part

Hey so i made a developer product and i made a script so that when a player touches a part, they are prompted with a dev product purchase (500 coins) but there seems to be an issue at line 52 where it says it attempted to call a nil value.

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[1226666863] = function(receipt, player)
	-- Logic/code for player buying 100 gold (may vary)
	local stats = player:FindFirstChild("leaderstats")
	local coins = stats and stats:FindFirstChild("Coins")
	if coins then
		coins.Value = coins.Value + 500
		-- 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, 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

	-- 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 Enum.ProductPurchaseDecision.NotProcessedYet
	end

	-- Look up handler function from 'productFunctions' table above
	local handler = productFunctions[receiptInfo.ProductId]

	-- Call the handler function and catch any errors
	local success, result = pcall(handler, receiptInfo, player)
	if not success or not result then
		warn("Error occurred while processing a product purchase")
		print("\nProductId:", receiptInfo.ProductId)
		print("\nPlayer:", player)
		return Enum.ProductPurchaseDecision.NotProcessedYet
	end

	-- Record transaction in data store so it isn't granted again
	local success, errorMessage = pcall(function()
		purchaseHistoryStore:SetAsync(playerProductKey, true)
	end)
	if not success then
		error("Cannot save purchase data: " .. errorMessage)
	end

	-- IMPORTANT: Tell Roblox that the game successfully handled the purchase
	return Enum.ProductPurchaseDecision.PurchaseGranted
end

-- Set the callback; this can only be done once by one script on the server! 
MarketplaceService.ProcessReceipt = processReceipt

Have you tried passing the function referenced by the handler variable, directly through the pcall on line 52?

Like so:

local success, result = pcall(productFunctions[receiptInfo.ProductId], recieptInfo, player)

Also I normally use strings as keys when storing functions in a table, so you can try that as well.

Would the script work if i called it in a different way without needing a receipt. I just want to make a script where if the player buys the dev product, the player gets 500 coins

I am just trying to think why that error would happen since things seem to able to work correctly in theory. It’s acting as if the table that has the function is nil, or if pcall itself is nil, which is very strange.

Maybe it has to do with the fact that processReceipt shouldn’t really yield and the pcall is causing issues for it, but im not sure.

And yea I do realize this is how the example is shown on the developer hub. Might need to do a work around instead of fixing the error itself.

Are you sure the receiptInfo.ProductId is equal to 1226666863? If no the handler is nil causing the error.

1226666863

I’m guessing this is a template script, you likely need to change the developer product ID to one of your own (the one which you intend to award 500 coins).

Hey so i fixed it, 1226666863 was indeed my own ID. I have another issue, the purchase goes fine but the players are not awarded 500 Coins, it’s a serverscript with a click detector under the part (fivehundred)

local MarketPlaceService = game:GetService("MarketplaceService")

game.Players.PlayerAdded:Connect(function(player)
	local leaderstats = player:WaitForChild("leaderstats")
end)

MarketPlaceService.PromptPurchaseFinished:Connect(function(userId,assetId,wasPurchased)
	if wasPurchased then
		print("Purchase Finished.")
		if game.Players:GetPlayerByUserId(userId) == nil then
			return Enum.ProductPurchaseDecision.NotProcessedYet
		elseif game.Players:GetPlayerByUserId(userId) ~= nil then

			game.Players:GetPlayerByUserId(userId).leaderstats.Coins.Value += 500
		end
		return Enum.ProductPurchaseDecision.PurchaseGranted
	end
	end)


local purchasePart = game.Workspace:WaitForChild("fivehundred")
purchasePart.ClickDetector.MouseClick:Connect(function(player)
	print("i clicked")
	MarketPlaceService:PromptProductPurchase(player,1228116898)
end)
local MPS = game:GetService("MarketplaceService")
local Players = game:GetService("Players")
local devProductId = 1228116898

local purchasePart = workspace:WaitForChild("fivehundred")
local clickDetect = purchasePart:WaitForChild("ClickDetector")

clickDetect.MouseClick:Connect(function(player)
	MPS:PromptProductPurchase(player, devProductId)
end)

MPS.PromptProductPurchaseFinished:Connect(function(userId, productId, isPurchased)
	if isPurchased then
		local Player = Players:GetPlayerByUserId(userId)
		if Player then
			if productId == devProductId then
				Player.leaderstats.Coins.Value += 500
				return Enum.ProductPurchaseDecision.PurchaseGranted
			--[[elseif productId == 0 then
				Player.leaderstats.Coins.Value += 1000
				return Enum.ProductPurchaseDecision.PurchaseGranted--]]
			end
		elseif not Player then
			return Enum.ProductPurchaseDecision.NotProcessedYet
		end
	end
end)

The bit I’ve commented out would be how you could add more developer products.

1 Like

Worked perfectly first try, thanks alot.