Money increasing exponentially problem?

So I have this dev product where if you buy it you should get the amount it mentions, but for some reason when you buy it several times, it starts to give you extra money exponentially, how do I fix such an issue?

Script (not local) in ServerScriptService:

local replicatedStorage = game:GetService("ReplicatedStorage")
local marketService = game:GetService("MarketplaceService")

local remote = replicatedStorage:WaitForChild("RequestPurchaseKoinDevProduct")

local validAmountTypes: {[string]: number} = { -- DevProduct ID's go in here
	["250"] = 1301207378,
	["500"] = 1301207626,
	["1000"] = 1301207729,
	["2000"] = 1301207840,
	["4000"] = 1301207965,
	["8000"] = 1301208082,
	["16000"] = 1301208232,
	["32000"] = 1301208373,
	["50000"] = 1301208531,
	["100000"] = 1301208605
}

local productFunctions: {[string]: () -> (boolean)} = {}

remote.OnServerEvent:Connect(function(plr: Player, amountType: string)
	if typeof(amountType) == "string" and validAmountTypes[amountType] ~= 0 then
		marketService:PromptProductPurchase(plr, validAmountTypes[amountType])
	end
end)

--[[
for str: string, id: number in validAmountTypes do
	productFunctions[str] = function(): boolean
		
	end
end

--
local function processReceipt(receiptInfo: {[string]: any})
	-- 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:", receiptInfo.ProductId, " Player:", player)
				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]]

marketService.ProcessReceipt = function(receiptInfo: {[string]: any})
	if Enum.ProductPurchaseDecision.PurchaseGranted and receiptInfo.PlayerId then
		local plr: Player? do
			for _, v: Player in game:GetService("Players"):GetPlayers() do
				if v.UserId == receiptInfo.PlayerId then
					plr = v
					break
				end
			end
		end
		
		local product: string? do
			for str: string, id: number in validAmountTypes do
				if id == receiptInfo.ProductId then
					product = str
				end
			end
		end
		
		if plr and product and tonumber(product) then
			plr.leaderstats.Koins.Value += tonumber(product)
		end
	end
end

And inside the ScrollingFrame of the GUI I have this local script:

local replicatedStorage = game:GetService("ReplicatedStorage")
local players = game:GetService("Players")
local localPlr = players.LocalPlayer

local remote = replicatedStorage:WaitForChild("RequestPurchaseKoinDevProduct")

local scrollFrame = script.Parent

for _, v in scrollFrame:GetChildren() do
	if v:IsA("Frame") then
		local amountType = string.split(v.Name, "Koins")[1]
		
		local button = v:FindFirstChild("TextButton")
		if button and button:IsA("TextButton") then
			button.MouseButton1Click:Connect(function()
				remote:FireServer(amountType)
			end)
		end
	end
end

Also this error shows in the first script and I have no idea how to fix it:

No errors show in output either, I don’t know much about marketplaceservice so any help is appreciated!

Most likely it’s how you’re setting up your processReceipt, You tell roblox if the purchase was successful or not by returning the ProductPurchaseDecision, in your code you don’t do that, so it takes it that the purchase was unsuccessful, thus when you do a purchase again, it tries to do the failed purchase again and thus causing it to give more than you told it to give. Not sure why you used it in an if statement, all that does is always give true because it’s not nil nor false

You have the processReceipt function roblox uses on the developer wiki, I think you can use that instead (with some changing around to suit your needs), the important thing is that you tell it if the purchase was granted or not via returning with the Enum

3 Likes

You didn’t return Enum.ProductPurchaseDecision.PurchaseGranted once the purchase is done

also, you don’t need to put it in the if statement up there

you’re supposed to use this enum to tell the MarketplaceService callback that player has been granted their reward/benefit, not use it on checking, etc

2 Likes