Issue with ProfileService dev products handling

Code directly from the profileservice docs

Output:

My code:

local SETTINGS = {

	ProfileTemplate = {
		Cash = 0,
	},

	Products = { -- developer_product_id = function(profile)
		[1203567724] = function(profile)
			profile.Data.Cash += 10
			print(profile.Data.Cash)
		end,
		[1203567938] = function(profile)
			profile.Data.Cash += 100
			print(profile.Data.Cash)	
		end,
	},

	PurchaseIdLog = 50, -- Store this amount of purchase id's in MetaTags;
	-- This value must be reasonably big enough so the player would not be able
	-- to purchase products faster than individual purchases can be confirmed.
	-- Anything beyond 30 should be good enough.

}

----- Loaded Modules -----

local ProfileService = require(game.ServerScriptService.ProfileService)

----- Private Variables -----

local Players = game:GetService("Players")
local MarketplaceService = game:GetService("MarketplaceService")

local GameProfileStore = ProfileService.GetProfileStore(
	"PlayerData",
	SETTINGS.ProfileTemplate
)

local Profiles = {} -- {player = profile, ...}

----- Private Functions -----

local function PlayerAdded(player)
	local profile = GameProfileStore:LoadProfileAsync("Player_" .. player.UserId)
	if profile ~= nil then
		profile:AddUserId(player.UserId) -- GDPR compliance
		profile:Reconcile() -- Fill in missing variables from ProfileTemplate (optional)
		profile:ListenToRelease(function()
			Profiles[player] = nil
			player:Kick() -- The profile could've been loaded on another Roblox server
		end)
		if player:IsDescendantOf(Players) == true then
			Profiles[player] = profile
		else
			profile:Release() -- Player left before the profile loaded
		end
	else
		-- The profile couldn't be loaded possibly due to other
		--   Roblox servers trying to load this profile at the same time:
		player:Kick() 
	end
end

function PurchaseIdCheckAsync(profile, purchase_id, grant_product_callback) --> Enum.ProductPurchaseDecision
	-- Yields until the purchase_id is confirmed to be saved to the profile or the profile is released

	if profile:IsActive() ~= true then

		return Enum.ProductPurchaseDecision.NotProcessedYet

	else

		local meta_data = profile.MetaData

		local local_purchase_ids = meta_data.MetaTags.ProfilePurchaseIds
		if local_purchase_ids == nil then
			local_purchase_ids = {}
			meta_data.MetaTags.ProfilePurchaseIds = local_purchase_ids
		end

		-- Granting product if not received:

		if table.find(local_purchase_ids, purchase_id) == nil then
			while #local_purchase_ids >= SETTINGS.PurchaseIdLog do
				table.remove(local_purchase_ids, 1)
			end
			table.insert(local_purchase_ids, purchase_id)
			coroutine.wrap(grant_product_callback)()
		end

		-- Waiting until the purchase is confirmed to be saved:

		local result = nil

		local function check_latest_meta_tags()
			local saved_purchase_ids = meta_data.MetaTagsLatest.ProfilePurchaseIds
			if saved_purchase_ids ~= nil and table.find(saved_purchase_ids, purchase_id) ~= nil then
				result = Enum.ProductPurchaseDecision.PurchaseGranted
			end
		end

		check_latest_meta_tags()

		local meta_tags_connection = profile.MetaTagsUpdated:Connect(function()
			check_latest_meta_tags()
			-- When MetaTagsUpdated fires after profile release:
			if profile:IsActive() == false and result == nil then
				result = Enum.ProductPurchaseDecision.NotProcessedYet
			end
		end)

		while result == nil do
			task.wait()
		end

		meta_tags_connection:Disconnect()

		return result

	end

end

local function GetPlayerProfileAsync(player) --> [Profile] / nil
	-- Yields until a Profile linked to a player is loaded or the player leaves
	local profile = Profiles[player]
	while profile == nil and player:IsDescendantOf(Players) == true do
		task.wait()
		profile = Profiles[player]
	end
	return profile
end

local function GrantProduct(player, product_id)
	-- We shouldn't yield during the product granting process!
	local profile = Profiles[player]
	local product_function = SETTINGS.Products[product_id]
	if product_function ~= nil then
		product_function(profile)
	else
		warn("ProductId " .. tostring(product_id) .. " has not been defined in Products table")
	end
end

local function ProcessReceipt(receipt_info)

	local player = Players:GetPlayerByUserId(receipt_info.PlayerId)

	if player == nil then
		return Enum.ProductPurchaseDecision.NotProcessedYet
	end

	local profile = GetPlayerProfileAsync(player)

	if profile ~= nil then

		return PurchaseIdCheckAsync(
			profile,
			receipt_info.PurchaseId,
			function()
				GrantProduct(player, receipt_info.ProductId)
			end
		)

	else
		return Enum.ProductPurchaseDecision.NotProcessedYet
	end

end

----- Initialize -----

for _, player in ipairs(Players:GetPlayers()) do
	coroutine.wrap(PlayerAdded)(player)
end

MarketplaceService.ProcessReceipt = ProcessReceipt

----- Connections -----

Players.PlayerAdded:Connect(PlayerAdded)

Players.PlayerRemoving:Connect(function(player)
	local profile = Profiles[player]
	if profile ~= nil then
		profile:Release()
	end
end)

Help?
@loleris :weary:

You should have replied to the post ProfileService have you tried testing in-studio?to see where the problem occurs?

my bad


Thats the output in studio

Can you pinpoint n copy and paste the line 10 in "Script" / or just click the error

It’s simply just printing the players new cash

	Products = { -- developer_product_id = function(profile)
		[1203567724] = function(profile)
			profile.Data.Cash += 10
			print(profile.Data.Cash)
		end,
		[1203567938] = function(profile)
			profile.Data.Cash += 100
			print(profile.Data.Cash)	
		end,
	},

Are you referring to this?

	print(profile.Data.Cash)

Yes that is line 10 and 14, both do the same thing by printing the players cash

Have you made any edits to the code besides just adding those prints? Have you tried just removing them?

Also do you have ProfileService within ServerScriptService ?(The Latest version)

No, I’ve been experieicning this issue in my actual game (it was working the other day) so ive made a fresh baseplate and stole the code from the website and that errors.

:+1:

Do you have any other scripts handling Developer products?

No, only these scripts are in the game. (Excluding the script to prompt dev product purchase)

What do you mean by

more than one?

Is there any script that has this line within it it could be the source of your problem…

MarketPlace.ProcessReceipt = 

No, the profileservice module and the actual script I sent in the original post, should’ve made myself clearer.

I’m also getting this error if products are purchased too fast, have you found a solution?

Hey, this output still gets posted from time to time in my game however it never causes any actual issues. Don’t worry about it, everything should still work as expected.

Ok thank you. I just wrote a message to @loleris to let him know abt it.