Can the MarketplaceService.ProcessReceipt yield?

function game:GetService("MarketplaceService").ProcessReceipt(info)
    local purchased = GetValue(info.PurchaseId..'_'..tostring(info.PlayerId))
    if purchased==true then
        return Enum.ProductPurchaseDecision.PurchaseGranted
    elseif purchased==false then
        return nil
    end
    -- if the value is nil then the purchase has not been processed
end

Basically I have function called GetValue that attempts to call GetAsync like 7 times.
And it yields 0.5 seconds in between each attempt.
So my question is can this callback function yield?

While I haven’t tested this myself, I believe logically and from reading the wiki page that it logically would have to yield as the wiki said that it is “called multiple times until it returns”. So I feel like it would be safe to assume that the callback function yields.

1 Like

I would assume it has to yield as it is essentially a web call, so it has to complete the web operation before it can return a correct result.

Yes, it can Yield

Process Reciept can Yield, with functions like :GetAsync()

It is not like functions like :UpdateAsync().

As for yielding itself, it just makes a callback. Not sure which yield you meant.


Reasoning

Roblox’s example of process receipt uses DataStores;

local success, errorMessage = pcall(function()
   purchaseHistoryStore:SetAsync(playerProductKey, true)
end)

Which I know for a fact have yields, so I think you are in the clear. I don’t think you should be doing return nil. Try doing return Enum.ProductPurchaseDecision.NotProcessedYet

Yes, ProcessReceipt can yield.

Why? Don’t do that. This is bad practice. You’re unnecessarily wasting your DataStore Get requests budget. Cache your data in a ModuleScript or ValueObjects instead.

Don’t return nil for failed purchases, return Enum.ProductPurchaseDecision.NotProcessedYet. This is the canonical way to signify that a purchase should not be processed and should wait until ProcessReceipt is ran again, or refund money if a purchase isn’t granted within a specific time window (I believe the window is 3 days).


@Computer2467

Don’t cherry pick wording from articles off the Developer Hub - read carefully.

After a player makes a purchase through a PromptProductPurchase() dialog, this callback is called multiple times until it returns Enum.ProductPurchaseDecision.PurchaseGranted .

The function defined to ProcessReceipt is called multiple times during play sessions (two highlighted scenarios being when a player joins or purchases another product). Until PurchaseGranted is returned or the window to grant the purchase expires, this function will keep getting called (not in continuous succession though, to clarify).

A function having yielding statements is a different matter altogether.


@REALTimothy0812

ProcessReceipt isn’t a connection, it’s a callback.

It doesn’t do so immediately. I don’t even think you’re supposed to return nil.

Basically I have function called GetValue that attempts to call GetAsync like 7 times.

Yeah I was wondering if that was good practice or not.

No, it’s not.You should be saving in a single key and scope by putting your data into a table.
Convert:
-DataStore1 for coins
-DataStore2 for gems
-Datastore3 for kills
-ect.
To:
-DataStore 1 for {coins,gems,kills}

Yes, it can yield. If you want an engineer’s opinion on it:

1 Like