Need Help Using Webhooks on Clothing Purchase

:wave: Hello,
I’m currently trying to get it so whenever someone purchases clothing from my game it sends a webhook to a Discord channel. I’ve got everything working, except for one thing: since the script that sends the purchase data (player’s username & the clothing’s name) isn’t local, I can’t fire the server.

The workaround I tried was to send the purchase data through another remote from a local script (maybe a security concern, I’m not exactly sure). This sort of works, however, I need to place the local script in StartPlayerScripts/ReplicatedFirst/StarterGui for it to (mostly) work.

Whenever I purchase something in-game, it will send a message with what appears to be the correct data (image below). Though since it’s handled locally it will sometimes work, sending the correct name & user profile, other times not so much.

image

Here’s a simplified version of the main clothing script (located in a Folder in the Workspace):

local MPS = game:GetService("MarketplaceService")
local Remotes = game:GetService("ReplicatedStorage").Remotes

for i,Clothing in pairs(script.Parent:GetChildren()) do
	if Clothing.Name == "ClothingItem" then
		-- code here that prompts purchases for item
	end
end)

MPS.PromptPurchaseFinished:Connect(function(Player, ProductId, IsPurchased)
	if IsPurchased == true then
		Remotes.PurchItem:FireAllClients(MPSClothing.Name, tostring(Player))
	end
end)

Aaaand the Local Script (Currently located in ReplicatedFirst):

local Remotes = game:GetService("ReplicatedStorage").Remotes
local MPS = game:GetService("MarketplaceService")
local Players = game:GetService("Players")

Remotes.PurchItem.OnClientEvent:Connect(function(clothingName, playerName)
	if Players:FindFirstChild(tostring(playerName)) then
		Remotes.WebhookFeedback:FireServer(clothingName, playerName)
	end
end)

And FINALLY, here’s the Webhook script (located in a Folder in ServerScriptService):

local HS = game:GetService("HttpService")
local Remotes = game:GetService("ReplicatedStorage").Remotes
local WebhookURL = "https://discord.com/api/webhooks/" -- insert webhook URL here
local Debounce = false

Remotes.WebhookFeedback.OnServerEvent:Connect(function(playerName, clothingName)
	if Debounce == false then
		Debounce = true

		local MessageData = {
			['embeds'] = {{
				color = 250100;
				title = "**Clothing Purchase!**";
				description = tostring(clothingName);
				thumbnail = {
					url = "https://web.roblox.com/Thumbs/Avatar.ashx?x=100&y=100&Format=Png&userid="..game.Players[tostring(playerName)].UserId..""
				};
				fields = {
					{
						name = "Purchased by "..tostring(playerName).."!";
						value = "https://www.roblox.com/users/"..game.Players[tostring(playerName)].UserId.."/profile";
					};
				};
				footer = {
					text = "Frozen Apparel Homestore"
				};
			}}
		}

		MessageData = HS:JSONEncode(MessageData)

		HS:PostAsync(WebhookURL, MessageData)
		wait(3)
		Debounce = false
	end

end)

Any help would be very greatly appreciated! :smile:

Hello nyawcola!

There are a couple major concerns with your code here! One major concern I notice is that webhooks are being triggered via your client. This can cause major issues with exploiters spamming your remotes and flooding your webhook.

You should look into a BindableEvent on the serverside to control webhook data. Asking a client to prompt a webhook is not a good idea at all.

There is no reason to fire to a client and have that client fire back to a different remote with the same information when you can just use a BindableEvent.

1 Like

Thanks! Will look into that. I figured handling it locally would be a concern.