MarketplaceService

Visualizza obsoleti
Non costruibile
Assistenza

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 developer product transactions do not fail.

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

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

Sommario

Metodi

Eventi

Richiami

Proprietà

Metodi

GetDeveloperProductsAsync

Resa

Restituzioni

Campioni di codice

MarketplaceService:GetDeveloperProductsAsync

local MarketplaceService = game:GetService("MarketplaceService")
local developerProducts = MarketplaceService:GetDeveloperProductsAsync():GetCurrentPage()
for _, developerProduct in pairs(developerProducts) do
for field, value in pairs(developerProduct) do
print(field .. ": " .. value)
end
print(" ")
end

GetProductInfo

Resa

Parametri

assetId: number
infoType: Enum.InfoType
Valore predefinito: "Asset"

Restituzioni

Campioni di codice

Getting Product Info

local MarketplaceService = game:GetService("MarketplaceService")
local ASSET_ID = 125378389
local asset = MarketplaceService:GetProductInfo(ASSET_ID)
print(asset.Name .. " :: " .. asset.Description)

GetSubscriptionProductInfoAsync

Resa

Parametri

subscriptionId: string

Restituzioni

GetUserSubscriptionDetailsAsync

Resa

Parametri

user: Player
subscriptionId: string

Restituzioni

GetUserSubscriptionPaymentHistoryAsync

Resa

Parametri

user: Player
subscriptionId: string

Restituzioni

Campioni di codice

MarketplaceService:GetUserSubscriptionPaymentHistoryAsync

local MarketplaceService = game:GetService("MarketplaceService")
local Players = game:GetService("Players")
local SUBSCRIPTION_ID = "EXP-0"
local function checkSubscriptionHistory(player: Player)
local subscriptionHistory = {}
local success, err = pcall(function()
subscriptionHistory = MarketplaceService:GetUserSubscriptionPaymentHistoryAsync(player, SUBSCRIPTION_ID)
end)
if not success then
warn(`Error while checking subscription history: {err}`)
return
end
if next(subscriptionHistory) then
-- User has some subscription history within the past 12 months.
-- Print the details of each payment entry from the subscription history.
print(`Player {player.Name} has subscribed to {SUBSCRIPTION_ID} before:`)
for entryNum, paymentEntry in subscriptionHistory do
local paymentStatus = tostring(paymentEntry.PaymentStatus)
local cycleStartTime = paymentEntry.CycleStartTime:FormatLocalTime("LLL", "en-us")
local cycleEndTime = paymentEntry.CycleEndTime:FormatLocalTime("LLL", "en-us")
print(`{entryNum}: {paymentStatus} ({cycleStartTime} - {cycleEndTime})`)
end
else
print(`Player {player.Name} has never subscribed to {SUBSCRIPTION_ID} before.`)
end
end
-- Call checkSubscriptionHistory for any players already in the game
for _, player in ipairs(Players:GetPlayers()) do
checkSubscriptionHistory(player)
end
-- Call checkSubscriptionHistory for all future players
Players.PlayerAdded:Connect(checkSubscriptionHistory)

GetUserSubscriptionStatusAsync

Resa

Parametri

user: Player
subscriptionId: string

Restituzioni

Campioni di codice

Check User Subscription Status

local MarketplaceService = game:GetService("MarketplaceService")
local Players = game:GetService("Players")
local subscriptionID = "EXP-00000"
local function checkSubStatus(player)
local subStatus = {}
local success, message = pcall(function()
-- returns IsRenewing and IsSubscribed
subStatus = MarketplaceService:GetUserSubscriptionStatusAsync(player, subscriptionID)
end)
if not success then
warn("Error while checking if player has subscription: " .. tostring(message))
return
end
if subStatus["IsSubscribed"] then
print(player.Name .. " is subscribed with " .. subscriptionID)
-- Give player permissions associated with the subscription
end
end
Players.PlayerAdded:Connect(checkSubStatus)

GetUsersPriceLevelsAsync

Resa

Parametri

userIds: Array

Restituzioni

PlayerOwnsAsset

Resa

Parametri

player: Instance
assetId: number

Restituzioni

Campioni di codice

Check for Item Ownership

local Players = game:GetService("Players")
local MarketplaceService = game:GetService("MarketplaceService")
-- The item we're checking for: https://www.roblox.com/catalog/30331986/Midnight-Shades
local ASSET_ID = 30331986
local ASSET_NAME = "Midnight Shades"
local function onPlayerAdded(player)
local success, doesPlayerOwnAsset = pcall(MarketplaceService.PlayerOwnsAsset, MarketplaceService, player, ASSET_ID)
if not success then
local errorMessage = doesPlayerOwnAsset
warn(`Error checking if {player.Name} owns {ASSET_NAME}: {errorMessage}`)
return
end
if doesPlayerOwnAsset then
print(`{player.Name} owns {ASSET_NAME}`)
else
print(`{player.Name} doesn't own {ASSET_NAME}`)
end
end
Players.PlayerAdded:Connect(onPlayerAdded)

PlayerOwnsBundle

Resa

Parametri

player: Player
bundleId: number

Restituzioni

Campioni di codice

Check for Bundle Ownership

local Players = game:GetService("Players")
local MarketplaceService = game:GetService("MarketplaceService")
-- The bundle we're checking for: https://www.roblox.com/bundles/589/Junkbot
local BUNDLE_ID = 589
local BUNDLE_NAME = "Junkbot"
Players.PlayerAdded:Connect(function(player)
local success, doesPlayerOwnBundle = pcall(function()
return MarketplaceService:PlayerOwnsBundle(player, BUNDLE_ID)
end)
if success == false then
print("PlayerOwnsBundle call failed: ", doesPlayerOwnBundle)
return
end
if doesPlayerOwnBundle then
print(player.Name .. " owns " .. BUNDLE_NAME)
else
print(player.Name .. " doesn't own " .. BUNDLE_NAME)
end
end)

PromptBulkPurchase

()

Parametri

player: Player
lineItems: Array
options: Dictionary

Restituzioni

()

Campioni di codice

Prompt Bulk Purchase Client

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local promptBulkPurchaseEvent = ReplicatedStorage:WaitForChild("PromptBulkPurchaseEvent")
local part = Instance.new("Part")
part.Parent = workspace
local clickDetector = Instance.new("ClickDetector")
clickDetector.Parent = part
clickDetector.MouseClick:Connect(function()
promptBulkPurchaseEvent:FireServer({
{ Type = Enum.MarketplaceProductType.AvatarAsset, Id = "16630147" },
{ Type = Enum.MarketplaceProductType.AvatarBundle, Id = "182" },
})
end)
Prompt Bulk Purchase Server

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local MarketplaceService = game:GetService("MarketplaceService")
local promptBulkPurchaseEvent = Instance.new("RemoteEvent")
promptBulkPurchaseEvent.Name = "PromptBulkPurchaseEvent"
promptBulkPurchaseEvent.Parent = ReplicatedStorage
--Listen for the RemoteEvent to fire from a Client and then trigger the bulk purchase prompt
promptBulkPurchaseEvent.OnServerEvent:Connect(function(player, items)
MarketplaceService:PromptBulkPurchase(player, items, {})
end)

PromptBundlePurchase

()

Parametri

player: Instance
bundleId: number

Restituzioni

()

PromptCancelSubscription

()

Parametri

user: Player
subscriptionId: string

Restituzioni

()

PromptGamePassPurchase

()

Parametri

player: Instance
gamePassId: number

Restituzioni

()

PromptPremiumPurchase

()

Parametri

player: Instance

Restituzioni

()

Campioni di codice

Acquisto premium rapido

local MarketplaceService = game:GetService("MarketplaceService")
local Players = game:GetService("Players")
local teleporter = script.Parent
local showModal = true
local TELEPORT_POSITION = Vector3.new(1200, 200, 60)
-- Teletrasporta il personaggio nell'area esclusiva
local function teleportPlayer(player)
-- Richiesta di streaming intorno alla posizione target
player:RequestStreamAroundAsync(TELEPORT_POSITION)
-- Personaggio di teletrasporto
local character = player.Character
if character and character.Parent then
local currentPivot = character:GetPivot()
character:PivotTo(currentPivot * CFrame.new(TELEPORT_POSITION))
end
end
-- Rileva le parti del personaggio che toccano il teletrasportatore
teleporter.Touched:Connect(function(otherPart)
local player = Players:GetPlayerFromCharacter(otherPart.Parent)
if not player then
return
end
if not player:GetAttribute("CharacterPartsTouching") then
player:SetAttribute("CharacterPartsTouching", 0)
end
player:SetAttribute("CharacterPartsTouching", player:GetAttribute("CharacterPartsTouching") + 1)
if player.MembershipType == Enum.MembershipType.Premium then
-- L'utente ha Premium; teletrasporta il personaggio nell'area esclusiva all'interno dell'esperienza
teleportPlayer(player)
else
-- Mostra la modalità di acquisto, utilizzando debounce per mostrare una volta ogni pochi secondi al massimo
if not showModal then
return
end
showModal = false
task.delay(5, function()
showModal = true
end)
MarketplaceService:PromptPremiumPurchase(player)
end
end)
-- Rileva le parti del personaggio che escono dal teletrasportatore
teleporter.TouchEnded:Connect(function(otherPart)
local player = Players:GetPlayerFromCharacter(otherPart.Parent)
if player and player:GetAttribute("CharacterPartsTouching") then
player:SetAttribute("CharacterPartsTouching", player:GetAttribute("CharacterPartsTouching") - 1)
end
end)
-- Trattare l'evento di modifica della membership
Players.PlayerMembershipChanged:Connect(function(player)
warn("User membership changed; new membership is " .. tostring(player.MembershipType))
-- Teletrasporta il personaggio se il tipo di adesione è Premium e il personaggio è sul teletrasportatore
if player.MembershipType == Enum.MembershipType.Premium and player:GetAttribute("CharacterPartsTouching") > 0 then
teleportPlayer(player)
end
end)

PromptProductPurchase

()

Parametri

player: Instance
productId: number
equipIfPurchased: boolean
Valore predefinito: true
currencyType: Enum.CurrencyType
Valore predefinito: "Default"

Restituzioni

()

Campioni di codice

MarketplaceService:PromptProductPurchase

local MarketplaceService = game:GetService("MarketplaceService")
local Players = game:GetService("Players")
local player = Players.LocalPlayer
local productId = 0000000 -- Change this to your developer product ID
-- Function to prompt purchase of the developer product
local function promptPurchase()
MarketplaceService:PromptProductPurchase(player, productId)
end
promptPurchase()

PromptPurchase

()

Parametri

player: Instance
assetId: number
equipIfPurchased: boolean
Valore predefinito: true
currencyType: Enum.CurrencyType
Valore predefinito: "Default"

Restituzioni

()

Campioni di codice

LocalScript (Client)

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local promptPurchaseEvent = ReplicatedStorage:WaitForChild("PromptPurchaseEvent")
local part = Instance.new("Part")
part.Parent = workspace
local clickDetector = Instance.new("ClickDetector")
clickDetector.Parent = part
clickDetector.MouseClick:Connect(function()
promptPurchaseEvent:FireServer(16630147)
end)
Script (Server)

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local MarketplaceService = game:GetService("MarketplaceService")
local promptPurchaseEvent = Instance.new("RemoteEvent")
promptPurchaseEvent.Name = "PromptPurchaseEvent"
promptPurchaseEvent.Parent = ReplicatedStorage
-- Listen for the RemoteEvent to fire from a Client and then trigger the purchase prompt
promptPurchaseEvent.OnServerEvent:Connect(function(player, id)
MarketplaceService:PromptPurchase(player, id)
end)

PromptSubscriptionPurchase

()

Parametri

user: Player
subscriptionId: string

Restituzioni

()

UserOwnsGamePassAsync

Resa

Parametri

userId: number
gamePassId: number

Restituzioni

Eventi

PromptBulkPurchaseFinished

Parametri


PromptBundlePurchaseFinished

Parametri

player: Instance
bundleId: number
wasPurchased: boolean

PromptGamePassPurchaseFinished

Parametri

player: Instance
gamePassId: number
wasPurchased: boolean

Campioni di codice

Handling Gamepass Purchase Finished

local MarketplaceService = game:GetService("MarketplaceService")
local function gamepassPurchaseFinished(...)
-- Print all the details of the prompt, for example:
-- PromptGamePassPurchaseFinished PlayerName 123456 false
print("PromptGamePassPurchaseFinished", ...)
end
MarketplaceService.PromptGamePassPurchaseFinished:Connect(gamepassPurchaseFinished)

PromptPremiumPurchaseFinished


PromptProductPurchaseFinished

Parametri

userId: number
productId: number
isPurchased: boolean

PromptPurchaseFinished

Parametri

player: Instance
assetId: number
isPurchased: boolean

Campioni di codice

Handling PromptPurchaseFinished Event

local MarketplaceService = game:GetService("MarketplaceService")
local function onPromptPurchaseFinished(player, assetId, isPurchased)
if isPurchased then
print(player.Name, "bought an item with AssetID:", assetId)
else
print(player.Name, "didn't buy an item with AssetID:", assetId)
end
end
MarketplaceService.PromptPurchaseFinished:Connect(onPromptPurchaseFinished)

PromptSubscriptionPurchaseFinished

Parametri

user: Player
subscriptionId: string
didTryPurchasing: boolean

Richiami

Parametri

receiptInfo: Dictionary

Restituzioni

Campioni di codice

ProcessReceipt Callback

local MarketplaceService = game:GetService("MarketplaceService")
local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")
-- Data store setup for tracking purchases that were successfully processed
local purchaseHistoryStore = DataStoreService:GetDataStore("PurchaseHistory")
local productIdByName = {
fullHeal = 123123,
gold100 = 456456,
}
-- A dictionary to look up the handler function to grant a purchase corresponding to a product ID
-- These functions return true if the purchase was granted successfully
-- These functions must never yield since they're called later within an UpdateAsync() callback
local grantPurchaseHandlerByProductId = {
[productIdByName.fullHeal] = function(_receipt, player)
local character = player.Character
local humanoid = character and character:FindFirstChild("Humanoid")
-- Ensure the player has a humanoid to heal
if not humanoid then
return false
end
-- Heal the player to full Health
humanoid.Health = humanoid.MaxHealth
-- Indicate a successful grant
return true
end,
[productIdByName.gold100] = function(_receipt, player)
local leaderstats = player:FindFirstChild("leaderstats")
local goldStat = leaderstats and leaderstats:FindFirstChild("Gold")
if not goldStat then
return false
end
-- Add 100 gold to the player's gold stat
goldStat.Value += 100
-- Indicate a successful grant
return true
end,
}
-- The core ProcessReceipt callback function
-- This implementation handles most failure scenarios but does not completely mitigate cross-server data failure scenarios
local function processReceipt(receiptInfo)
local success, result = pcall(
purchaseHistoryStore.UpdateAsync,
purchaseHistoryStore,
receiptInfo.PurchaseId,
function(isPurchased)
if isPurchased then
-- This purchase was already recorded as granted, so it must have previously been handled
-- Avoid calling the grant purchase handler here to prevent granting the purchase twice
-- While the value in the data store is already true, true is returned again so that the pcall result variable is also true
-- This will later be used to return PurchaseGranted from the receipt processor
return true
end
local player = Players:GetPlayerByUserId(receiptInfo.PlayerId)
if not player then
-- Avoids granting the purchase if the player is not in the server
-- When they rejoin, this receipt processor will be called again
return nil
end
local grantPurchaseHandler = grantPurchaseHandlerByProductId[receiptInfo.ProductId]
if not grantPurchaseHandler then
-- If there's no handler defined for this product ID, the purchase cannot be processed
-- This will never happen as long as a handler is set for every product ID sold in the experience
warn(`No purchase handler defined for product ID '{receiptInfo.ProductId}'`)
return nil
end
local handlerSucceeded, handlerResult = pcall(grantPurchaseHandler, receiptInfo, player)
if not handlerSucceeded then
local errorMessage = handlerResult
warn(
`Grant purchase handler errored while processing purchase from '{player.Name}' of product ID '{receiptInfo.ProductId}': {errorMessage}`
)
return nil
end
local didHandlerGrantPurchase = handlerResult == true
if not didHandlerGrantPurchase then
-- The handler did not grant the purchase, so record it as not granted
return nil
end
-- The purchase is now granted to the player, so record it as granted
-- This will later be used to return PurchaseGranted from the receipt processor
return true
end
)
if not success then
local errorMessage = result
warn(`Failed to process receipt due to data store error: {errorMessage}`)
return Enum.ProductPurchaseDecision.NotProcessedYet
end
local didGrantPurchase = result == true
return if didGrantPurchase
then Enum.ProductPurchaseDecision.PurchaseGranted
else Enum.ProductPurchaseDecision.NotProcessedYet
end
-- Set the callback; this can only be done once by one script on the server
MarketplaceService.ProcessReceipt = processReceipt