MarketplaceService

Show Deprecated
Not Creatable
Service

MarketplaceService is responsible for in-experience transactions. The most notable methods are PromptProductPurchase and PromptPurchase, as well as the callback ProcessReceipt which must be defined so that transactions do not fail.

MarketplaceService also has methods that fetch information about developer products (GetProductInfo and GetDeveloperProductsAsync), game passes (UserOwnsGamePassAsync), and other assets (PlayerOwnsAsset, PlayerOwnsBundle).

Understanding MarketplaceService is the first step towards learning to monetize an experience on Roblox, as well as DataStoreService which is responsible for saving and loading data related to purchases.

Summary

Properties

Events

ClientPurchaseSuccess(ticket: string, playerId: number, productId: number): RBXScriptSignal  


NativePurchaseFinished(player: Instance, productId: string, wasPurchased: boolean): RBXScriptSignal  


PromptBundlePurchaseFinished(player: Instance, bundleId: number, wasPurchased: boolean): RBXScriptSignal  


PromptGamePassPurchaseFinished(player: Instance, gamePassId: number, wasPurchased: boolean): RBXScriptSignal  

Fires when a purchase prompt closes for a game pass.


Fires when the Premium purchase modal closes.

PromptProductPurchaseRequested(player: Instance, productId: number, equipIfPurchased: boolean, currencyType: CurrencyType): RBXScriptSignal  


PromptPurchaseFinished(player: Instance, assetId: number, isPurchased: boolean): RBXScriptSignal  

Fires when a purchase prompt closes for an affiliate gear sale or other asset (does not fire for developer product or game pass prompts).

PromptPurchaseRequested(player: Instance, assetId: number, equipIfPurchased: boolean, currencyType: CurrencyType): RBXScriptSignal  


PromptSubscriptionPurchaseFinished(player: Instance, subscriptionId: number, wasPurchased: boolean): RBXScriptSignal  


ThirdPartyPurchaseFinished(player: Instance, productId: string, receipt: string, wasPurchased: boolean): RBXScriptSignal  

Fires when a third-party purchase has been completed.

Methods

PromptBundlePurchase(player: Instance, bundleId: number): void  

Used to prompt a user to purchase a bundle with the given bundleId.

PromptGamePassPurchase(player: Instance, gamePassId: number): void  

Used to prompt a user to purchase a game pass with the given assetId.

PromptNativePurchase(player: Instance, productId: string): void  


PromptPremiumPurchase(player: Instance): void  

Used to prompt a user to purchase Premium.

PromptProductPurchase(player: Instance, productId: number, equipIfPurchased: boolean, currencyType: CurrencyType): void  

Used to prompt a user to purchase a product with the given product id.

PromptPurchase(player: Instance, assetId: number, equipIfPurchased: boolean, currencyType: CurrencyType): void  

Used to prompt a user to purchase an item with the given assetId.

PromptRobloxPurchase(assetId: number, equipIfPurchased: boolean): void  


PromptSubscriptionCancellation(player: Instance, subscriptionId: number): void  


PromptSubscriptionPurchase(player: Instance, subscriptionId: number): void  


PromptThirdPartyPurchase(player: Instance, productId: string): void  

Prompts a third-party purchase.

ReportAssetSale(assetId: string, robuxAmount: number): void  


SignalAssetTypePurchased(player: Instance, assetType: AssetType): void  


SignalClientPurchaseSuccess(ticket: string, playerId: number, productId: number): void  


SignalPromptBundlePurchaseFinished(player: Instance, bundleId: number, success: boolean): void  


SignalPromptGamePassPurchaseFinished(player: Instance, gamePassId: number, success: boolean): void  


SignalPromptPremiumPurchaseFinished(didTryPurchasing: boolean): void  


SignalPromptProductPurchaseFinished(userId: number, productId: number, success: boolean): void  


SignalPromptPurchaseFinished(player: Instance, assetId: number, success: boolean): void  


SignalPromptSubscriptionCancellationFinished(player: Instance, subscriptionId: number, wasCanceled: boolean): void  


SignalPromptSubscriptionPurchaseFinished(player: Instance, subscriptionId: number, wasPurchased: boolean): void  



Returns a Pages object which contains information for all of the current game's developer products.

GetProductInfo(assetId: number, infoType: InfoType): table  YIELDS

Returns the product information of an asset using its assetId.

GetRobuxBalance(): number  YIELDS


IsPlayerSubscribed(player: Instance, subscriptionId: number): boolean  YIELDS


PerformPurchase(infoType: InfoType, productId: number, expectedPrice: number, requestId: string, isRobloxPurchase: boolean): table  YIELDS


PlayerOwnsAsset(player: Instance, assetId: number): boolean  YIELDS

Returns whether the given player has the given asset.

PlayerOwnsBundle(player: Player, bundleId: number): boolean  YIELDS

Returns whether the given player owns the given bundle.

UserOwnsGamePassAsync(userId: number, gamePassId: number): boolean  YIELDS

Returns true if the player with the given UserId owns the game pass with the given game pass ID.

Callbacks

ProcessReceipt(receiptInfo: table)  

Properties

Events

ClientLuaDialogRequested

Roblox Script Security

Parameters

arguments: Tuple

ClientPurchaseSuccess

Roblox Script Security

Parameters

ticket: string
playerId: number
productId: number

NativePurchaseFinished

Roblox Script Security

Parameters

player: Instance
productId: string
wasPurchased: boolean

NativePurchaseFinishedWithLocalPlayer

Roblox Script Security

Parameters

productId: string
wasPurchased: boolean

PromptBundlePurchaseFinished

Parameters

player: Instance
bundleId: number
wasPurchased: boolean

PromptBundlePurchaseRequested

Roblox Script Security

Parameters

player: Instance
bundleId: number

PromptGamePassPurchaseFinished

This event fires when a purchase dialog of a game pass is closed. This fires right as the dialog closes when the player presses "Cancel" at the prompt, or "OK" at the success/error message.

Parameters

player: Instance

The Player object for whom the prompt was shown.

gamePassId: number

The ID number of the game pass shown in the prompt (not to be confused with an asset ID).

wasPurchased: boolean

Whether the item was successfully purchased (false for errors and cancellations).


Code Samples

Handling Gamepass Purchase Finished

1local MarketplaceService = game:GetService("MarketplaceService")
2
3local function gamepassPurchaseFinished(...)
4 -- Print all the details of the prompt, for example:
5 -- PromptGamePassPurchaseFinished PlayerName 123456 false
6 print("PromptGamePassPurchaseFinished", ...)
7end
8
9MarketplaceService.PromptGamePassPurchaseFinished:Connect(gamepassPurchaseFinished)

PromptGamePassPurchaseRequested

Roblox Script Security

Parameters

player: Instance
gamePassId: number

PromptPremiumPurchaseFinished

This event fires when the Premium purchase modal closes, specifically when the player presses "Cancel" at the prompt, "OK" at the error message, or after the payment UI closes.

To learn more about and incorporating Premium into your game, and monetizing your game with the Premium Payouts system, see Premium Payouts.

See also:


PromptPremiumPurchaseRequested

Roblox Script Security

Parameters

player: Instance

PromptProductPurchaseRequested

Roblox Script Security

Parameters

player: Instance
productId: number
equipIfPurchased: boolean
currencyType: CurrencyType

PromptPurchaseFinished

For new game passes using a Game Pass ID, use MarketplaceService.PromptGamePassPurchaseFinished

PromptPurchaseFinished fires when a purchase dialog of an affiliate gear sale or other asset is closed. This fires right as the dialog closes when the player presses "Cancel" at the prompt, or "OK" at the success/error message.

Parameters

player: Instance

The Player object for whom the prompt was shown.

assetId: number

The asset ID number of the item shown in the prompt.

isPurchased: boolean

Whether the item was successfully purchased (false for errors and cancellations).


Code Samples

Handling PromptPurchaseFinished Event

1local MarketplaceService = game:GetService("MarketplaceService")
2
3local function onPromptPurchaseFinished(player, assetId, isPurchased)
4 if isPurchased then
5 print(player.Name, "bought an item with AssetID:", assetId)
6 else
7 print(player.Name, "didn't buy an item with AssetID:", assetId)
8 end
9end
10
11MarketplaceService.PromptPurchaseFinished:Connect(onPromptPurchaseFinished)

PromptPurchaseRequested

Roblox Script Security

Parameters

player: Instance
assetId: number
equipIfPurchased: boolean
currencyType: CurrencyType

PromptRobloxPurchaseRequested

Roblox Script Security

Parameters

assetId: number
equipIfPurchased: boolean

PromptSubscriptionCancellationFinished

Parameters

player: Instance
subscriptionId: number
wasCanceled: boolean

PromptSubscriptionCancellationRequested

Roblox Script Security

Parameters

player: Instance
subscriptionId: number

PromptSubscriptionPurchaseFinished

Parameters

player: Instance
subscriptionId: number
wasPurchased: boolean

PromptSubscriptionPurchaseRequested

Roblox Script Security

Parameters

player: Instance
subscriptionId: number

ServerPurchaseVerification

Roblox Script Security

Parameters

serverResponseTable: table

ThirdPartyPurchaseFinished

Local User Security

Fires when a third-party purchase has been completed.

Parameters

player: Instance
productId: string
receipt: string
wasPurchased: boolean

Methods

PlayerCanMakePurchases

Roblox Script Security

Parameters

player: Instance

Returns

PromptBundlePurchase

void

Used to prompt a user to purchase a bundle with the given bundleId

Parameters

player: Instance
bundleId: number

Returns

void

PromptGamePassPurchase

void

Used to prompt a user to purchase a game pass with the given assetId.

Parameters

player: Instance
gamePassId: number

Returns

void

PromptNativePurchase

void
Roblox Script Security

Parameters

player: Instance
productId: string

Returns

void

PromptNativePurchaseWithLocalPlayer

void
Roblox Script Security

Parameters

productId: string

Returns

void

PromptPremiumPurchase

void

Used to prompt a user to purchase Premium. If the user is already premium, the user will receive an error message "You are already subscribed to Roblox Premium! Please try again."

To learn more about and incorporating Premium into your game, and monetizing your game with the Premium Payout system, see Premium Payouts.

See also:

Parameters

player: Instance

The player being prompted to purchase premium.


Returns

void

No return.

Code Samples

Prompt Premium Purchase

1local MarketplaceService = game:GetService("MarketplaceService")
2local TeleportService = game:GetService("TeleportService")
3local Players = game:GetService("Players")
4
5local teleporter = script.Parent
6local showPrompt = true
7
8local PREMIUM_PLACE_ID = 012345678
9
10local function onTeleporterTouch(otherPart)
11 local player = Players:GetPlayerFromCharacter(otherPart.Parent)
12 if not player then
13 return
14 end
15
16 -- If the user already has Premium, teleport them to the Premium-only place
17 if player.MembershipType == Enum.MembershipType.Premium then
18 TeleportService:TeleportAsync(PREMIUM_PLACE_ID, { player })
19 -- Else, prompt Premium upgrade (use debounce to show it only once every few seconds)
20 else
21 if showPrompt == false then
22 return
23 end
24 showPrompt = false
25 task.delay(5, function()
26 showPrompt = true
27 end)
28 MarketplaceService:PromptPremiumPurchase(player)
29 warn("Prompted Premium purchase")
30 end
31end
32teleporter.Touched:Connect(onTeleporterTouch)
33
34-- If needed, use this event to know when the Premium modal is closed
35local function onPromptFinished(player)
36 warn("Premium modal closed by", player)
37end
38
39MarketplaceService.PromptPremiumPurchaseFinished:Connect(onPromptFinished)
40
41-- Handle potential Premium purchase from outside the game while user is playing
42local function onMembershipChanged(player)
43 warn("Player membership changed; new membership is " .. tostring(player.MembershipType))
44 if player.MembershipType == Enum.MembershipType.Premium then
45 -- Teleport player to the Premium-only place
46 TeleportService:TeleportAsync(PREMIUM_PLACE_ID, { player })
47 end
48end
49Players.PlayerMembershipChanged:Connect(onMembershipChanged)

PromptProductPurchase

void

Used to prompt a user to purchase a product with the given product id.

Parameters

player: Instance
productId: number
equipIfPurchased: boolean
Default Value: "true"
currencyType: CurrencyType
Default Value: "Default"

Returns

void

Code Samples

MarketplaceService:PromptProductPurchase

1local MarketplaceService = game:GetService("MarketplaceService")
2local Players = game:GetService("Players")
3
4local PRODUCT_ID = 123456
5
6Players.PlayerAdded:Connect(function(player)
7 MarketplaceService:PromptProductPurchase(player, PRODUCT_ID)
8end)

PromptPurchase

void

PromptPurchase is used to prompt a player to purchase an item with the given assetId.

Parameters

player: Instance
assetId: number
equipIfPurchased: boolean
Default Value: "true"
currencyType: CurrencyType

Ignored.

Default Value: "Default"

Returns

void

Code Samples

Script (Server)

1local ReplicatedStorage = game:GetService("ReplicatedStorage")
2local MarketplaceService = game:GetService("MarketplaceService")
3
4local promptPurchaseEvent = Instance.new("RemoteEvent")
5promptPurchaseEvent.Name = "PromptPurchaseEvent"
6promptPurchaseEvent.Parent = ReplicatedStorage
7
8-- Listen for the RemoteEvent to fire from a Client and then trigger the purchase prompt
9promptPurchaseEvent.OnServerEvent:Connect(function(player, id)
10 MarketplaceService:PromptPurchase(player, id)
11end)
LocalScript (Client)

1local ReplicatedStorage = game:GetService("ReplicatedStorage")
2
3local promptPurchaseEvent = ReplicatedStorage:WaitForChild("PromptPurchaseEvent")
4
5local part = Instance.new("Part")
6part.Parent = workspace
7
8local clickDetector = Instance.new("ClickDetector")
9clickDetector.Parent = part
10
11clickDetector.MouseClick:Connect(function()
12 promptPurchaseEvent:FireServer(16630147)
13end)

PromptRobloxPurchase

void
Roblox Script Security

Parameters

assetId: number
equipIfPurchased: boolean

Returns

void

PromptSubscriptionCancellation

void

Parameters

player: Instance
subscriptionId: number

Returns

void

PromptSubscriptionPurchase

void

Parameters

player: Instance
subscriptionId: number

Returns

void

PromptThirdPartyPurchase

void
Local User Security

Prompts a third-party purchase.

Parameters

player: Instance
productId: string

Returns

void

ReportAssetSale

void
Roblox Script Security

Parameters

assetId: string
robuxAmount: number

Returns

void

ReportRobuxUpsellStarted

void
Roblox Script Security

Returns

void

SignalAssetTypePurchased

void
Roblox Script Security

Parameters

player: Instance
assetType: AssetType

Returns

void

SignalClientPurchaseSuccess

void
Roblox Script Security

Parameters

ticket: string
playerId: number
productId: number

Returns

void

SignalMockPurchasePremium

void
Roblox Script Security

Returns

void

SignalPromptBundlePurchaseFinished

void
Roblox Script Security

Parameters

player: Instance
bundleId: number
success: boolean

Returns

void

SignalPromptGamePassPurchaseFinished

void
Roblox Script Security

Parameters

player: Instance
gamePassId: number
success: boolean

Returns

void

SignalPromptPremiumPurchaseFinished

void
Roblox Script Security

Parameters

didTryPurchasing: boolean

Returns

void

SignalPromptProductPurchaseFinished

void
Roblox Script Security

Parameters

userId: number
productId: number
success: boolean

Returns

void

SignalPromptPurchaseFinished

void
Roblox Script Security

Parameters

player: Instance
assetId: number
success: boolean

Returns

void

SignalPromptSubscriptionCancellationFinished

void
Roblox Script Security

Parameters

player: Instance
subscriptionId: number
wasCanceled: boolean

Returns

void

SignalPromptSubscriptionPurchaseFinished

void
Roblox Script Security

Parameters

player: Instance
subscriptionId: number
wasPurchased: boolean

Returns

void

SignalServerLuaDialogClosed

void
Roblox Script Security

Parameters

value: boolean

Returns

void

GetDeveloperProductsAsync

Yields

Returns a Pages object which contains information for all of the current game's developer products.


Returns

Code Samples

MarketplaceService:GetDeveloperProductsAsync

1local MarketplaceService = game:GetService("MarketplaceService")
2
3local developerProducts = MarketplaceService:GetDeveloperProductsAsync():GetCurrentPage()
4
5for _, developerProduct in pairs(developerProducts) do
6 for field, value in pairs(developerProduct) do
7 print(field .. ": " .. value)
8 end
9 print(" ")
10end

GetProductInfo

Yields

This function provides information about an asset, developer product or game pass given its assetId and the InfoType (Asset, Product or GamePass respectively).

Information about the queried item is provided in a dictionary with the following keys. Note that not all information is provided or necessarily relevant for the kind of object you are querying.

NameTypeDescription
NamestringThe name shown on the asset's page.
DescriptionstringThe description as shown on the asset's page; can be nil if blank.
PriceInRobuxnumberThe cost of purchasing the asset using Robux.
CreatedtimestampTimestamp of when the asset was created, e.g. 2018-08-01T17:55:11.98Z.
UpdatedtimestampTimestamp of when the asset was last updated by its creator, e.g. 2018-08-01T17:55:11.98Z.
ContentRatingTypeIdnumberIndicates whether the item is marked as 13+ in catalog.
MinimumMembershipLevelnumberThe minimum subscription level necessary to purchase the item.
IsPublicDomainbooleanDescribes whether the asset can be taken for free.
Creator Information
CreatorDictionaryA table of information describing the creator of the asset (see following lines).
Creator.CreatorTypestringEither User or Group.
Creator.CreatorTargetIdnumberThe ID of the creator user or group.
Creator.HasVerifiedBadgebooleanWhether the creator has a verified badge.
Creator.NamestringThe name/username of the creator.
Creator.Idnumber(Use CreatorTargetId instead).
Assets
AssetIdnumberIf InfoType was Asset, this is the ID of the given asset.
AssetTypeIdnumberThe type of asset (e.g. place, model, shirt)*.
IsForSalebooleanDescribes whether the asset is purchasable.
IsLimitedbooleanDescribes whether the asset is a "limited item" that is no longer (if ever) sold.
IsLimitedUniquebooleanDescribes whether the asset is a "limited unique" ("Limited U") item that only has a fixed number sold.
IsNewbooleanDescribes whether the asset is marked as "new" in the catalog.
RemainingnumberThe remaining number of items a limited unique item may be sold.
SalesnumberThe number of items the asset has been sold.
SaleAvailabilityLocationsDictionaryThe item's `Enum.ProductLocationRestriction|ProductLocationRestriction` or sale location setting (e.g. anywhere, Shop only).
CanBeSoldInThisGamebooleanDescribes whether the asset is purchasable in the current experience.
Developer Products and Game Passes
ProductIdnumberIf the InfoType was Product, this is the product ID.
IconImageAssetIdnumberThis is the asset ID of the product/pass icon, or 0 if there isn't one.

* See AssetType for the asset type ID numbers. †Timestamps are formatted using ISO 8601

Possible Errors

If no such item exists with the given ID, this function will throw an error:

  • For developer products, the error is:

MarketplaceService:getProductInfo() failed because rawProductInfo was empty

  • For game passes and assets, the error is:

MarketplaceService:getProductInfo() failed because HTTP 0 (HTTP 400 (HTTP/1.1 400 BadRequest))

Parameters

assetId: number

The assetId of the specified product.

infoType: InfoType

An InfoType enum value specifying the type of information being retrieved.

Default Value: "Asset"

Returns

A dictionary containing information about the queried item (described in the table above). Note that not all information is provided or necessarily relevant for the kind of object you are querying.

Code Samples

Getting Product Info

1local MarketplaceService = game:GetService("MarketplaceService")
2
3local ASSET_ID = 125378389
4
5local asset = MarketplaceService:GetProductInfo(ASSET_ID)
6print(asset.Name .. " :: " .. asset.Description)

GetRobuxBalance

Yields
Roblox Script Security

Returns

IsPlayerSubscribed

Yields

Parameters

player: Instance
subscriptionId: number

Returns

PerformPurchase

Yields
Roblox Script Security

Parameters

infoType: InfoType
productId: number
expectedPrice: number
requestId: string
isRobloxPurchase: boolean

Returns

PlayerOwnsAsset

Yields

Returns whether the inventory of given Player contains an asset, given the ID. This method can query for hats, models, sounds, etc. This function takes a small amount of time to send a request the Roblox website.

In the case that a query fails, this function will throw an error. Therefore, it is recommended to wrap calls to this function in pcall.

  • This method should not be used for game passes, since they use a separate ID system. Legacy game passes that still depend on an asset ID should use MarketplaceService:UserOwnsGamePassAsync() instead of this method.
  • This method cannot be used to check for developer products since they can be purchased multiple times but not owned themselves. Use a GlobalDataStore to save when a player has bought a developer product instead.

Parameters

player: Instance

A Player object whose inventory shall be tested for the ownership of the given asset.

assetId: number

The ID of an asset for which the given player's inventory shall be tested.


Returns

Indicates whether the given Player's inventory contains the given asset.

Code Samples

Check for Item Ownership

1local Players = game:GetService("Players")
2local MarketplaceService = game:GetService("MarketplaceService")
3
4-- The item we're checking for: https://www.roblox.com/catalog/30331986/Midnight-Shades
5local ASSET_ID = 30331986
6local ASSET_NAME = "Midnight Shades"
7
8local function onPlayerAdded(player)
9 local _success, doesPlayerOwnAsset = pcall(MarketplaceService.PlayerOwnsAsset, MarketplaceService, player, ASSET_ID)
10 if doesPlayerOwnAsset then
11 print(player.Name .. " owns " .. ASSET_NAME)
12 else
13 print(player.Name .. " doesn't own " .. ASSET_NAME)
14 end
15end
16
17Players.PlayerAdded:Connect(onPlayerAdded)

PlayerOwnsBundle

Yields

Returns whether the inventory of given Player contains a bundle, given the ID. This function takes a small amount of time to send a request to the Roblox website.

In the case that a query fails, this function throws an error. Therefore, it is recommended to wrap calls to this function in pcall.

Parameters

player: Player

A Player object whose inventory shall be tested for the ownership of the given bundle.

bundleId: number

The ID of a bundle for which the given player's inventory shall be tested.


Returns

Indicates whether the given Player's inventory contains the given bundle.

Code Samples

Check for Bundle Ownership

1local Players = game:GetService("Players")
2local MarketplaceService = game:GetService("MarketplaceService")
3
4-- The bundle we're checking for: https://www.roblox.com/bundles/589/Junkbot
5local BUNDLE_ID = 589
6local BUNDLE_NAME = "Junkbot"
7
8Players.PlayerAdded:Connect(function (player)
9 local success, doesPlayerOwnBundle = pcall(function()
10 return MarketplaceService:PlayerOwnsBundle(player, BUNDLE_ID)
11 end)
12
13 if success == false then
14 print("PlayerOwnsBundle call failed: ", doesPlayerOwnBundle)
15 return
16 end
17
18 if doesPlayerOwnBundle then
19 print(player.Name .. " owns " .. BUNDLE_NAME)
20 else
21 print(player.Name .. " doesn't own " .. BUNDLE_NAME)
22 end
23end)

UserOwnsGamePassAsync

Yields

UserOwnsGamePassAsync returns true if the Player with the given UserId owns the game pass with the given game pass ID (not to be confused with asset ID).

Caching Behavior

Results of this function are remembered so that repeated calls will return quicker. This function will always return true if the player owns the game pass upon first entering a server after having purchased the game pass. If the game pass is purchased in-game (through PromptGamePassPurchase), this function may return false due to the caching behavior. Conversely, should the player delete the game pass from their inventory, this function may return true despite the player not owning the game pass.

Parameters

userId: number

The UserId of the Player whose inventory shall be queried.

gamePassId: number

The game pass ID of the game pass to be checked, not to be confused with asset ID.


Returns

Callbacks

Parameters

receiptInfo: table

Code Samples

ProcessReceipt Callback

1local MarketplaceService = game:GetService("MarketplaceService")
2local DataStoreService = game:GetService("DataStoreService")
3local Players = game:GetService("Players")
4
5-- Data store for tracking purchases that were successfully processed
6local purchaseHistoryStore = DataStoreService:GetDataStore("PurchaseHistory")
7
8-- Table setup containing product IDs and functions for handling purchases
9local productFunctions = {}
10-- ProductId 123123 for a full heal
11productFunctions[123123] = function(_receipt, player)
12 -- Logic/code for player buying a full heal (may vary)
13 if player.Character and player.Character:FindFirstChild("Humanoid") then
14 -- Heal the player to full health
15 player.Character.Humanoid.Health = player.Character.Humanoid.MaxHealth
16 -- Indicate a successful purchase
17 return true
18 end
19end
20-- ProductId 456456 for 100 gold
21productFunctions[456456] = function(_receipt, player)
22 -- Logic/code for player buying 100 gold (may vary)
23 local stats = player:FindFirstChild("leaderstats")
24 local gold = stats and stats:FindFirstChild("Gold")
25 if gold then
26 gold.Value = gold.Value + 100
27 -- Indicate a successful purchase
28 return true
29 end
30end
31
32-- The core 'ProcessReceipt' callback function
33local function processReceipt(receiptInfo)
34 -- Determine if the product was already granted by checking the data store
35 local playerProductKey = receiptInfo.PlayerId .. "_" .. receiptInfo.PurchaseId
36 local purchased = false
37 local success, result, errorMessage
38
39 success, errorMessage = pcall(function()
40 purchased = purchaseHistoryStore:GetAsync(playerProductKey)
41 end)
42 -- If purchase was recorded, the product was already granted
43 if success and purchased then
44 return Enum.ProductPurchaseDecision.PurchaseGranted
45 elseif not success then
46 error("Data store error:" .. errorMessage)
47 end
48
49 -- Determine if the product was already granted by checking the data store
50 local playerProductKey = receiptInfo.PlayerId .. "_" .. receiptInfo.PurchaseId
51
52 local success, isPurchaseRecorded = pcall(function()
53 return purchaseHistoryStore:UpdateAsync(playerProductKey, function(alreadyPurchased)
54 if alreadyPurchased then
55 return true
56 end
57
58 -- Find the player who made the purchase in the server
59 local player = Players:GetPlayerByUserId(receiptInfo.PlayerId)
60 if not player then
61 -- The player probably left the game
62 -- If they come back, the callback will be called again
63 return nil
64 end
65
66 local handler = productFunctions[receiptInfo.ProductId]
67
68 local success, result = pcall(handler, receiptInfo, player)
69 -- If granting the product failed, do NOT record the purchase in datastores.
70 if not success or not result then
71 error("Failed to process a product purchase for ProductId: " .. tostring(receiptInfo.ProductId) .. " Player: " .. tostring(player) .. " Error: " .. tostring(result))
72 return nil
73 end
74
75 -- Record the transcation in purchaseHistoryStore.
76 return true
77 end)
78 end)
79
80 if not success then
81 error("Failed to process receipt due to data store error.")
82 return Enum.ProductPurchaseDecision.NotProcessedYet
83 elseif isPurchaseRecorded == nil then
84 -- Didn't update the value in data store.
85 return Enum.ProductPurchaseDecision.NotProcessedYet
86 else
87 -- IMPORTANT: Tell Roblox that the game successfully handled the purchase
88 return Enum.ProductPurchaseDecision.PurchaseGranted
89 end
90end
91
92-- Set the callback; this can only be done once by one script on the server!
93MarketplaceService.ProcessReceipt = processReceipt
94