MarketplaceService API overhaul

As a Roblox developer, it is currently too hard to sell developer products, gamepasses, catalog assets, and so forth in game.

If this issue is addressed, it would improve my development experience because…

  • I could much easier allow players immediate access to the product they just purchased.
  • I could create better and fluid UI feedback such as denying the clicking of other buttons until the prompt is closed.
  • I would no longer need to create a complex system where I’m waiting for multiple events and remotes to tell me if a purchase was successful or not. This overall would simplify the process making it easier to implement a marketplace in my game.

Non developer products

My request is for a new set of API that allows us to do the following:

  • A method or property to check if a purchase prompt is visible on screen or not
  • Events for when a purchase prompt becomes visible and is hidden
  • An asyncronous method for prompting a purchase.
  • Enums for different types of purchase prompt results.

In use I think it would look something like this:

local function tryPurchase(player, productType, productId)
	local result
	local success, err = pcall(function()
		-- this method yields until the player has made a choice or the prompt is denied
		result = MarketplaceService:PromptPurchaseOf(player, productType, productId)
	end)

	if success then
		-- the prompt did not error
		if result == Enum.PromptResult.Purchased then
			-- the player successfully bought the item
		elseif result == Enum.PromptResult.Cancelled then
			-- the player did not buy the item
		elseif result == Enum.PromptResult.Denied then
			-- Another prompt was already visible and thus this prompt could not be shown
			-- Alternatively, we could've checked if MarketplaceService:IsPurchasePromptVisible() 
			-- was false before requesting the current prompt
		end
	else
		-- something happened w/ the prompt. for example, network issues.
		warn(err)
	end
end


-- might use these events to disallow the player to interact w/ the rest of the UI
-- until they're done with the purchase prompt
MarketplaceService.PurchasePromptVisible:Connect(function()
	ScreenGui.InputSinkFrame.Visible = true
end)

MarketplaceService.PurchasePromptVisible:Connect(function()
	ScreenGui.InputSinkFrame.Visible = false
end)

-- Simple buy a game pass example
ScreenGui.Button.Activated:Connect(function()
	tryPurchase(player, "GamePass", 123456)
end)

Developer products

Now unfortunately due to the nature of developer products they wouldn’t be able to work like the above API. This is because the developer should ensure the “benefits” of the product are awarded to the player before the transaction is considered a success.

My suggestion here would be to scrap the current system in favour of a much simpler design.

This would involve a new method that behaves very similarily to the prompt purchase method suggested above. The only difference is that this method requires a callback function that will be run when the player attempts to purchase a developer product.

If this callback returns true then they are charged and the purchase was a success. Otherwise, the purchase failed and it does NOT try again automatically when the player joins a future game session.

It would look something like this:

local function tryDevProductPurchase(player, productId, )
	local result
	local success, err = pcall(function()
		-- this method yields until the player has made a choice or the prompt is denied
		result = MarketplaceService:PromptDevProductPurchase(player, productId, function(purchaseReceipt)
			-- verify the player's still in the game
			-- save that they purchased the product to a datastore
			-- if all the above succeeded then...
			return true
		end)
	end)

	if success then
		-- the prompt did not error
		if result == Enum.PromptResult.Purchased then
			-- the player successfully bought the item
		elseif result == Enum.PromptResult.Cancelled then
			-- the player did not buy the item
		elseif result == Enum.PromptResult.Denied then
			-- Another prompt was already visible and thus this prompt could not be shown
			-- Alternatively, we could've checked if MarketplaceService:IsPurchasePromptVisible() 
			-- was false before requesting the current prompt
		elseif result == Enum.PromptResult.Failed then
			-- the callback did not succeed
		end
	else
		-- something happened w/ the prompt. for example, network issues.
		warn(err)
	end
end

Conclusion

I understand the above API would not be implemented as is (nor would i expect it to be). I hope though that it makes clear how a system overhaul could make the process of marketplace transactions much much easier.

Thanks!

80 Likes

Definitely support new Enums, the current ones are just NE for context of purchases.
When I was trying to write code for puchases in my own game I seriously was confused why it was designed this way, I think your suggestion would greatly beneficial for developers so we don’t have to use hacky workarounds for purchases to work how they are intended to.

5 Likes

You should title/intro your posts with the problems rather than starting with your proposed solution (that will likely not be implemented as-is anyway, so it’s a waste to discuss that first).

3 Likes

I could write a book on all the issues that the current API has.

Although unconventional and inconvenient to an engineer reading this, I don’t have a literal full day to write out examples of all the individual problem cases with the current system.

10 Likes

I’ve tried the API of platforms outside of Roblox over the past several months and they’re significantly better! Definitely time for an upgrade

4 Likes

You already have a list of pain points at the bottom – just expand on that and move it closer to the top!

It’s hard for a product manager to prioritize this without clear problems they can work through and see where the issues are and how they could be alleviated. I understand proposing an API might be more intuitive to request for you, but it will likely be tossed out anyway, since they need to come up with something that works for everyone and for their back-end.

Alternatively you can file separate feature requests on each problem that you have trouble implementing if that makes it easier to write about it.

3 Likes

That makes sense. Thank you for the suggestion!

1 Like