Remote Function Returning Nil

I don’t understand why my remote function keeps on returning nil? I’m trying to see if the player owns a certain dev product so that they can unbox a crate. But instead, whenever the function is called, it returns a nil instead of true or false?? Any ideas why this is happening

I tried using a print statement and it prints “TRUE” for the server script, but it prints nil, false, nil for the local script.

ServerScript

event.OnServerInvoke = function(player ,id)
	
	warn("A")
	
	local MarketplaceService = game:GetService("MarketplaceService")
	
	MarketplaceService.ProcessReceipt = function(receiptInfo)
		
		local ID = id
		
		warn("B")
		
		local productId = receiptInfo.ProductId
		local playerId = receiptInfo.PlayerId
		local player = getPlayerFromId(playerId)
		
		if productId == ID then
			
			warn("TRUE")
			return true
			
		else
			
			warn("FALSE")
			return nil
			
		end
	
	end
	
end

Local Script

spin.MouseButton1Down:Connect(function()
	local canspin = true
	
	if canspin then
		canspin = false
		
	local id = 985025707
	warn("A")
	
	game:GetService("MarketplaceService"):PromptProductPurchase(player, id)
	
	local bool = game.ReplicatedStorage.Test:InvokeServer(id)
	
	while wait(1) do
	
	print("B")
	
	warn(bool)
		
		if bool == nil then
			
			warn("False")
			
			warn(bool)
			
		elseif bool == "Yes" then
			
			warn("True")
			
			warn(bool)
			
			break

	end
	
	canspin = true
	
	end
	end
end)

Why do you use a remotefunction for this? You need to use the MarketPlaceService.ProcessReceipt function for this and fire a RemoteEvent if someone can spin

Read more about it here:

MarketplaceService | Documentation - Roblox Creator Hub

You shouldn’t have processreceipt inside of a invoke event.
It returns nil because the invoke will not return anything as you just connected an event that isn’t called yet.

1 Like

I’m want the spinner gui to appear as well, I got it working with the actual item giver. I’m unsure how I’d make the GUI popup if the own it?

Use a RemoteEvent as I said before

How would I detect if they own the dev product via local script?

Dev products are a one-time purchase you can’t detect if they own it

I mean how would I know that they purchased it?

Here’s a link that I already show’d you before MarketplaceService | Documentation - Roblox Creator Hub be sure to make this on a script not a local one

Aside from what was already suggested; you should only set ProcessReceipt once, so don’t place it inside a RemoteEvent or RemoteFunction. This specific example is free of the bug because you then get player again using receiptInfo.PlayerId, but had you done it slightly differently you could have had players overwriting each other’s purchases.

1 Like

Don’t use RemoteFunctions at all, you don’t need to cross the client-server boundary here. There are some use examples of ProcessReceipt you can get off the Developer Hub about ProcessReceipt and working with developer products.

If you want the player to see when they’ve purchased a product with immediate feedback, use PromptProductPurchaseFinished. Although it does say deprecated and the usual spiel would be that you shouldn’t be using deprecated items, this item only has a deprecation tag to warn developers from misusing it to grant purchases over ProcessReceipt.

Beyond your initial problem which can be resolved by not using RemoteFunctions at all and using the above event, you’re using ProcessReceipt wrong. You must return a ProductPurchaseDecision Enum, either PurchaseGranted for a successful purchase and to tell Roblox that you should be given the money or NotProcessedYet to queue the purchase for later, for example, in case of error.

Developer products, next, are not necessarily “ownable” assets, they are monetary assets that can be purchased several times over. You should rework your system to account for this. For instance, the server should be keeping track of how many spins a player can perform through the purchase.

Finally, please don’t use loops where unnecessary. The specific loop you’re using is bad practice and the LocalScript will yield until InvokeServer returns anyway, removing the need to do any kind of manual waiting. By making a while loop after InvokeServer, you’re causing the script to wait unnecessarily.

3 Likes