We use cookies on this site to enhance your user experience

ProcessReceipt Callback Example

ProcessReceipt Callback Example

This code sample sets the MarketplaceService/ProcessReceipt callback so the game can handle purchasing two products: one that heals the player to full health and the other that grants 100 Gold (a hypothetical Articles/Leaderboards|leaderstat). It properly checks for and records purchases using a GlobalDataStore|data store called “PurchaseHistory”. Most importantly, it properly returns Enum.ProductPurchaseDecision.PurchaseGranted upon successfully completing a transaction or detecting that it has already been granted using the “PurchaseHistory” data store. It is important to take note of the 5 distinct steps in processing a transaction.

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

-- A data store for tracking purchases that were successfully processed
local PurchaseHistory = DataStoreService:GetDataStore("PurchaseHistory")

-- These are our product ID numbers given by the configure game products page
-- For this example, these products will heal the player to full health, and
-- give the player 100 gold.
local PRODUCT_ID_FULL_HEAL = 123123
local PRODUCT_ID_GOLD = 456456
local GOLD_AWARD = 100 -- How much gold the product gives

local function processReceipt(receiptInfo)
	-- Step 1: Check if the product was already granted by using a data store  
	local playerProductKey = receiptInfo.PlayerId .. ":" .. receiptInfo.PurchaseId
	if PurchaseHistory:GetAsync(playerProductKey) then
		-- If we recorded the purchase, then the product was already granted
		return Enum.ProductPurchaseDecision.PurchaseGranted
	end
	
	-- Step 2: Find the player who made the purchase in the server
	local player = game:GetService("Players"):GetPlayerByUserId(receiptInfo.PlayerId)
	if not player then
		-- The player left the game, probably.
		-- If they come back, the callback will be called again so we can try again
		return Enum.ProductPurchaseDecision.NotProcessedYet
	end
	
	-- Step 3: Find out what product they bought!
	if receiptInfo.ProductId == PRODUCT_ID_FULL_HEAL then
		if player.Character and player.Character:FindFirstChild("Humanoid") then
			-- Heal the player to full health!
			player.Character.Humanoid.Health = player.Character.Humanoid.MaxHealth
		else
			-- We can't heal a player without a character!
			return Enum.ProductPurchaseDecision.NotProcessedYet
		end
	elseif receiptInfo.ProductId == PRODUCT_ID_GOLD then
		-- Assuming the presence of a "Gold" leaderstat, increment by GOLD_AWARD
		player.leaderstats.Gold.Value = player.leaderstats.Gold.Value + GOLD_AWARD
	else
		-- We don't know what product they bought!
	end
	
	-- Step 4: Record the transaction in our data store so it isn't granted again
	PurchaseHistory:SetAsync(playerProductKey, true)
	
	-- Step 5: Tell Roblox that the game successfully handled the transaction (required)
	return Enum.ProductPurchaseDecision.PurchaseGranted
end

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