> For the complete documentation index, see [llms.txt](https://docs.sourcedev.pro/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.sourcedev.pro/src-billing/custom-framework.md).

# Custom Framework

If you are using a framework other than QBox, QBCore, or ESX, you can still use the Billing System by implementing the Bridge API.

## Implementation Steps

### 1. Set Config

In your `config.lua`, set the framework to `'custom'`:

```lua
Config.Framework = 'custom'
```

### 2. Client-Side Bridge (`bridge/client.lua`)

Open `bridge/client.lua` and locate the `elseif fw == 'custom' then` blocks. You need to implement the following functions:

* `GetPlayerData()`: Should return a table with player information.
* `Notify(msg, type)`: Your framework's notification function.
* `GetNearbyPlayers()`: (Optional) If your framework has a specific way to get nearby players.

```lua
-- Example Client implementation
elseif fw == 'custom' then
    function Bridge.GetPlayerData()
        return exports['my-core']:GetPlayerData()
    end

    function Bridge.Notify(msg, type)
        exports['my-notifications']:Show(msg, type)
    end
end
```

### 3. Server-Side Bridge (`bridge/server.lua`)

Open `bridge/server.lua` and implement the core logic for money and player handling:

* `GetPlayer(source)`: Return your framework's player object.
* `GetPlayerBank(source)`: Return player's bank balance.
* `GetPlayerCash(source)`: Return player's cash balance.
* `RemoveMoney(source, amount, type)`: **CRITICAL** - Deduct money and return boolean.
* `AddMoney(source, amount, type)`: Add money to a player.

```lua
-- Example Server implementation
elseif fw == 'custom' then
    function Bridge.GetPlayer(source)
        return exports['my-core']:GetPlayer(source)
    end

    function Bridge.RemoveMoney(source, amount, type)
        local player = Bridge.GetPlayer(source)
        if player.money >= amount then
            player.removeMoney(amount, type)
            return true
        end
        return false
    end
end
```

### 4. Shared Bridge (`bridge/shared.lua`)

Ensure your framework detection logic is added to `bridge/shared.lua` if you want it to be auto-detected, or just rely on the manual `'custom'` setting.

***

## Required Return Formats

### Player Data

```lua
{
    identifier = "string",
    name = "string",
    job = {
        name = "string",
        label = "string",
        grade = number,
        isBoss = boolean
    }
}
```

### Money Functions

* `RemoveMoney` **MUST** return `true` if deduction was successful, and `false` otherwise. This is vital for preventing payment exploits.

***

## Testing Your Implementation

1. **Verify Startup:** Check the console for `[Billing Bridge] Framework set to: custom`.
2. **Verify Job Check:** Ensure you can open the tablet with an allowed job.
3. **Verify Money:**
   * Try to pay with not enough money (should fail).
   * Try to pay with enough money (should succeed and deduct).
4. **Verify Notifications:** Success/Error messages should appear using your framework's UI.

***

{% hint style="danger" %}
**Security Warning:** Never trust client-side data for money transactions. Always perform the final check and deduction on the server side within the bridge.
{% endhint %}
