ProductService | Handle ingame monetization easily

Hey everyone! So before i begin i wanted to say that this module is in no way meant to replace the MarketplaceService, it’s simply made to allow developers to handle ingame monetization easily!

(Yes i know that MPS is pretty straight forward and easy to use but i believe that this module could make certain things easier / better)

Why should you use this module?

This module is pretty much just made to make stuff like .PromptPurchaseFinished alot easier to use and track, let me show you what i mean

Let’s say you have a VIP Door or something in your game, and you wanna register when that purchase has been completed

Normally you would do something like this:

local MarketplaceService = game:GetService("MarketplaceService")

local vip_gamepassId = 123

function processTransaction(player : Player, gamepassId : number, isPurchased : boolean)
	if isPurchased == false then
		return
	end
	
	if gamepassId ~= vip_gamepassId then
		return
	end
	
	warn(player.DisplayName .. " has bought VIP! 🎉")
end

MarketplaceService.PromptGamePassPurchaseFinished:Connect(processTransaction)

But using ProductService you could do something like this:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ProductService = require(ReplicatedStorage.ProductService)

local VipProduct = ProductService.new(123, "Gamepass")

function processTransaction(player : Player)
	warn(player.DisplayName .. " has bought VIP! 🎉")
end

VipProduct:GetPurchasedSignal():Connect(processTransaction)

It simply makes your life easier, and when it comes to Developer Products it’s even better!
ProductService has built in support for both PromptProductPurchaseFinished AND ProcessReceipt making it extremely easy to use

Instead of handling all that mess like saving the TransactionId or finding the Player Object from the receipt you can simply do exactly the same thing we did for the previous gamepass example and only have to change two words!

PromptProductPurchaseFinished example:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ProductService = require(ReplicatedStorage.ProductService)

local StarterPackProduct = ProductService.new(123, "Product")

function processTransaction(player : Player, receipt)
	warn(player.DisplayName .. " has bought StarterPack! 💸")
end

StarterPackProduct:GetPurchasedSignal():Connect(processTransaction)

As you can see i only had to change the assetType from “Gamepass” to “Product” and if i wanted this to use the ProcessReceipt i could simply add one more param when constructing the product

ProcessReceipt example:
(You can also get the receiptInfo as the second argument if you want)

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ProductService = require(ReplicatedStorage.ProductService)

local StarterPackProduct = ProductService.new(123, "Product", true)

function processTransaction(player : Player, receiptInfo)
	warn(player.DisplayName .. " has bought StarterPack! 💸")
end

StarterPackProduct:GetPurchasedSignal():Connect(processTransaction)

I hope you like this quick module i made, please keep in mind that this is the first one i actually released to the public to use for free so i won’t really be creating some Documentation or something since im pretty noob at this :sob:, and if you can please give me feedback on this module!

:link: Source-code is available here.

3 Likes

I forgot to add these things before releasing the module but here they are!

Instead of having to create each Product manually you can simply do:

ocal ReplicatedStorage = game:GetService("ReplicatedStorage")
local ProductService = require(ReplicatedStorage.ProductService)

function receiptProcessed(player : Player, productId : number, receiptInfo)

end

function productBought(player : Player, productId : number)

end

function gamepassBought(player : Player, gamepassId : number)

end

ProductService.ReceiptProcessed:Connect(receiptProcessed)
ProductService.ProductPurchased:Connect(productBought)
ProductService.GamepassPurchased:Connect(gamepassBought)

That’s pretty much it, i tested everything as much as i could and it seemed to work just fine for now