# Интеграции

cxg-tattoos подключается к разным framework для списания оплаты и проверки административных прав. Интеграция системы внешнего вида повторно применяет сохранённые татуировки при загрузке персонажа или смене skin. Каждая часть настраивается отдельно.

См. также [Введение](https://docs.cxgstudios.com/docs/ru/01-cxg-tattoos/01-introduccion.md), [Установка](https://docs.cxgstudios.com/docs/ru/01-cxg-tattoos/02-instalacion.md), [Настройка](https://docs.cxgstudios.com/docs/ru/01-cxg-tattoos/03-configuracion.md), [Каталог](https://docs.cxgstudios.com/docs/ru/01-cxg-tattoos/04-catalogo.md) и [Интерфейс](https://docs.cxgstudios.com/docs/ru/01-cxg-tattoos/06-interfaz.md).

## Доступные framework

| Система | Идентификатор конфигурации | Ресурс по умолчанию | Платежи | Права |
| --- | --- | --- | --- | --- |
| Qbox | `qbx` | `qbx_core` | Да | Да |
| QBCore | `qbcore` | `qb-core` | Да | Да |
| ESX | `esx` | `es_extended` | Да | Да |
| Без framework | `standalone` | Не применяется | Собственный callback или бесплатные покупки | ACE или собственная проверка |

В режиме `auto` ресурс определяет запущенные Qbox, QBCore или ESX; если ни один не найден, используется `standalone`. Можно указать framework явно, если на сервере одновременно работают несколько framework или используется другое имя ресурса:

```lua
Config.Purchases.framework = 'qbx' -- auto | qbx | qbcore | esx | standalone
Config.Purchases.resources.qbx = 'qbx_core'
Config.Purchases.accounts = { 'cash', 'bank' }
Config.Purchases.esxAccountMap.cash = 'money'
Config.Purchases.esxAccountMap.bank = 'bank'
Config.Purchases.allowFreePurchases = false
```

Счета проверяются в указанном порядке. Списание производится только с одного счёта; если средств недостаточно, проверяется следующий. В ESX параметр `esxAccountMap` сопоставляет `cash` со счётом `money`.

`Config.Purchases.reason` и `refundReason` указывают причину операций для providers, которые её поддерживают. Начальные значения — `tattoo-purchase` и `tattoo-purchase-refund`. Параметр `allowFreePurchases` разрешает пропускать списание в адаптере standalone; он не делает бесплатными покупки через другие framework.

## Платежи без framework

В режиме `standalone` подключите `tryCharge` и `refund` к экономике сервера. Оба callback необходимы для покупок: возврат нужен, чтобы вернуть списанную сумму, если сохранить татуировку не удалось.

```lua
Config.Purchases.framework = 'standalone'
Config.Purchases.standalone.tryCharge = function(source, totalAmount, context)
    -- Sustituye esta llamada por la API de economía de tu servidor.
    local charged, receipt = MyEconomy.charge(source, totalAmount, context)
    if charged then
        return true, receipt
    end
    return false, 'No tienes saldo suficiente.'
end

Config.Purchases.standalone.refund = function(source, totalAmount, context, receiptData)
    -- Usa receiptData para devolver el mismo cobro aprobado.
    return MyEconomy.refund(source, totalAmount, receiptData) == true
end
```

`MyEconomy` — условное имя API сервера; замените его фактическим названием и вызовами. Чтобы намеренно разрешить бесплатные покупки, установите `allowFreePurchases = true`.

Адаптеры платежей предоставляют методы `isAvailable(settings)`, `charge(source, amount, context, settings)` и `refund(source, amount, context, settings)`. После одобрения платежа квитанция должна сохраняться в `context.paymentReceipt`; cxg-tattoos использует его, чтобы направлять возврат в ту же платёжную систему. Для собственной экономики настройте callback `tryCharge` и `refund` в `standalone`.

## Административные права

Права проверяются на сервере при открытии административной панели и выполнении операций в ней. Скрытие или изменение клиентского интерфейса не предоставляет доступ.

Начальная конфигурация использует обнаруженный framework и ACE как резервный способ:

```lua
Config.Permissions = {
    framework = 'auto', -- auto | qbx | qbcore | esx | standalone
    mode = 'hybrid',    -- framework | ace | hybrid | custom
    acePrefix = 'cxg-tattoos.',
    resources = {
        qbx = 'qbx_core',
        qbcore = 'qb-core',
        esx = 'es_extended',
    },
    bindings = {
        admin = {
            ace = { 'cxg-tattoos.admin', 'group.admin', 'admin' },
            qbx = { 'god', 'admin', 'group.admin' },
            qbcore = { 'god', 'admin', 'group.admin' },
            esx = { 'superadmin', 'admin' },
        },
    },
}
```

Режим `framework` проверяет роли framework. Режим `ace` использует записи ACE из binding. `hybrid` разрешает любой из этих способов. В `standalone` авторизация через framework недоступна; настройте ACE или собственную проверку.

Например, чтобы разрешить доступ principal ACE `group.admin`:

```cfg
add_ace group.admin cxg-tattoos.admin allow
```

Чтобы передать решение собственной системе, используйте `mode = 'custom'`. Callback получает идентификатор игрока, право, контекст операции и настроенный binding; доступ разрешает только логическое значение `true`:

```lua
Config.Permissions.mode = 'custom'
Config.Permissions.custom = {
    hasPermission = function(source, permission, context, binding)
        return exports.my_permissions:hasPermission(source, permission) == true
    end,
}
```

Замените `my_permissions` согласно API, установленному на сервере. Если callback отсутствует, завершается ошибкой или возвращает любое другое значение, доступ запрещается.

Настраивается и команда открытия панели. `permission` должен совпадать с одним из ключей `Config.Permissions.bindings`:

```lua
Config.AdminCommand.enabled = true
Config.AdminCommand.name = 'tattooadmin'
Config.AdminCommand.permission = 'admin'
```

С этими параметрами право `admin` защищает команду `/tattooadmin` и административные операции. Установите `enabled = false`, чтобы отключить команду; проверка прав в остальных административных операциях продолжит выполняться.

### Редактируемые файлы интеграции

В редактируемых bridge-модулях собраны подключения к внешним системам. Для собственных прав или платежей предпочтительно настроить описанные выше callback. Если вы изменяете существующий bridge-модуль, сохраните его контракт:

| Файл или группа | Назначение | Контракт адаптера |
| --- | --- | --- |
| `bridge/permissions/server.lua` | Выбор framework и применение режима `framework`, `ace`, `hybrid` или `custom` | `TattooPermissions.Has(source, permission, context)` возвращает `true` только при разрешённом доступе |
| `bridge/permissions/registry.lua` | Регистрация и общие инструменты для прав | `TattooPermissionBridge.register(name, adapter)` |
| `bridge/permissions/qbx.lua`, `qbcore.lua`, `esx.lua`, `standalone.lua` | Проверки для каждого framework или режима без framework | `isAvailable(settings)` и `hasPermission(source, binding, settings, permission)`; при адаптации можно добавить `context` |
| `bridge/payments/server.lua` | Выбор provider, списание и возврат | `Config.TryChargePlayer(source, totalAmount, context)` и `Config.RefundPlayer(source, totalAmount, context)` |
| `bridge/payments/registry.lua` | Регистрация и общие инструменты платежей | `TattooPaymentBridge.register(name, adapter)` и инструменты работы с квитанциями |
| `bridge/payments/qbx.lua`, `qbcore.lua`, `esx.lua`, `standalone.lua` | Операции оплаты через framework или собственные callback | `isAvailable(settings)`, `charge(...)` и `refund(...)` |
| `bridge/appearance.lua` | События загрузки skin и запрос сохранённых татуировок | Запрашивает список татуировок персонажа и применяет его после загрузки внешнего вида |

Когда bridge вызывает callback прав, он также передаёт `context` пятым аргументом. В реестре есть включённые providers (`qbx`, `qbcore`, `esx`, `standalone`); для пользовательских вариантов добавлять нового provider не требуется.

В адаптере платежей сохраняйте квитанцию через `TattooPaymentBridge.setReceipt(context, provider, account, amount, identifier, data)`. При возврате проверьте того же provider и сумму вызовом `getReceipt(context, provider, amount)`, а после подтверждённого возврата отметьте квитанцию как возвращённую. Адаптируйте файл нужного provider; для собственной интеграции без изменения адаптеров используйте standalone callback.

## Внешность и загрузка персонажа

Ресурс отслеживает стандартные события `illenium-appearance`, `fivem-appearance`, QBCore, ESX и `spawnmanager`, а затем загружает сохранённые татуировки и применяет их повторно. В Qbox настройка предпросмотра multicharacter использует `playerskins.skin`, чтобы показывать сохранённые татуировки на экране выбора персонажа.

Если ваша система внешнего вида использует другое событие, запросите применение после завершения загрузки skin:

```lua
TriggerServerEvent('cxg-tattoos:fetchMyTattoos')
```

Событие возвращает клиенту татуировки текущего персонажа. Не отправляйте список из источника, выбранного игроком: принадлежность проверяется и определяется на сервере.

Предпросмотр multicharacter в Qbox настраивается следующими полями:

```lua
Config.QbxMulticharacterPreview.enabled = true
Config.QbxMulticharacterPreview.resource = 'qbx_core'
Config.QbxMulticharacterPreview.playerskinsTable = 'playerskins'
Config.QbxMulticharacterPreview.playersTable = 'players'
Config.QbxMulticharacterPreview.syncExistingOnStart = true
```

`enabled` включает интеграцию; `resource` задаёт установленное имя Qbox. `playerskinsTable` и `playersTable` указывают таблицы внешнего вида и персонажей, используемые этой установкой. `syncExistingOnStart` позволяет синхронизировать уже сохранённые татуировки при запуске cxg-tattoos, чтобы они отображались и на экране выбора персонажа multicharacter. Если на сервере таблицы переименованы, измените эти два поля. Менять `qbx_core` не нужно.
