Building onto @Mubinets 's response, I used
Roproxy as a free Roblox proxy and created this functional system:
When you make a gamepass purchase, it will check the proxy to make sure you own it fully. When it verifies you do, it’ll call the ‘onPurchased’ function with ‘player’ and ‘gamepassId’. Due to the nature of it, it will not work in studio, however I have tested it and verified it does work in live games. I tested this with gamepasses that cost 1 robux that I did not own prior.
I implemented a method that will not attempt to reach out to the website if the same gamepass is somehow purchased twice in-game, which should not be possible without the use of exploits. That was in light of trying to prevent them from overloading the web request limit, however, this could be abused if they discover this code and it will likely need some form of rate-limiting if you are to counteract that problem specifically.
If you have any problems with this, you can always reach out to me, I do have a lot of experience with proxies and setting up web servers.
local onPurchased = function(player,gamepassId)
print(player,gamepassId)
end
-- functions:
local marketplaceService = game:GetService("MarketplaceService")
local httpService = game:GetService("HttpService")
local lastPurchases = {}
local apiUrl = "https://inventory.roproxy.com/v1/users/%s/items/1/%s/is-owned"
local request = function(url)
local success,response = pcall(function()
return httpService:RequestAsync({
["Url"] = url,
["Method"] = "GET"
})
end)
if success then
return true,response
else
return false,response
end
end
local try = function(url,attempts)
local attempt,success,response = 0,false,nil
while(attempt <= attempts and not success) do
attempt += 1
success,response = request(url)
end
if success and response then
local contentType = response.Headers["content-type"]
if contentType:find("json") then
response.Body = httpService:JSONDecode(response.Body)
end
end
return success,response
end
marketplaceService.PromptGamePassPurchaseFinished:Connect(function(player,gamepassId,wasPurchased)
if wasPurchased then
lastPurchases[player] = lastPurchases[player] or {}
if not lastPurchases[player][gamepassId] then
lastPurchases[player][gamepassId] = tick()
local success,response = try(apiUrl:format(player.UserId,gamepassId),5)
if success and response and response.StatusCode == 200 then
local ownsGamepass = response.Body
if ownsGamepass then
onPurchased(player,gamepassId)
end
end
end
end
end)
However, this is quite a bit larger than the 4 lines of code Roblox could provide us in one method, and I wish it wasn’t this nuanced. So I also do agree to the annoyance. I provided this solution because Roblox themselves have not replied to this thread and I’m not sure that they will.