Overview
How categories & rewards work
This page explains the model behind the shop: how a category becomes a set of products, and how buying one actually delivers something to the player.
The three pieces of a category
A working category needs three things:
A config entry in
Config.Categories(name+label) so the shop knows the category exists.Products in the
vip_productstable (added from the admin panel).A reward handler registered with
RegisterRewardso the server knows how to deliver the products in that category.
If any of the three is missing, the category won't work: no config = it won't show; no products = it's empty; no handler = purchases fail with a delivery error.
The reward pipeline
Every purchase and gift runs through a single hardened pipeline on the server (in the escrow‑protected core). In order:
Validate — the product exists, isn't a web link, the buyer meets the VIP requirement, and the buyer has enough of the right currency.
Reserve stock — stock is decremented atomically in the database (
stock ≥ 9999means unlimited and is never decremented). A per‑player lock prevents double‑spends.Deliver — your category's reward handler runs inside a protected call.
Settle — only if delivery succeeds, the buyer is charged, the purchase is logged, notifications are sent, and the token/category state is refreshed.
Deliver before charge. If the handler throws an error or returns false, the reserved stock is refunded and the player is never charged. This is what makes the shop exploit‑resistant.
The reward handler contract
A handler is a function you register for a category. It receives a single payload table and returns whether delivery succeeded:
Always deliver to payload.recipient, not payload.source. For a normal purchase they're the same player, but for a gift the recipient is the wishlist owner — using payload.source would hand the item to the wrong person.
Where handlers live
The default handlers ship in server/editable/_<category>.lua (for example _vehicles.lua, _items.lua, _money.lua, _vip.lua, _business.lua, _peds.lua, _weapons.lua). These files are meant to be customized for your framework — they contain the actual database inserts, item grants and money calls. Editable helpers you'll reuse (like generatePlate, getMoney, Round) live in server/editable/functions.lua and server/editable/buy.lua.
Keep your credential/delivery logic in the editable files and let the escrow‑protected core handle the pipeline. That way you can adapt AV VIP to any framework without touching the secure logic.
Last updated