Developer product module for those having trouble with dev products

Because I’m so nice and I’ve seen numerous people struggling with with developer products, I made a module to make their usage similar to game passes (well, pretty much exactly like game passes) reserving the ability to use them as consumables instead of just passes as well.

Module

Syntax:
[size=4]void productService.sellProduct(player, int productId, function callback)[/size]
Sells the product to the player. If the player does successfully go through the the purchase and a callback was supplied, callback will be executed.

[size=4]boolean productService.ownsProduct(player, int productId)[/size]
Returns whether or not the player owns the product

[size=4]void productService.sellConsumable(player, int productId, int consumablesToAward, function callback)[/size]
Sells consumablesToAward consumables to player. If the player does successfully go through the the purchase and a callback was supplied, callback will be executed.

[size=4]int productService.ownedConsumables(player, int productId)[/size]
Returns number of consumables owned by player

[size=4]boolean productService.useConsumable(player, int productId, int consumablesToUse)[/size]
Depletes consumablesToUse from the player’s consumables and returns true if the player had enough consumables to consume. Otherwise, if the player did not have enough consumables, the number of consumables they own remains the same and returns false. Can also be given a negative consumablesToUse if you want to award free consumables.

Example usage:

[code]local productService = require(223666277)

print(“EchoReaper”, (productService.ownsProduct(game.Players.EchoReaper, 100001)) and “owns” or “does not own”, “product 100001”)
print(“EchoReaper owns”, productService.ownedConsumables(game.Players.EchoReaper, 200002), “of consumable 200002”)

productService.sellProduct(game.Players.EchoReaper, 100001)

productService.sellProduct(game.Players.EchoReaper, 100001, function()
–will get run if and when player buys the product
print(“Player bought the product!”)
end)

productService.sellConsumable(game.Players.EchoReaper, 200002, 5, function(newValue)
print(“Player just bought 5 consumables! Their new count is”, newValue)
end)

local success = productService.useConsumable(game.Players.EchoReaper, 200002, 3)
if success then
print(“Player had enough consumables!”)
–do stuff
end

–if productCount is left blank, 1 consumable will be used
local success = productService.useConsumable(game.Players.EchoReaper, 200002, 1)
if success then
print(“Player used one consumable!”)
end

–You can also optionally supply currency types with sellConsumable and sellProduct:
productService.sellProduct(game.Players.EchoReaper, 100001, Enum.CurrencyType.Robux, function()
–will get run if and when player buys the product
print(“Player bought the product!”)
end)

productService.sellConsumable(game.Players.EchoReaper, 200002, 5, Enum.CurrencyType.Tix, function(newValue)
print(“Player just bought 5 consumables! Their new count is”, newValue)
end)[/code]

[size=6]Important notices:[/size]
[ul]
[li]This is intended to be used from a server script. Conceivably it should work from a local script, but if you experience issues with local scripts, that’s on you[/li]
[li]Due to the horrible way ROBLOX set up ProcessReceipt, you will have to use this for all of your developer products or not at all. I don’t really see this being that much of an issue considering you’d be using it since you likely don’t know how to use developer products on their own in the first place, but it’s best you know. ROBLOX can only handle one ProcessReceipt function at a time (their call not mine), so if you have this in your place and try to sell a developer product with your own ProcessReceipt function, one of the two is getting overwritten. Again, this likely won’t be an issue for you because if you’re using this it’s likely because you couldn’t use developer products in the first place[/li]
[li]If you don’t like something (i.e. the naming conventions), the module is open-source and you are free to take it and edit it to your heart’s content[/li]
[li]Since I already have a framework for this done, I’ll be using this in my projects from now on. If a ROBLOX update somehow manages to break the module or datastores/marketplaceservice are improved, I’ll know. I’ll keep this module up-to-date, so if you load it from the site instead of inserting it and packaging it with your game, you’ll get those updates as soon as I make them – if I even have to that is. I pretty much consider this done, and won’t be changing it unless a serious issue / possible improvement arises.[/li]
[/ul]

You
Are
Welcome!

2 Likes

This is awesome. As somebody who is more of a builder but enjoys making his stuff semi functional or fun, I can’t Thank You enough.

Just a heads up: Rename the ModuleScript to MainModule.

While I’m sure this wasn’t meant to be used remotely (i.e require(223666277)) if someone decides to do that, they shouldn’t have to have a broken game.

oohhh oops. Thank you! Had completely forgot about that ):

Resolved.

Is it odd that I just decided to see if you’d done that? Like, the only reason I even took the asset is to check that… Haha.

Odd? No. I would roll with eager to help. (That’s a compliment)

Just did, from [tt].lowerCamelCase( … )[/tt] to [tt]:PascalCase( … )[/tt], because that matches the rest of my code, considering my game’s largely object-oriented. :wink:

Thanks for making this module anyway, I may find this useful in the future when I do decide to add devprods.

Just did, from [tt].lowerCamelCase( … )[/tt] to [tt]:CamelCase( … )[/tt], because that matches the rest of my code, considering my game’s largely object-oriented. :wink:

Thanks for making this module anyway, I may find this useful in the future when I do decide to add devprods.[/quote]

I would have preferred it to be [tt]:CamelCase(…)[/tt] because that seems to be the convention for the ROBLOX API.

[quote] [quote=“Echo” post=145965]
[size=6]Important notices:[/size]
[ul]
[li]If you don’t like something (i.e. the naming conventions), the module is open-source and you are free to take it and edit it to your heart’s content[/li]
[/ul]
[/quote]
Just did, from [tt].lowerCamelCase( … )[/tt] to [tt]:CamelCase( … )[/tt], because that matches the rest of my code, considering my game’s largely object-oriented. :wink:

Thanks for making this module anyway, I may find this useful in the future when I do decide to add devprods.[/quote]

I would have preferred it to be [tt]:CamelCase(…)[/tt] because that seems to be the convention for the ROBLOX API.[/quote]Well, that as well. Yes.

I hate CamelCase… I always make my code like so:

variablesLikeThis

FunctionsLikeThis

That way I can do:

local ThisIsAFunction
local thisIsAVariable

thisIsAVariable = 1
function ThisIsAFunction()
print(thisIsAVariable *4)
end

I like defining my function names beforehand so I can see what I still have to do.

For some odd reason, I have serious problems with having articles like “A” and “the” in my variables/function names. It annoys me, and I usually try to leave them out. I wonder if other people have that problem.

I used to like lowerCamelCase, but have since converted to CamelCase.

Even though ROBLOX uses CamelCase for method names, I stuck with lowerCamelCase because that’s generally what everyone uses outside of ROBLOX.

thisIsCamelCase

ThisIsPascalCase

I was literally about to correct this post like um3k did.

thisIsCamelCase AndSoIsThis. It doesn’t matter whether you start with a capital or not, although ThisIsPascalCase andThisIsNot. All PascalCase is camelCase but not all camelCase is PascalCase.