BenzyMoney — Integrations
Step-by-step, copy-paste guides for wiring BenzyMoney into other resources (HUDs, phones, shops, and more). Each entry says exactly what to paste and where, so setting it up — or re-doing it after a script update — is quick. More integrations get added here over time.
Standalone setup. These guides assume BenzyMoney is your money system on a standalone server (no ESX/QBCore). In your
server.cfg, alwaysensure BenzyMoneybefore the resource you're integrating.
Contents
What integrations use
Most client-side integrations only need two things from BenzyMoney (the full API is in EXPORTS.md and EVENTS.md):
- Read your own balances —
exports.BenzyMoney:GetMyCash(),:GetMyBank(),:GetMyMoney()(→{ cash, bank, total }). Cheap local reads, always current. - Live updates — the client event
BenzyMoney:UpdateBalance({ cash, bank, total }) fires the instant either balance changes (and on load). TriggerBenzyMoney:RequestBalanceto ask BenzyMoney to push your current balances right now.
JG HUD
Tells jg-hud to read cash + bank from BenzyMoney and keep them updated live.
jg-hud's
Framework.*code is its own internal naming for "where to read data from" — it is not ESX/QBCore, and pointing it at BenzyMoney does not install a framework. You stay fully standalone.
1 — Set the framework (jg-hud config/config.lua)
Config.Framework = "auto"
BenzyMoney does not have dirty money, so also turn off the components it can't provide:
Config.ShowComponents.dirtyMoneyBalance = false
2 — Add the balance reader (jg-hud framework/cl-functions.lua)
Find function Framework.Client.GetBalance(type). If not using a framework, add this branch to its if / elseif chain — right after the ESX block:
elseif Config.Framework == "none" then
if type == "bank" then return exports.BenzyMoney:GetMyBank() or 0 end
if type == "cash" or type == "money" then return exports.BenzyMoney:GetMyCash() or 0 end
return 0 -- BenzyMoney has no dirty / black money
end
If using a framework, instead replace the contents of that framework's if / elseif block with:
if type == "bank" then return exports.BenzyMoney:GetMyBank() or 0 end
if type == "cash" or type == "money" then return exports.BenzyMoney:GetMyCash() or 0 end
return 0 -- BenzyMoney has no dirty / black money
3 — Add the live listener (jg-hud framework/cl-functions.lua)
Find function Framework.Client.CreateEventListeners(). If not using a framework, paste this block inside it (anywhere among the other if Config.Framework == ... blocks — e.g. just before the function's final end):
if Config.Framework == "none" then
RegisterNetEvent("BenzyMoney:UpdateBalance", function(data)
Framework.CachedPlayerData.cash = data.cash
Framework.CachedPlayerData.bank = data.bank
end)
TriggerServerEvent("BenzyMoney:RequestBalance") -- pull the current values right now
end
If using a framework, instead replace the contents of that framework's block with:
RegisterNetEvent("BenzyMoney:UpdateBalance", function(data)
Framework.CachedPlayerData.cash = data.cash
Framework.CachedPlayerData.bank = data.bank
end)
TriggerServerEvent("BenzyMoney:RequestBalance") -- pull the current values right now
Done
Restart jg-hud. Cash + bank now come from BenzyMoney and update the instant a balance changes. Login works automatically — any non-QB/ESX framework value (like "Benzy") uses jg-hud's built-in standalone login path.
GKSPHONE
Makes GKSPhone use BenzyMoney as its money backend, so the phone and the /money menu share the same balances. Covers your bank balance (kept live in the bank app), player-to-player bank transfers (online or offline), every in-app purchase the phone charges for (SIM packages, ads, valet, Squawk Verified, screen and battery repairs, phone recovery, …), and Job Center payouts — they all run through the same bank functions.
Scope. Every operation that spends or receives player money is covered, because it all runs through the bank functions you wire below. Not covered: the phone is bank-only, so no cash, deposit/withdraw, or money requests (those stay in the
/moneymenu and at ATMs); and society money — theSociety*functions inserver/bank/, picked byConfig.BankScript— isn't wired: tips, business bills, and society balances all need a job, and GKSPhone has no jobs on standalone. The SIM data allowance (MB) is GKSPhone's own internal resource, not money. Because every phone money move flows through BenzyMoney, the/moneymenu (and theGetTransactionsexport) is the complete history; the phone's own history tab still shows only what the phone itself did.
1 — Set the framework (gksphone config/config.lua)
Config.Framework = "standalone"
The default, "auto", also picks standalone when no ESX/QBCore/Qbox is running — setting it explicitly just removes the guesswork.
2 — Wire the bank money functions (gksphone server/bank/framework.lua)
The first if Config.Framework == ... block in this file ends with an else branch holding the standalone stubs — GetBankBalance, GetBankBalanceByIndetifier, RemoveBankMoney, and AddBankMoney, which just return 0 / return true. Replace those four functions with:
function GetBankBalance(source)
return exports.BenzyMoney:GetBank(source) or 0
end
function GetBankBalanceByIndetifier(identifier)
return exports.BenzyMoney:GetBank(identifier) or 0
end
function RemoveBankMoney(source, amount, type)
amount = tonumber(amount)
if not amount or amount < 0 then return false end
amount = math.ceil(amount) -- charges round up to a whole amount
if amount == 0 then return true end -- a free price
return exports.BenzyMoney:RemoveBank(source, amount, "GKSPhone") and true or false
end
function AddBankMoney(source, amount, type)
amount = tonumber(amount)
if not amount or amount < 0 then return false end
amount = math.floor(amount) -- payouts round down to a whole amount
if amount == 0 then return true end
return exports.BenzyMoney:AddBank(source, amount, "GKSPhone") and true or false
end
Edit them right there — this file defines these four functions on every setup, so a copy placed in another file (such as server/bank/custom.lua) can be overwritten by the stubs.
source is a server id, or a license:… identifier when GKSPhone passes type = "identifier" — BenzyMoney resolves both and works offline, so there's no need to branch on type. BenzyMoney only moves whole, positive amounts, so a free (0) price succeeds without touching the balance, and a fractional amount (from a price markup) is rounded up when charging and down when paying out — rounding can never create money.
3 — Wire offline transfers (gksphone server/framework/standalone.lua)
Replace the whole GetOfflinePlayerByIdentifier function. GKSPhone uses it whenever it moves money by identifier rather than by server id — every transfer to an offline recipient (Config.OfflineBankTransfer), and both sides of every transfer when Config.MetaBankTransfer is on (where the money comes from the phone's registered owner rather than whoever's holding it) — so those move BenzyMoney money too:
function GetOfflinePlayerByIdentifier(identifier)
local data = exports.BenzyMoney:GetPlayerData(identifier)
if not data then return nil end -- not a BenzyMoney player
local self = {}
function self.getAccount(account)
local bal = exports.BenzyMoney:GetBalances(identifier)
if bal then return { money = (account == "cash") and bal.cash or bal.bank } end
return nil
end
function self.removeAccountMoney(account, amount, reason)
return exports.BenzyMoney:RemoveMoney(identifier, account == "cash" and "cash" or "bank", amount, reason or "GKSPhone") and true or false
end
function self.addAccountMoney(account, amount, reason)
return exports.BenzyMoney:AddMoney(identifier, account == "cash" and "cash" or "bank", amount, reason or "GKSPhone") and true or false
end
function self.getName()
return data.name or ""
end
return self
end
Returning nil for someone BenzyMoney has never seen is what GKSPhone's own ESX/QBCore versions do, so an offline transfer to an unknown player is refused instead of charging the sender for money that can't arrive.
4 — Wire the client balance (gksphone client/framework/standalone.lua)
Replace GetPlayerBankBalance (including the commented-out block inside it) with the function below, and paste the listener right under it. The listener pushes each BenzyMoney balance change into the bank app the moment it happens — the same live update GKSPhone does on ESX/QBCore:
function GetPlayerBankBalance()
return exports.BenzyMoney:GetMyBank() or 0
end
RegisterNetEvent("BenzyMoney:UpdateBalance", function(data)
if type(data) == "table" and data.bank then
SendNUIMessage({ action = "UpdateBankBalance", bankMoney = data.bank })
end
end)
Done
ensure BenzyMoney before gksphone in your server.cfg, then restart. The phone bank app now shows your BenzyMoney bank and keeps it current while open, and its transfers and purchases move BenzyMoney money — fully in sync with the /money menu.
Notes
- GKSPhone identifies players by
license:…, which is exactly what BenzyMoney keys on — no mapping needed. - GKSPhone's transfer tax (
Config.BankTransferTax) is taken from the sender and removed from circulation (its normal behavior); set it to0for no fee. - Leave
Config.BankScriptas it is — it only chooses where society money goes (see the scope note), never player money.
Prompt Studio Train Script
Charges the train script's ticket fares through BenzyMoney, so they leave the same cash/bank balance the /money menu shows.
Route the fare through BenzyMoney (train script config/server.lua)
Paste at the bottom of the file. Bridge is global there and config is already local to it, so this redefines the one function the script set up above — re-pasting it is all a script update needs:
-- BenzyMoney -- take the fare from the player's configured account.
function Bridge.removePayment(source, amount)
return exports.BenzyMoney:RemoveMoney(source, config.paymentMethod, amount, 'Train ticket') and true or false
end
Done
ensure BenzyMoney before the train script in your server.cfg, then restart. Buying a ticket now debits BenzyMoney, and every fare lands in the /money history and your Discord log.
Optional — keep the fare instead of destroying it. By default the fare just leaves the player. To bank it somewhere instead, use this removePayment — the account key is either 'government' for the government/society account, or a business key from Config.Businesses:
function Bridge.removePayment(source, amount)
if not exports.BenzyMoney:RemoveMoney(source, config.paymentMethod, amount, 'Train ticket') then return false end
exports.BenzyMoney:AddToAccount('government', amount, 'Train fare') -- or a business key from Config.Businesses
return true
end
Notes
- A player who can't afford the fare is refused the ticket (
RemoveMoneyreturnsfalse), so it is never handed over free. paymentMethod(train scriptconfig/config.lua) picks which balance a fare comes out of. Leave it at'cash'or'bank'— both map straight onto BenzyMoney's accounts, so no mapping is needed.- Fares stay the train script's own numbers (
tickets.defaultPrice, plus per-stationtickets.prices), andframework/inventorystay as they are — BenzyMoney only moves the amount.