エンジンクラス
MarketplaceService
*このコンテンツは、ベータ版のAI(人工知能)を使用して翻訳されており、エラーが含まれている可能性があります。このページを英語で表示するには、 こちら をクリックしてください。
概要
方法
イベント
PromptBulkPurchaseFinished(player: Instance,status: Enum.MarketplaceBulkPurchasePromptStatus,results: Dictionary):RBXScriptSignal |
PromptBundlePurchaseFinished(player: Instance,bundleId: number,wasPurchased: boolean):RBXScriptSignal |
PromptGamePassPurchaseFinished(player: Instance,gamePassId: number,wasPurchased: boolean):RBXScriptSignal |
PromptProductPurchaseFinished(userId: number,productId: number,isPurchased: boolean):RBXScriptSignal |
PromptPurchaseFinished(player: Instance,assetId: number,isPurchased: boolean):RBXScriptSignal |
PromptRobloxSubscriptionPurchaseFinished(user: Player,didTryPurchasing: boolean):RBXScriptSignal |
PromptSubscriptionPurchaseFinished(user: Player,subscriptionId: string,didTryPurchasing: boolean):RBXScriptSignal |
コールバック
ProcessReceipt(receiptInfo: Dictionary):Enum.ProductPurchaseDecision |
APIリファレンス
方法
BindReceiptHandler
MarketplaceService:BindReceiptHandler(
パラメータ
コードサンプル
MarketplaceService:BindReceiptHandler
-- 注: ハンドラーが永続的な利益(通貨、アイテム)を付与する場合は、
-- DataStoreService:UpdateAsync() を TransferRequestId で使用して、
-- 同じ領収書が複数のサーバーに配信されるときに二重付与を防ぎます。
local MarketplaceService = game:GetService("MarketplaceService")
local Players = game:GetService("Players")
-- 送信者の領収書を処理します(Robux を送信したプレイヤー)
MarketplaceService:BindReceiptHandler(
Enum.ReceiptType.RobuxTransferSender,
function(receiptInfo)
local player = Players:GetPlayerByUserId(receiptInfo.PlayerId)
if not player then
-- プレイヤーがこのサーバーにいません; 保留にして領収書を
-- 現在いるサーバーに再配信されるようにします
return Enum.ReceiptDecision.NotProcessedYet
end
print(
`{player.Name} が {receiptInfo.CurrencySpent} Robux を送信しました`
.. ` (TransferRequestId: {receiptInfo.TransferRequestId})`
)
-- ここで送信者に対する確認または UI を更新します
return Enum.ReceiptDecision.Processed
end
)
-- 受信者の領収書を処理します(Robux を受信したプレイヤー)
MarketplaceService:BindReceiptHandler(
Enum.ReceiptType.RobuxTransferReceiver,
function(receiptInfo)
local player = Players:GetPlayerByUserId(receiptInfo.PlayerId)
if not player then
return Enum.ReceiptDecision.NotProcessedYet
end
print(
`{player.Name} が {receiptInfo.CurrencySpent} Robux を受信しました`
.. ` (TransferRequestId: {receiptInfo.TransferRequestId})`
)
-- ここで受信者側の利益を付与するか、UI を更新します
return Enum.ReceiptDecision.Processed
end
)GetDeveloperProductsAsync
戻り値
コードサンプル
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(" ")
endGetProductInfo
GetProductInfoAsync
パラメータ
| 既定値: "Asset" |
戻り値
コードサンプル
プロダクト情報の取得
local MarketplaceService = game:GetService("MarketplaceService")
local ASSET_ID = 125378389
local asset = MarketplaceService:GetProductInfoAsync(ASSET_ID)
print(asset.Name .. " :: " .. asset.Description)価格割引の表示
local MarketplaceService = game:GetService("MarketplaceService")
local PASS_ID = 12345678
local textLabel = script.Parent
local DiscountTypeDisplay = {
RobloxPlusSubscription = "Roblox Plus 割引",
}
local productInfo = MarketplaceService:GetProductInfoAsync(PASS_ID, Enum.InfoType.GamePass)
print(string.format("元の価格: %d", productInfo.UserBasePriceInRobux))
for _, discount in ipairs(productInfo.PriceDiscountDetails) do
local displayName = DiscountTypeDisplay[discount.Type] or "その他の割引"
print(string.format("%s (%d%%): -%d", displayName, discount.Percent, discount.AmountInRobux))
end
print(string.format("あなたの支払い: %d", productInfo.PriceInRobux))利用可能なタイムオプションの表示
local MarketplaceService = game:GetService("MarketplaceService")
local info = MarketplaceService:GetProductInfoAsync(105589844216517, Enum.InfoType.Asset)
if info.TimedOptions then
for _, option in info.TimedOptions do
local days = option.Duration / 86400
print(string.format("%d 日 - %d Robux", days, option.Price))
end
endGetRobloxSubscriptionDetailsAsync
パラメータ
戻り値
コードサンプル
Roblox サブスクリプションの詳細を確認する
local MarketplaceService = game:GetService("MarketplaceService")
local Players = game:GetService("Players")
Players.PlayerAdded:Connect(function(player)
local success, details = pcall(function()
return MarketplaceService:GetRobloxSubscriptionDetailsAsync(player)
end)
if success and details.IsSubscribed then
-- 1. 忠誠心を確認する(例:60日以上サブスクライブ)
local threeMonths = 60 * 24 * 60 * 60
if details.StartTime and (os.time() - details.StartTime.UnixTimestamp) > threeMonths then
print("'3ヶ月のサブスクリプションベテラン'スキンを授与します!")
end
-- 2. 帰属を確認する
if details.IsOriginExperience then
print("帰属が確認されました:ユーザーはこの体験を通じてサブスクライブしました。")
else
print("ユーザーは別の場所(ウェブサイトまたは別の体験)でサブスクライブしました。")
end
end
end)GetSubscriptionProductInfoAsync
パラメータ
戻り値
GetUsersPriceLevelsAsync
パラメータ
戻り値
{PriceLevelInfo}
コードサンプル
ユーザーのリストの価格レベルを取得する
-- MarketplaceServiceを取得します
local MarketplaceService = game:GetService("MarketplaceService")
-- ユーザーのリストの価格レベルを取得する関数を定義します
local function getPriceLevels(userIds)
local success, result = pcall(function()
return MarketplaceService:GetUsersPriceLevelsAsync(userIds)
end)
if success then
-- 各PriceLevelInfoをUserId -> PriceLevelルックアップテーブルにマップします
local lookup = {}
for _, info in ipairs(result) do
lookup[info.UserId] = info.PriceLevel
end
return lookup
else
warn("価格レベルの取得中にエラーが発生しました:", result)
return nil
end
end
-- プレースホルダーIDを使用した例
local user1Id = 123456789
local user2Id = 987654321
-- 関数を呼び出し、結果を保存します
local priceLevels = getPriceLevels({user1Id, user2Id})
-- 成功した場合、各ユーザーのレベルを表示します
if priceLevels then
print("ユーザー1の価格レベル:", priceLevels[user1Id])
print("ユーザー2の価格レベル:", priceLevels[user2Id])
else
print("価格レベルの取得に失敗しました.")
endGetUserSubscriptionDetailsAsync
戻り値
GetUserSubscriptionPaymentHistoryAsync
戻り値
コードサンプル
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(`サブスクリプション履歴の確認中にエラーが発生しました: {err}`)
return
end
if next(subscriptionHistory) then
-- ユーザーは過去12か月以内にいくつかのサブスクリプション履歴を持っています。
-- サブスクリプション履歴の各支払いエントリの詳細を印刷します。
print(`プレイヤー {player.Name} は以前に {SUBSCRIPTION_ID} にサブスクライブしました:`)
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.Name} は以前に {SUBSCRIPTION_ID} にサブスクライブしたことがありません。`)
end
end
-- ゲームに既にいるプレイヤーのために checkSubscriptionHistory を呼び出す
for _, player in ipairs(Players:GetPlayers()) do
checkSubscriptionHistory(player)
end
-- 今後のすべてのプレイヤーのために checkSubscriptionHistory を呼び出す
Players.PlayerAdded:Connect(checkSubscriptionHistory)GetUserSubscriptionStatusAsync
戻り値
コードサンプル
ユーザーのサブスクリプションステータスを確認
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()
-- IsRenewing および IsSubscribed を返します
subStatus = MarketplaceService:GetUserSubscriptionStatusAsync(player, subscriptionID)
end)
if not success then
warn("プレイヤーのサブスクリプションを確認中にエラーが発生しました: " .. tostring(message))
return
end
if subStatus["IsSubscribed"] then
print(player.Name .. " は " .. subscriptionID .. " でサブスクライブされています")
-- サブスクリプションに関連する権限をプレイヤーに付与します
end
end
Players.PlayerAdded:Connect(checkSubStatus)PlayerOwnsAsset
PlayerOwnsAssetAsync
戻り値
コードサンプル
アイテム所有権の確認
local Players = game:GetService("Players")
local MarketplaceService = game:GetService("MarketplaceService")
-- 確認するアイテム: 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.PlayerOwnsAssetAsync, MarketplaceService, player, ASSET_ID)
if not success then
local errorMessage = doesPlayerOwnAsset
warn(`{player.Name} が {ASSET_NAME} を所有しているか確認中にエラーが発生しました: {errorMessage}`)
return
end
if doesPlayerOwnAsset then
print(`{player.Name} は {ASSET_NAME} を所有しています`)
else
print(`{player.Name} は {ASSET_NAME} を所有していません`)
end
end
Players.PlayerAdded:Connect(onPlayerAdded)PlayerOwnsBundle
PlayerOwnsBundleAsync
戻り値
コードサンプル
バンドルの所有権を確認する
local Players = game:GetService("Players")
local MarketplaceService = game:GetService("MarketplaceService")
-- 確認しているバンドル: 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:PlayerOwnsBundleAsync(player, BUNDLE_ID)
end)
if success == false then
print("PlayerOwnsBundleAsync の呼び出しに失敗しました: ", doesPlayerOwnBundle)
return
end
if doesPlayerOwnBundle then
print(player.Name .. " は " .. BUNDLE_NAME .. " を所有しています")
else
print(player.Name .. " は " .. BUNDLE_NAME .. " を所有していません")
end
end)PromptBulkPurchase
パラメータ
戻り値
()
コードサンプル
プロンプト一括購入クライアント
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)プロンプト一括購入サーバー
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local MarketplaceService = game:GetService("MarketplaceService")
local promptBulkPurchaseEvent = Instance.new("RemoteEvent")
promptBulkPurchaseEvent.Name = "PromptBulkPurchaseEvent"
promptBulkPurchaseEvent.Parent = ReplicatedStorage
-- クライアントからの RemoteEvent の発火を待ち受け、次に一括購入プロンプトをトリガーします
promptBulkPurchaseEvent.OnServerEvent:Connect(function(player, items)
MarketplaceService:PromptBulkPurchase(player, items, {})
end)タイムオプション購入の促進
local MarketplaceService = game:GetService("MarketplaceService")
local Players = game:GetService("Players")
local ASSET_ID = 105589844216517
Players.PlayerAdded:Connect(function(player)
local info = MarketplaceService:GetProductInfoAsync(ASSET_ID, Enum.InfoType.Asset)
if info.TimedOptions and #info.TimedOptions > 0 then
-- 最短の期間オプションを探す
local shortest = info.TimedOptions[1]
for _, option in info.TimedOptions do
if option.Duration < shortest.Duration then
shortest = option
end
end
local items = {
{
Type = Enum.MarketplaceProductType.AvatarAsset,
Id = tostring(ASSET_ID),
PurchaseOptions = {
{ Type = Enum.PurchaseOption.TimedOption, Value = shortest.Duration },
},
}
}
MarketplaceService:PromptBulkPurchase(player, items, {})
end
end)PromptBundlePurchase
PromptCancelSubscription
PromptGamePassPurchase
PromptPremiumPurchase
PromptProductPurchase
MarketplaceService:PromptProductPurchase(
):()
パラメータ
| 既定値: true |
| 既定値: "Default" |
戻り値
()
コードサンプル
MarketplaceService:PromptProductPurchase
local MarketplaceService = game:GetService("MarketplaceService")
local Players = game:GetService("Players")
local player = Players.LocalPlayer
local productId = 0000000 -- これをあなたのデベロッパー製品IDに変更してください
-- デベロッパー製品の購入を促す関数
local function promptPurchase()
MarketplaceService:PromptProductPurchase(player, productId)
end
promptPurchase()PromptPurchase
MarketplaceService:PromptPurchase(
):()
パラメータ
| 既定値: true |
| 既定値: "Default" |
戻り値
()
コードサンプル
ローカルスクリプト (クライアント)
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)スクリプト(サーバー)
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local MarketplaceService = game:GetService("MarketplaceService")
local promptPurchaseEvent = Instance.new("RemoteEvent")
promptPurchaseEvent.Name = "PromptPurchaseEvent"
promptPurchaseEvent.Parent = ReplicatedStorage
-- クライアントから発火した RemoteEvent をリッスンし、購入プロンプトをトリガーします
promptPurchaseEvent.OnServerEvent:Connect(function(player, id)
MarketplaceService:PromptPurchase(player, id)
end)PromptRobloxSubscriptionPurchase
パラメータ
戻り値
()
コードサンプル
Roblox Plus サブスクリプション購入のプロンプト
local MarketplaceService = game:GetService("MarketplaceService")
local Players = game:GetService("Players")
local teleporter = script.Parent
local showModal = true
local EXCLUSIVE_AREA_POSITION = Vector3.new(1200, 200, 60)
-- 報酬を付与し、サブスクライブしたプレイヤーを専用エリアにテレポートする
local function grantRewardAndTeleport(player)
player:RequestStreamAroundAsync(EXCLUSIVE_AREA_POSITION)
local character = player.Character
if character and character.Parent then
local currentPivot = character:GetPivot()
character:PivotTo(currentPivot * CFrame.new(EXCLUSIVE_AREA_POSITION))
end
end
-- テレポーターに接触したキャラクターのパーツを検出する
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.HasRobloxSubscription then
-- プレイヤーはすでに Roblox Plus を持っています; 即座に報酬を付与
grantRewardAndTeleport(player)
else
-- Roblox Plus サブスクリプションを促す、数秒ごとにデバウンス
if not showModal then
return
end
showModal = false
task.delay(5, function()
showModal = true
end)
MarketplaceService:PromptRobloxSubscriptionPurchase(player)
end
end)
-- テレポーターから出ているキャラクターのパーツを検出する
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)
-- サーバーがサブスクリプションの変更を確認したときに報酬を付与
-- 各プレイヤーの HasRobloxSubscription の変更を接続する
Players.PlayerAdded:Connect(function(player)
player:GetPropertyChangedSignal("HasRobloxSubscription"):Connect(function()
if player.HasRobloxSubscription
and player:GetAttribute("CharacterPartsTouching")
and player:GetAttribute("CharacterPartsTouching") > 0
then
grantRewardAndTeleport(player)
end
end)
end)PromptRobuxTransferAsync
戻り値
コードサンプル
MarketplaceService:PromptRobuxTransferAsync
local MarketplaceService = game:GetService("MarketplaceService")
local Players = game:GetService("Players")
-- 例: プレイヤーが RemoteEvent をトリガーしたときに Robux を転送する
local transferEvent = game.ReplicatedStorage:WaitForChild("RequestTransfer")
transferEvent.OnServerEvent:Connect(function(sender, receiverUserId, amount)
-- 入力を検証
if not sender or not sender:IsA("Player") then
return
end
if typeof(receiverUserId) ~= "number" or receiverUserId <= 0 then
warn("無効な receiverUserId")
return
end
if typeof(amount) ~= "number" or amount <= 0 then
warn("無効な金額")
return
end
local success, result = pcall(function()
return MarketplaceService:PromptRobuxTransferAsync(sender, receiverUserId, amount)
end)
if success then
print(`転送が開始されました: TransferRequestId: {result}`)
else
warn(`転送に失敗しました: {result}`)
end
end)PromptSubscriptionPurchase
RankProductsAsync
パラメータ
戻り値
{RankedItem}
コードサンプル
提供された商品IDに基づいてランク付けされた商品のリストを取得
-- MarketplaceServiceを取得
local MarketplaceService = game:GetService("MarketplaceService")
-- ランク付けしたい商品の配列を作成
local productIdentifiers = {
{InfoType = Enum.InfoType.GamePass, Id = 123},
{InfoType = Enum.InfoType.Product, Id = 456},
{InfoType = Enum.InfoType.Product, Id = 789}
}
-- エラーを優雅に処理するために保護された呼び出しを行う
local success, rankedProducts = pcall(function()
return MarketplaceService:RankProductsAsync(productIdentifiers)
end)
if not success then
error("商品のランク付けに失敗しました")
end
-- 返されたアイテムをストアに読み込む。
for i, rankedItem in ipairs(rankedProducts) do
local productIdentifier = rankedItem.ProductIdentifier
local productInfo = rankedItem.ProductInfo
-- ...
-- ストアに商品を追加するロジック
endRecommendTopProductsAsync
パラメータ
戻り値
{RankedItem}
コードサンプル
体験内ストアでの上位製品のランキング一覧を取得
-- MarketplaceServiceを取得
local MarketplaceService = game:GetService("MarketplaceService")
-- 含める製品タイプの配列を作成します。この場合、ゲームパスと開発者製品の両方
local productTypes = {Enum.InfoType.GamePass, Enum.InfoType.Product}
-- エラーを優雅に処理するために保護された呼び出しを行います
local success, topRankedItems = pcall(function()
return MarketplaceService:RecommendTopProductsAsync(productTypes)
end)
if not success then
error("製品のランキングに失敗しました")
end
-- 返されたアイテムをストアにロードします。ユーザーがもう購入できない開発者製品などの不適格なアイテムをtopRankedItemsからフィルタリングすることを確認してください
for i, rankedItem in ipairs(topRankedItems) do
local productIdentifier = rankedItem.ProductIdentifier
local productInfo = rankedItem.ProductInfo
-- ...
-- ストアに製品を追加するロジック
endイベント
PromptBulkPurchaseFinished
MarketplaceService.PromptBulkPurchaseFinished(
パラメータ
PromptBundlePurchaseFinished
PromptGamePassPurchaseFinished
MarketplaceService.PromptGamePassPurchaseFinished(
コードサンプル
ゲームパス購入完了の処理
local MarketplaceService = game:GetService("MarketplaceService")
local function gamepassPurchaseFinished(...)
-- プロンプトの詳細をすべて表示します。たとえば:
-- PromptGamePassPurchaseFinished PlayerName 123456 false
print("PromptGamePassPurchaseFinished", ...)
end
MarketplaceService.PromptGamePassPurchaseFinished:Connect(gamepassPurchaseFinished)PromptProductPurchaseFinished
PromptPurchaseFinished
MarketplaceService.PromptPurchaseFinished(
コードサンプル
PromptPurchaseFinishedイベントの処理
local MarketplaceService = game:GetService("MarketplaceService")
local function onPromptPurchaseFinished(player, assetId, isPurchased)
if isPurchased then
print(player.Name, "はAssetID:", assetId, "のアイテムを購入しました")
else
print(player.Name, "はAssetID:", assetId, "のアイテムを購入しませんでした")
end
end
MarketplaceService.PromptPurchaseFinished:Connect(onPromptPurchaseFinished)PromptRobloxSubscriptionPurchaseFinished
MarketplaceService.PromptRobloxSubscriptionPurchaseFinished(
コードサンプル
PromptRobloxSubscriptionPurchaseFinishedイベントの処理
local MarketplaceService = game:GetService("MarketplaceService")
local function onPromptRobloxSubscriptionPurchaseFinished(player, didTryPurchasing)
if didTryPurchasing then
-- プレイヤーはサブスクリプションを試みました; HasRobloxSubscriptionの変更を待って確認します
print(player.Name, "はRoblox Plusのサブスクリプションを試みました")
else
print(player.Name, "は購入せずにRoblox Plusのサブスクリプションのプロンプトを閉じました")
end
end
MarketplaceService.PromptRobloxSubscriptionPurchaseFinished:Connect(onPromptRobloxSubscriptionPurchaseFinished)コールバック
ProcessReceipt
パラメータ
コードサンプル
プロセスレシートコールバック
local MarketplaceService = game:GetService("MarketplaceService")
local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")
-- 購入が正常に処理されたことを追跡するためのデータストアのセットアップ
local purchaseHistoryStore = DataStoreService:GetDataStore("PurchaseHistory")
local productIdByName = {
fullHeal = 123123,
gold100 = 456456,
}
-- 製品IDに対応する購入を付与するためのハンドラ関数をルックアップする辞書
-- これらの関数は、購入が正常に付与された場合にtrueを返します
-- これらの関数は、UpdateAsync()コールバック内で後で呼び出されるため、決して yield してはいけません
local grantPurchaseHandlerByProductId = {
[productIdByName.fullHeal] = function(_receipt, player)
local character = player.Character
local humanoid = character and character:FindFirstChild("Humanoid")
-- プレイヤーに治療するためのヒューマノイドがあることを確認します
if not humanoid then
return false
end
-- プレイヤーを完全にヒールします
humanoid.Health = humanoid.MaxHealth
-- 成功した付与を示します
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
-- プレイヤーの金の統計に100の金を追加します
goldStat.Value += 100
-- 成功した付与を示します
return true
end,
}
-- コアProcessReceiptコールバック関数
-- この実装はほとんどの失敗シナリオを処理しますが、サーバー間データ失敗シナリオを完全には軽減しません
local function processReceipt(receiptInfo)
local success, result = pcall(
purchaseHistoryStore.UpdateAsync,
purchaseHistoryStore,
receiptInfo.PurchaseId,
function(isPurchased)
if isPurchased then
-- この購入はすでに付与されたとして記録されているため、以前に処理されている必要があります
-- ここで購入付与ハンドラを呼び出すことを避けて、購入を二重に付与しないようにします
-- データストア内の値がすでにtrueであっても、trueが再度返され、pcallの結果変数もtrueになります
-- これは後でレシートプロセッサからPurchaseGrantedを返すために使用されます
return true
end
local player = Players:GetPlayerByUserId(receiptInfo.PlayerId)
if not player then
-- プレイヤーがサーバーにいない場合は購入の付与を避けます
-- 再加入すると、このレシートプロセッサが再度呼び出されます
return nil
end
local grantPurchaseHandler = grantPurchaseHandlerByProductId[receiptInfo.ProductId]
if not grantPurchaseHandler then
-- この製品IDに対するハンドラが定義されていない場合、購入を処理できません
-- 経験で販売されているすべての製品IDにハンドラが設定されている限り、これは決して発生しません
warn(`製品ID '{receiptInfo.ProductId}' のための購入ハンドラが定義されていません`)
return nil
end
local handlerSucceeded, handlerResult = pcall(grantPurchaseHandler, receiptInfo, player)
if not handlerSucceeded then
local errorMessage = handlerResult
warn(
`'{player.Name}' が製品ID '{receiptInfo.ProductId}' を購入しようとしたときに購入ハンドラがエラーを発生させました: {errorMessage}`
)
return nil
end
local didHandlerGrantPurchase = handlerResult == true
if not didHandlerGrantPurchase then
-- ハンドラは購入を付与しなかったので、付与されていないとして記録します
return nil
end
-- 購入は現在プレイヤーに付与されたので、付与として記録します
-- これは後でレシートプロセッサからPurchaseGrantedを返すために使用されます
return true
end
)
if not success then
local errorMessage = result
warn(`データストアエラーのためレシートを処理できませんでした: {errorMessage}`)
return Enum.ProductPurchaseDecision.NotProcessedYet
end
local didGrantPurchase = result == true
return if didGrantPurchase
then Enum.ProductPurchaseDecision.PurchaseGranted
else Enum.ProductPurchaseDecision.NotProcessedYet
end
-- コールバックを設定します; これはサーバー上で一つのスクリプトによって一度だけ実行できます
MarketplaceService.ProcessReceipt = processReceipt