Recently I have been working on some rather unusual things that are of zero relevance to me, quite frankly, just for fun. One of these projects is an in-game subscription system, now it isn’t the best but it works, you may want to slightly revamp this. But it simply is just a draft, I wrote it all in one session, anyway, here it is, thanks!
--Created by YellowTripleG, https://www.roblox.com/users/119187141
local dataService = game:GetService("DataStoreService")
local subDat = dataService:GetDataStore("isSubscribed")
local purchaseHistoryStore = dataService:GetDataStore("purchaseHistory")
local marketServ = game:GetService("MarketplaceService")
local Players = game:GetService("Players")
local thirtyDays = 2592000
local subscriptionId = 0
function createInst(Parent,Name,Type)
local c = Instance.new(Type)
c.Name = Name
c.Parent = Parent
return c
end
game.Players.PlayerAdded:Connect(function(Player)
local data
local currentDate = os.time()
local success, err = pcall(function()
data = subDat:GetAsync(Player.UserId) or nil
end)
if success then
if data ~= nil then
if currentDate >= data + thirtyDays then
print('Subscription Ended!')
local success1, err1 = pcall(function()
subDat:RemoveAsync(Player.UserId)
end)
if err1 then
error(err1)
end
marketServ:PromptProductPurchase(Player,subscriptionId)
else
local daysLeft = math. floor(((data + thirtyDays) - currentDate)/86400 + 0.5)
print(daysLeft..' days left!')
local subInfo = createInst(Player,"subInfo","Folder")
local isSubbed = createInst(Player.subInfo,"isSubscribed","StringValue")
local subDays = createInst(Player.subInfo,"subDays","StringValue")
while wait(1) do
local newD
currentDate = os.time()
local success2, err2 = pcall(function()
newD = subDat:GetAsync(Player.UserId)
end)
if success2 then
isSubbed.Value = (newD + thirtyDays) - currentDate
subDays.Value = math. floor(((newD + thirtyDays) - currentDate)/86400 + 0.5)
else
error(err2)
end
end
end
end
else
error(err)
end
end)
local productFunctions = {}
productFunctions[subscriptionId] = function(receipt, Player)
if Player then
if not Player:FindFirstChild("subInfo") then
local subInfo = createInst(Player,"subInfo","Folder")
local isSubbed = createInst(Player.subInfo,"isSubscribed","StringValue")
local subDays = createInst(Player.subInfo,"subDays","StringValue")
end
local success, err = pcall(function()
subDat:SetAsync(Player.UserId,os.time())
end)
while wait(1) do
local newD
local currentDate = os.time()
local success2, err2 = pcall(function()
newD = subDat:GetAsync(Player.UserId)
end)
if success2 then
Player:WaitForChild("subInfo").isSubscribed.Value = (newD + thirtyDays) - currentDate
Player:WaitForChild("subInfo").subDays.Value = math. floor(((newD + thirtyDays) - currentDate)/86400 + 0.5)
else
error(err2)
end
end
if err then
error(err)
else
return true
end
end
end
local function processReceipt(receiptInfo)
local playerProductKey = receiptInfo.PlayerId .. "_" .. receiptInfo.PurchaseId
print(playerProductKey)
local purchased = false
local success, errorMessage = pcall(function()
purchased = purchaseHistoryStore:GetAsync(playerProductKey)
end)
if success and purchased then
return Enum.ProductPurchaseDecision.PurchaseGranted
elseif not success then
error("Data store error:" .. errorMessage)
end
local player = Players:GetPlayerByUserId(receiptInfo.PlayerId)
if not player then
return Enum.ProductPurchaseDecision.NotProcessedYet
end
local handler = productFunctions[receiptInfo.ProductId]
local success, result = pcall(handler, receiptInfo, player)
if not success or not result then
warn("Error occurred while processing a product purchase")
print("ProductId:", receiptInfo.ProductId)
print("Player:", player)
return Enum.ProductPurchaseDecision.NotProcessedYet
end
local success, errorMessage = pcall(function()
purchaseHistoryStore:SetAsync(playerProductKey, true)
end)
if not success then
error("Cannot save purchase data: " .. errorMessage)
end
return Enum.ProductPurchaseDecision.PurchaseGranted
end
marketServ.ProcessReceipt = processReceipt