Lớp công cụ
MarketplaceService
*Nội dung này được dịch bằng AI (Beta) và có thể có lỗi. Để xem trang này bằng tiếng Anh, hãy nhấp vào đây.
Tóm Tắt
Phương Pháp
Sự Kiện
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 |
Gọi Lại
ProcessReceipt(receiptInfo: Dictionary):Enum.ProductPurchaseDecision |
Tài Liệu Tham Khảo API
Phương Pháp
BindReceiptHandler
MarketplaceService:BindReceiptHandler(
Tham Số
Lợi Nhuận
Mẫu mã
MarketplaceService:BindReceiptHandler
-- LƯU Ý: Nếu trình xử lý của bạn cấp những lợi ích lâu dài (tiền tệ, vật phẩm), hãy sử dụng
-- DataStoreService:UpdateAsync() trên TransferRequestId để ngăn
-- cấp đôi khi cùng một biên nhận được gửi đến nhiều máy chủ.
local MarketplaceService = game:GetService("MarketplaceService")
local Players = game:GetService("Players")
-- Xử lý biên nhận của người gửi (người chơi đã gửi Robux)
MarketplaceService:BindReceiptHandler(
Enum.ReceiptType.RobuxTransferSender,
function(receiptInfo)
local player = Players:GetPlayerByUserId(receiptInfo.PlayerId)
if not player then
-- Người chơi không có trên máy chủ này; hoãn lại để biên nhận
-- được gửi lại đến máy chủ mà họ đang ở
return Enum.ReceiptDecision.NotProcessedYet
end
print(
`{player.Name} đã gửi {receiptInfo.CurrencySpent} Robux`
.. ` (TransferRequestId: {receiptInfo.TransferRequestId})`
)
-- Cấp bất kỳ xác nhận hoặc cập nhật UI nào ở phía người gửi tại đây
return Enum.ReceiptDecision.Processed
end
)
-- Xử lý biên nhận của người nhận (người chơi đã nhận 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} đã nhận {receiptInfo.CurrencySpent} Robux`
.. ` (TransferRequestId: {receiptInfo.TransferRequestId})`
)
-- Cấp bất kỳ lợi ích nào ở phía người nhận hoặc cập nhật UI tại đây
return Enum.ReceiptDecision.Processed
end
)GetDeveloperProductsAsync
Lợi Nhuận
Mẫu mã
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
Tham Số
| Giá Trị Mặc Định: "Asset" |
Lợi Nhuận
Mẫu mã
Lấy Thông Tin Sản Phẩm
local MarketplaceService = game:GetService("MarketplaceService")
local ASSET_ID = 125378389
local asset = MarketplaceService:GetProductInfoAsync(ASSET_ID)
print(asset.Name .. " :: " .. asset.Description)Hiển thị Giảm giá Giá
local MarketplaceService = game:GetService("MarketplaceService")
local PASS_ID = 12345678
local textLabel = script.Parent
local DiscountTypeDisplay = {
RobloxPlusSubscription = "Giảm giá Roblox Plus",
}
local productInfo = MarketplaceService:GetProductInfoAsync(PASS_ID, Enum.InfoType.GamePass)
print(string.format("Giá gốc: %d", productInfo.UserBasePriceInRobux))
for _, discount in ipairs(productInfo.PriceDiscountDetails) do
local displayName = DiscountTypeDisplay[discount.Type] or "Giảm giá khác"
print(string.format("%s (%d%%): -%d", displayName, discount.Percent, discount.AmountInRobux))
end
print(string.format("Bạn phải trả: %d", productInfo.PriceInRobux))Hiển Thị Các Tùy Chọn Thời Gian Có Sẵn
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 ngày - %d Robux", days, option.Price))
end
endGetRobloxSubscriptionDetailsAsync
Tham Số
Lợi Nhuận
Mẫu mã
Kiểm tra Chi tiết Đăng ký 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. Kiểm tra lòng trung thành (vd: Đăng ký > 60 ngày)
local threeMonths = 60 * 24 * 60 * 60
if details.StartTime and (os.time() - details.StartTime.UnixTimestamp) > threeMonths then
print("Trao skin 'Cựu chiến binh Đăng ký 3 tháng'!")
end
-- 2. Kiểm tra sự thuộc về
if details.IsOriginExperience then
print("Xác nhận sự thuộc về: Người dùng đã đăng ký qua trải nghiệm này.")
else
print("Người dùng đã đăng ký ở nơi khác (Website hoặc trải nghiệm khác).")
end
end
end)GetSubscriptionProductInfoAsync
Tham Số
Lợi Nhuận
GetUsersPriceLevelsAsync
Tham Số
Lợi Nhuận
{PriceLevelInfo}
Mẫu mã
Lấy mức giá cho danh sách người dùng
-- Lấy MarketplaceService
local MarketplaceService = game:GetService("MarketplaceService")
-- Định nghĩa một hàm để lấy cấp độ giá cho danh sách người dùng
local function getPriceLevels(userIds)
local success, result = pcall(function()
return MarketplaceService:GetUsersPriceLevelsAsync(userIds)
end)
if success then
-- Ánh xạ từng PriceLevelInfo tới bảng tra cứu UserId -> PriceLevel
local lookup = {}
for _, info in ipairs(result) do
lookup[info.UserId] = info.PriceLevel
end
return lookup
else
warn("Lỗi khi lấy cấp độ giá:", result)
return nil
end
end
-- Ví dụ sử dụng ID tạm thời
local user1Id = 123456789
local user2Id = 987654321
-- Gọi hàm và lưu kết quả
local priceLevels = getPriceLevels({user1Id, user2Id})
-- Nếu thành công, in ra cấp độ của từng người dùng
if priceLevels then
print("Cấp độ giá cho Người dùng 1:", priceLevels[user1Id])
print("Cấp độ giá cho Người dùng 2:", priceLevels[user2Id])
else
print("Không thể lấy cấp độ giá.")
endGetUserSubscriptionDetailsAsync
Lợi Nhuận
GetUserSubscriptionPaymentHistoryAsync
Lợi Nhuận
Mẫu mã
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(`Lỗi khi kiểm tra lịch sử đăng ký: {err}`)
return
end
if next(subscriptionHistory) then
-- Người dùng có một số lịch sử đăng ký trong vòng 12 tháng qua.
-- In chi tiết của từng mục thanh toán từ lịch sử đăng ký.
print(`Người chơi {player.Name} đã đăng ký {SUBSCRIPTION_ID} trước đây:`)
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(`Người chơi {player.Name} chưa bao giờ đăng ký {SUBSCRIPTION_ID} trước đây.`)
end
end
-- Gọi checkSubscriptionHistory cho bất kỳ người chơi nào đã ở trong trò chơi
for _, player in ipairs(Players:GetPlayers()) do
checkSubscriptionHistory(player)
end
-- Gọi checkSubscriptionHistory cho tất cả người chơi tương lai
Players.PlayerAdded:Connect(checkSubscriptionHistory)GetUserSubscriptionStatusAsync
Lợi Nhuận
Mẫu mã
Kiểm tra tình trạng đăng ký của người dùng
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()
-- trả về IsRenewing và IsSubscribed
subStatus = MarketplaceService:GetUserSubscriptionStatusAsync(player, subscriptionID)
end)
if not success then
warn("Lỗi khi kiểm tra xem người chơi có đăng ký hay không: " .. tostring(message))
return
end
if subStatus["IsSubscribed"] then
print(player.Name .. " đã đăng ký với " .. subscriptionID)
-- Cấp quyền hạn cho người chơi liên quan đến đăng ký
end
end
Players.PlayerAdded:Connect(checkSubStatus)PlayerOwnsAsset
PlayerOwnsAssetAsync
Lợi Nhuận
Mẫu mã
Kiểm tra quyền sở hữu vật phẩm
local Players = game:GetService("Players")
local MarketplaceService = game:GetService("MarketplaceService")
-- Món đồ mà chúng tôi đang kiểm tra: 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(`Lỗi khi kiểm tra xem {player.Name} có sở hữu {ASSET_NAME}: {errorMessage}`)
return
end
if doesPlayerOwnAsset then
print(`{player.Name} sở hữu {ASSET_NAME}`)
else
print(`{player.Name} không sở hữu {ASSET_NAME}`)
end
end
Players.PlayerAdded:Connect(onPlayerAdded)PlayerOwnsBundle
PlayerOwnsBundleAsync
Lợi Nhuận
Mẫu mã
Kiểm tra quyền sở hữu gói
local Players = game:GetService("Players")
local MarketplaceService = game:GetService("MarketplaceService")
-- Bộ mà chúng ta đang kiểm tra: 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("Gọi PlayerOwnsBundleAsync thất bại: ", doesPlayerOwnBundle)
return
end
if doesPlayerOwnBundle then
print(player.Name .. " sở hữu " .. BUNDLE_NAME)
else
print(player.Name .. " không sở hữu " .. BUNDLE_NAME)
end
end)PromptBulkPurchase
Tham Số
Lợi Nhuận
()
Mẫu mã
Khách Hàng Mua Sắm Số Lượng Lớn
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)Máy chủ yêu cầu mua số lượng lớn
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local MarketplaceService = game:GetService("MarketplaceService")
local promptBulkPurchaseEvent = Instance.new("RemoteEvent")
promptBulkPurchaseEvent.Name = "PromptBulkPurchaseEvent"
promptBulkPurchaseEvent.Parent = ReplicatedStorage
-- Lắng nghe sự kiện RemoteEvent được gửi từ một khách hàng và sau đó kích hoạt yêu cầu mua số lượng lớn
promptBulkPurchaseEvent.OnServerEvent:Connect(function(player, items)
MarketplaceService:PromptBulkPurchase(player, items, {})
end)Mua Tùy Chọn Có Thời Gian
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
-- Tìm tùy chọn có thời gian ngắn nhất
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(
):()
Tham Số
| Giá Trị Mặc Định: true |
| Giá Trị Mặc Định: "Default" |
Lợi Nhuận
()
Mẫu mã
MarketplaceService:PromptProductPurchase
local MarketplaceService = game:GetService("MarketplaceService")
local Players = game:GetService("Players")
local player = Players.LocalPlayer
local productId = 0000000 -- Thay đổi điều này thành ID sản phẩm nhà phát triển của bạn
-- Hàm để yêu cầu mua sản phẩm nhà phát triển
local function promptPurchase()
MarketplaceService:PromptProductPurchase(player, productId)
end
promptPurchase()PromptPurchase
MarketplaceService:PromptPurchase(
):()
Tham Số
| Giá Trị Mặc Định: true |
| Giá Trị Mặc Định: "Default" |
Lợi Nhuận
()
Mẫu mã
LocalScript (Khách hàng)
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)Kịch bản (Máy chủ)
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local MarketplaceService = game:GetService("MarketplaceService")
local promptPurchaseEvent = Instance.new("RemoteEvent")
promptPurchaseEvent.Name = "PromptPurchaseEvent"
promptPurchaseEvent.Parent = ReplicatedStorage
-- Lắng nghe RemoteEvent để gửi từ Khách hàng và sau đó kích hoạt thông báo mua
promptPurchaseEvent.OnServerEvent:Connect(function(player, id)
MarketplaceService:PromptPurchase(player, id)
end)PromptRobloxSubscriptionPurchase
Tham Số
Lợi Nhuận
()
Mẫu mã
Nhắc nhở mua đăng ký 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)
-- Cung cấp phần thưởng và dịch chuyển người chơi đăng ký đến khu vực độc quyền
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
-- Phát hiện các phần của nhân vật chạm vào teleporter
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
-- Người chơi đã có Roblox Plus; cung cấp phần thưởng ngay lập tức
grantRewardAndTeleport(player)
else
-- Nhắc nhở đăng ký Roblox Plus, chỉ thực hiện một lần mỗi vài giây
if not showModal then
return
end
showModal = false
task.delay(5, function()
showModal = true
end)
MarketplaceService:PromptRobloxSubscriptionPurchase(player)
end
end)
-- Phát hiện các phần của nhân vật rời khỏi teleporter
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)
-- Cung cấp phần thưởng khi máy chủ xác nhận thay đổi đăng ký
-- Kết nối thay đổi HasRobloxSubscription cho mỗi người chơi
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
Lợi Nhuận
Mẫu mã
MarketplaceService:PromptRobuxTransferAsync
local MarketplaceService = game:GetService("MarketplaceService")
local Players = game:GetService("Players")
-- Ví dụ: chuyển Robux khi một người chơi kích hoạt RemoteEvent
local transferEvent = game.ReplicatedStorage:WaitForChild("RequestTransfer")
transferEvent.OnServerEvent:Connect(function(sender, receiverUserId, amount)
-- Xác thực đầu vào
if not sender or not sender:IsA("Player") then
return
end
if typeof(receiverUserId) ~= "number" or receiverUserId <= 0 then
warn("receiverUserId không hợp lệ")
return
end
if typeof(amount) ~= "number" or amount <= 0 then
warn("số tiền không hợp lệ")
return
end
local success, result = pcall(function()
return MarketplaceService:PromptRobuxTransferAsync(sender, receiverUserId, amount)
end)
if success then
print(`Giao dịch đã được khởi tạo với TransferRequestId: {result}`)
else
warn(`Giao dịch không thành công: {result}`)
end
end)PromptSubscriptionPurchase
RankProductsAsync
Tham Số
Lợi Nhuận
{RankedItem}
Mẫu mã
Lấy danh sách sản phẩm có xếp hạng dựa trên ID sản phẩm đã cung cấp
-- Lấy MarketplaceService
local MarketplaceService = game:GetService("MarketplaceService")
-- Tạo mảng các sản phẩm mà bạn muốn xếp hạng
local productIdentifiers = {
{InfoType = Enum.InfoType.GamePass, Id = 123},
{InfoType = Enum.InfoType.Product, Id = 456},
{InfoType = Enum.InfoType.Product, Id = 789}
}
-- Gọi trong một cuộc gọi bảo vệ để xử lý lỗi một cách nhẹ nhàng
local success, rankedProducts = pcall(function()
return MarketplaceService:RankProductsAsync(productIdentifiers)
end)
if not success then
error("Không thể xếp hạng sản phẩm")
end
-- Tải các mục đã trả về vào cửa hàng.
for i, rankedItem in ipairs(rankedProducts) do
local productIdentifier = rankedItem.ProductIdentifier
local productInfo = rankedItem.ProductInfo
-- ...
-- Logic để thêm sản phẩm vào cửa hàng
endRecommendTopProductsAsync
Tham Số
Lợi Nhuận
{RankedItem}
Mẫu mã
Nhận danh sách xếp hạng các sản phẩm hàng đầu trong cửa hàng trải nghiệm của bạn
-- Nhận dịch vụ MarketplaceService
local MarketplaceService = game:GetService("MarketplaceService")
-- Tạo một mảng các loại sản phẩm để bao gồm. Trong trường hợp này cả hai loại là game passes và sản phẩm phát triển
local productTypes = {Enum.InfoType.GamePass, Enum.InfoType.Product}
-- Gọi trong một cuộc gọi bảo vệ để xử lý lỗi một cách thanh lịch
local success, topRankedItems = pcall(function()
return MarketplaceService:RecommendTopProductsAsync(productTypes)
end)
if not success then
error("Không thể xếp hạng sản phẩm")
end
-- Tải các mục đã trả về vào cửa hàng. Đảm bảo lọc ra bất kỳ mục không đủ điều kiện nào từ topRankedItems chẳng hạn như sản phẩm phát triển mà người dùng không còn mua được
for i, rankedItem in ipairs(topRankedItems) do
local productIdentifier = rankedItem.ProductIdentifier
local productInfo = rankedItem.ProductInfo
-- ...
-- Logic để thêm sản phẩm vào cửa hàng
endSự Kiện
PromptBulkPurchaseFinished
MarketplaceService.PromptBulkPurchaseFinished(
Tham Số
PromptBundlePurchaseFinished
PromptGamePassPurchaseFinished
MarketplaceService.PromptGamePassPurchaseFinished(
Mẫu mã
Xử lý Kết thúc Mua Gamepass
local MarketplaceService = game:GetService("MarketplaceService")
local function gamepassPurchaseFinished(...)
-- In ra tất cả các chi tiết của thông báo, ví dụ:
-- PromptGamePassPurchaseFinished PlayerName 123456 false
print("PromptGamePassPurchaseFinished", ...)
end
MarketplaceService.PromptGamePassPurchaseFinished:Connect(gamepassPurchaseFinished)PromptProductPurchaseFinished
PromptPurchaseFinished
MarketplaceService.PromptPurchaseFinished(
Mẫu mã
Xử lý sự kiện PromptPurchaseFinished
local MarketplaceService = game:GetService("MarketplaceService")
local function onPromptPurchaseFinished(player, assetId, isPurchased)
if isPurchased then
print(player.Name, "đã mua một món đồ với AssetID:", assetId)
else
print(player.Name, "đã không mua một món đồ với AssetID:", assetId)
end
end
MarketplaceService.PromptPurchaseFinished:Connect(onPromptPurchaseFinished)PromptRobloxSubscriptionPurchaseFinished
MarketplaceService.PromptRobloxSubscriptionPurchaseFinished(
Mẫu mã
Xử lý sự kiện PromptRobloxSubscriptionPurchaseFinished
local MarketplaceService = game:GetService("MarketplaceService")
local function onPromptRobloxSubscriptionPurchaseFinished(player, didTryPurchasing)
if didTryPurchasing then
-- Người chơi đã cố gắng đăng ký; chờ thay đổi HasRobloxSubscription để xác nhận
print(player.Name, "cố gắng đăng ký Roblox Plus")
else
print(player.Name, "đã đóng lời mời đăng ký Roblox Plus mà không mua sắm")
end
end
MarketplaceService.PromptRobloxSubscriptionPurchaseFinished:Connect(onPromptRobloxSubscriptionPurchaseFinished)Gọi Lại
ProcessReceipt
Tham Số
Lợi Nhuận
Mẫu mã
Hàm Callback ProcessReceipt
local MarketplaceService = game:GetService("MarketplaceService")
local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")
-- Thiết lập kho dữ liệu để theo dõi các giao dịch mua đã được xử lý thành công
local purchaseHistoryStore = DataStoreService:GetDataStore("PurchaseHistory")
local productIdByName = {
fullHeal = 123123,
gold100 = 456456,
}
-- Một từ điển để tra cứu hàm xử lý cấp phát một giao dịch mua tương ứng với ID sản phẩm
-- Các hàm này trả về true nếu giao dịch mua được cấp phát thành công
-- Các hàm này không bao giờ được cho phép chờ vì chúng được gọi sau đó trong một callback UpdateAsync()
local grantPurchaseHandlerByProductId = {
[productIdByName.fullHeal] = function(_receipt, player)
local character = player.Character
local humanoid = character and character:FindFirstChild("Humanoid")
-- Đảm bảo người chơi có một humanoid để hồi phục sức khỏe
if not humanoid then
return false
end
-- Hồi phục sức khỏe cho người chơi đến mức tối đa
humanoid.Health = humanoid.MaxHealth
-- Chỉ ra rằng việc cấp phát đã thành công
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
-- Thêm 100 vàng vào thống kê vàng của người chơi
goldStat.Value += 100
-- Chỉ ra rằng việc cấp phát đã thành công
return true
end,
}
-- Hàm callback chính của ProcessReceipt
-- Triển khai này xử lý hầu hết các kịch bản thất bại nhưng không hoàn toàn giảm thiểu các kịch bản thất bại dữ liệu giữa các máy chủ
local function processReceipt(receiptInfo)
local success, result = pcall(
purchaseHistoryStore.UpdateAsync,
purchaseHistoryStore,
receiptInfo.PurchaseId,
function(isPurchased)
if isPurchased then
-- Giao dịch mua này đã được ghi lại là đã cấp phát, vì vậy nó phải đã được xử lý trước đó
-- Tránh gọi hàm xử lý cấp phát ở đây để ngăn chặn việc cấp phát giao dịch mua hai lần
-- Trong khi giá trị trong kho dữ liệu đã là true, true sẽ được trả về một lần nữa để biến kết quả pcall cũng là true
-- Điều này sẽ được sử dụng sau đó để trả về PurchaseGranted từ bộ xử lý biên lai
return true
end
local player = Players:GetPlayerByUserId(receiptInfo.PlayerId)
if not player then
-- Tránh cấp phát giao dịch mua nếu người chơi không có trong máy chủ
-- Khi họ tham gia lại, bộ xử lý biên lai này sẽ được gọi lại
return nil
end
local grantPurchaseHandler = grantPurchaseHandlerByProductId[receiptInfo.ProductId]
if not grantPurchaseHandler then
-- Nếu không có hàm xử lý nào được xác định cho ID sản phẩm này, giao dịch mua không thể được xử lý
-- Điều này sẽ không bao giờ xảy ra miễn là một hàm xử lý được thiết lập cho mỗi ID sản phẩm được bán trong trải nghiệm
warn(`Không có hàm xử lý giao dịch mua được xác định cho ID sản phẩm '{receiptInfo.ProductId}'`)
return nil
end
local handlerSucceeded, handlerResult = pcall(grantPurchaseHandler, receiptInfo, player)
if not handlerSucceeded then
local errorMessage = handlerResult
warn(
`Hàm xử lý cấp phát giao dịch mua gặp lỗi trong quá trình xử lý giao dịch từ '{player.Name}' của ID sản phẩm '{receiptInfo.ProductId}': {errorMessage}`
)
return nil
end
local didHandlerGrantPurchase = handlerResult == true
if not didHandlerGrantPurchase then
-- Hàm xử lý đã không cấp phát giao dịch mua, vì vậy ghi lại nó là không được cấp phát
return nil
end
-- Giao dịch mua bây giờ đã được cấp phát cho người chơi, vì vậy ghi lại nó là đã cấp phát
-- Điều này sẽ được sử dụng sau đó để trả về PurchaseGranted từ bộ xử lý biên lai
return true
end
)
if not success then
local errorMessage = result
warn(`Giao dịch biên lai không thành công do lỗi kho dữ liệu: {errorMessage}`)
return Enum.ProductPurchaseDecision.NotProcessedYet
end
local didGrantPurchase = result == true
return if didGrantPurchase
then Enum.ProductPurchaseDecision.PurchaseGranted
else Enum.ProductPurchaseDecision.NotProcessedYet
end
-- Đặt callback; điều này chỉ có thể được thực hiện một lần bởi một tập lệnh trên máy chủ
MarketplaceService.ProcessReceipt = processReceipt