Forest Logo
search
package_2

monetize

By @moxxum

Roblox

Mirrored

monetize

Purchases without the classic double-grant bug. A ProcessReceipt router whose idempotency comes from a purchase-ID ledger stored in the player's datakit profile — a receipt already in the ledger is acknowledged as granted without re-running the grant, so DataStore retries and rejoin-replays can never grant twice. Plus a GamePass ownership cache (filled on purchase/first query), and prompt helpers.

Server realm: Monetize = "moxxum/monetize@0.1.0" under [server-dependencies]. Monetize owns MarketplaceService.ProcessReceipt; nothing else may set it.

API

Monetize.Init({
	GetProfile = DataKit.Get,          -- required; profile needs :Get/:Set/:IsActive
	LedgerPath = "PurchaseLedger",     -- default; add it to your datakit template or let it self-create
	LedgerSize = 50,                   -- purchase IDs retained
	OnPurchasePrompted = Analytics.PurchasePrompted,   -- optional hooks
	OnPurchaseCompleted = Analytics.PurchaseCompleted,
})
Monetize.RegisterProduct(productId, grantFn)  -- grantFn(player, receiptInfo); may yield
Monetize.RegisterPass(passId, grantFn?)       -- grant runs on purchase during session
Monetize.OwnsPass(player, passId)             -- cached; fails closed on API error
Monetize.PromptProduct(player, productId)
Monetize.PromptPass(player, passId)

Receipt flow: player absent or profile inactive → NotProcessedYet (Roblox retries). Grant errors → NotProcessedYet. Grant succeeds → purchase ID recorded in the ledger, then PurchaseGranted.

Example

local DataKit = require(ServerPackages.DataKit)
local Monetize = require(ServerPackages.Monetize)

Monetize.Init({ GetProfile = DataKit.Get })

Monetize.RegisterProduct(GameConfig.Products.SmallCoinPack.Id, function(player, receipt)
	local profile = DataKit.Get(player) -- guaranteed active inside a grant
	profile:Set("Coins", profile:Get("Coins") + 100)
end)

-- Pass-gated perk: check at point of use, no grant needed
if Monetize.OwnsPass(player, GameConfig.Passes.Vip.Id) then ... end

Test

rojo build test.project.json -o test.rbxl, open in Studio, Play Solo, expect [monetize-test] ALL PASS (receipt idempotency, unknown products, ledger cap).

Package Details

Install command (Click to copy)


Version

0.1.0

License

MIT

check_circle

Safe for commercial use

infoThe package archive does not include its license text; the license is declared in its manifest metadata.

Automated license review — not legal advice.