A simple question, is it like pcall? Like when a purchase fail it does something about it? Because When I’m trying to read it from the docs I just complicate stuff for no reason.
ProcessReceipt MUST be used in order to handle purchases in your game. It gets called when a player makes a purchase, and it’s where you should be granting rewards. If you successfully grant the reward, then you should return PurchaseGranted. Otherwise, return NotProcessedYet, so that it will be called again later and try again.
There are a lot of nuances with the implementation in order to avoid data loss scenarios that can lead to duplicate reward granting, or no reward being granted for a purchase, or other things that you should be careful about.
Any time you’re taking someone’s money, you need to be extra diligent about your implementation of handling that purchase to avoid taking their money without giving them what they purchased, and secondly to avoid giving them more than they purchased in the duplication case.
Really take your time to fully understand the documentation around this, because you don’t want to mess this up. I emphasize once more: Handling purchases needs to be done with care to avoid scamming your players. There’s nothing extraneous in the documentation. It’s all necessary for a correct best-practice implementation. It is complicated, and that’s the unfortunate nature of non-atomic data transactions. You need things like session locking and receipt tracking for a correct implementation.
I might be misunderstanding
ProcessReceipt is the offical way of granting the player what the gamepass/ devproduct promises them? Like VIP for example that makes humanoidspeed = 20 and when playey buys that devproduct ProcessReceipt makes humanoidseed = 20
That’s correct. The flow is
- You set the ProcessReceipt function
- Player makes a purchase
- Roblox calls your ProcessReceipt function with the details of the purchase
- Your ProcessReceipt function handles the purchase, like saving their purchase to datastore, changing their walkspeed, etc.
- Your ProcessReceipt function returns PurchaseGranted so that Roblox knows you are done handling the purchase
- If for some reason you couldn’t handle the purchase (e.g. the player is not in the server so they have no humanoid to change walkspeed), then you need to return NotProcessedYet.
- If you returned NotProcessedYet, the ProcessReceipt function will be called again in the future to try again. The times it is called again I believe are if they make another purchase or join a server.
That’s correct. The flow is
- You set the ProcessReceipt function
- Player makes a purchase
- Roblox calls your ProcessReceipt function with the details of the purchase
- Your ProcessReceipt function handles the purchase, like saving their purchase to datastore, changing their walkspeed, etc.
- Your ProcessReceipt function returns PurchaseGranted so that Roblox knows you are done handling the purchase
- If for some reason you couldn’t handle the purchase (e.g. the player is not in the server so they have no humanoid to change walkspeed), then you need to return NotProcessedYet.
- If you returned NotProcessedYet, the ProcessReceipt function will be called again in the future to try again. The times it is called again I believe are if they make another purchase or join a server.
The biggest problematic cases you have to be aware of are
- ProcessReceipt can be called more than once for the same purchase, so you need to ensure you don’t grant a second time if the first handler is still ongoing. An in-memory table of purchases being processed solves this.
- ProcessReceipt can be called for the same purchase in multiple servers if the player joins another server while the previous server is still processing the purchase. This is where session locking the player data is important, so the new server avoids processing it if the previous server is still holding a lock on their data.
Is there another way rather than ProcessReceipt for granting promised rewards? and is it the safest way?
It is the only way you should be handling purchases.
One last question, PromptPurchase is like for donations since it doesn’t grant anything and ProcessReceipt is for granting player stuff for purchasing a devproduct right?
PromptPurchase is how you initiate the purchase prompt on the player’s screen.
Once they complete the purchase, that generates a receipt, which Roblox passes as a parameter to ProcessReceipt.
ProcessReceipt is simply a function that handles the result of any purchase from the player. It’s not a different way of prompting a purchase.
For something like a donation (which functionally is the same as any other dev product purchase), your ProcessReceipt will still get called with their receipt, but you wouldn’t need to do anything with it except record their donation in data and return PurchaseGranted.