Agency Docs
QBESXStandalone

Agency-Phone Apps Personalizadas

Ahora con AgencyOS27: una actualización gratuita para todos los que ya tienen el teléfono.

v27.1.2De pago8 Páginas

🧩 Crea una app propia para Agency-Phone

Hay dos formas de poner una app en el teléfono. Elige la que te encaje:

MétodoIdeal paraQué tocas
A. SDK (resource externo)Desarrolladores y scripts que añaden una app con su propio iconoSolo tu propio resource. Ningún cambio en agency-phone.
B. Drop-in (dentro de agency-phone)Dueños de servidor que añaden una pantalla nativa en la interfaz del teléfonoconfig.lua + apps/ (+ html/js para una pantalla)

Si distribuyes una app a otros servidores, usa el método A. No necesita código fuente nuestro y sigue funcionando tras las actualizaciones.

A SDK: registra una app desde tu propio resource

agency-phone ofrece exports con los que cualquier resource pone en tiempo de ejecución una app con su propio icono en la pantalla de inicio del teléfono. La interfaz de tu app vive en tu propio resource; el teléfono muestra el icono y te pasa el control cuando el jugador lo toca. Sin cambios en agency-phone ni build desbloqueado.

Ejemplo mínimo

-- client side of YOUR resource
CreateThread(function()
    Wait(1500) -- let agency-phone boot
    exports['agency-phone']:RegisterApp({
        id        = 'myshop',
        label     = 'My Shop',
        icon      = 'fa-solid fa-cart-shopping', -- FontAwesome 6 class
        -- image  = 'https://cfx-nui-myresource/icon.png', -- or your own image instead
        color     = '#ff9500',
        colorDark = '#e08600',
    })
end)

-- fired when the player taps your icon on the phone
AddEventHandler('agency-phone:client:openApp', function(appId)
    if appId ~= 'myshop' then return end
    exports['agency-phone']:ClosePhone()
    -- open your own NUI here
end)

Configuración de RegisterApp

CampoTipoObligatorioDescripción
idstringsíId único, en minúsculas y sin espacios.
labelstringsíNombre bajo el icono.
iconstringnoClase de FontAwesome 6. Se ignora si hay image.
imagestringnoImagen de icono propia, por ejemplo https://cfx-nui-<resource>/icon.png.
color / colorDarkstringnoDegradado detrás del icono (hex).
slotnumbernoPosición en la pantalla de inicio. Si falta, se coloca sola.
storeDescstringnoDescripción corta en la página de la Store de tu app. Si falta, se usa el label.

Exports del SDK (cliente)

ExportDescripción
RegisterApp(config)Añade o actualiza tu app. Devuelve true, o false, err.
UnregisterApp(id)Quita tu app. También ocurre automáticamente cuando se detiene tu resource.
GetRegisteredApps()Tabla con todas las apps externas registradas.
ClosePhone()Cierra el teléfono, por ejemplo antes de abrir tu propia NUI.

El evento al tocar

Cuando el jugador toca tu icono, agency-phone lanza estos dos eventos en el cliente. Usa el que prefieras:

EventoArgumentos
agency-phone:client:openAppappId (filtra por tu id)
agency-phone:client:openApp:<yourId>ninguno (ya va solo a tu app)

Añade dependency 'agency-phone' a tu fxmanifest.lua para que el orden de arranque sea correcto.

B Drop-in, una pantalla nativa dentro del teléfono

Para una pantalla que dibuja el propio teléfono (no tu resource). Esto modifica archivos de agency-phone.

PasoArchivo¿Editable en el build escrow?
1. Entrada de la app en AgencyConfig.Appsconfig.lua✓ sí
2. Lógica con RegisterNUICallbackapps/<id>_client.lua (+ _server.lua)✓ sí
3. Pantalla <div id="app-<id>">html/index.html✗ cifrado
4. case '<id>': en openApp() + cargadorhtml/js/phone.js✗ cifrado

Los pasos 3 y 4 están en archivos cifrados por el escrow, así que una pantalla nativa necesita un build con código fuente o desbloqueado. Si solo tienes la versión escrow, usa el método A (tu pantalla vive en tu propio resource). Archivos de referencia dentro del resource: apps/testapp_client.lua y apps/dispatch_client.lua.

📋 Otros exports del teléfono

Cliente

ExportDevuelveDescripción
IsPhoneOpen()booleanEl teléfono está abierto.
IsPhonePoweredOn()booleanEl dispositivo está encendido.
HasPhone()booleanEl jugador tiene un objeto de teléfono.
HasCarrierContract()booleaneSIM o contrato activo.
GetPhoneData()tableInstantánea del estado del teléfono.
PhoneNotification(title, text, icon, color, timeout, acceptIcon, denyIcon)voidNotificación en el teléfono.
StartCall(contact)voidLlama a { name, number }.
StartAgencyPayCheckout(opts)voidCobro AgencyPay (ver abajo).

Servidor

ExportDescripción
SendMail(identifier, mailData)Entrega un correo a un jugador (conectado o no).
AddChirp(data)Publica un mensaje en el feed social Pulse.
VerifyAgencyPayCharge(source, requestId, minAmount)Confirma en el servidor un cobro AgencyPay pagado antes de entregar la mercancía (ver abajo).

⇄ Puente NUI ↔ Lua (método B)

DirecciónLado JSLado Lua
JS → LuafetchNUI('callbackName', data)RegisterNUICallback('callbackName', fn)
Lua → JSescucha action en window.onmessageSendNUIMessage({ action = '...' })

💳 Cobro AgencyPay

Cobra al wallet del jugador desde cualquier resource.

exports['agency-phone']:StartAgencyPayCheckout({
    merchant = 'My Shop', title = 'Agency Pay', subtitle = 'Checkout',
    label = 'Premium Coffee', amount = 24.50,
    icon = 'fa-solid fa-mug-hot', accent = '#ff9f0a',
    clientEvent = 'myshop:client:agencyPayResult',
    serverEvent = 'myshop:server:agencyPayResult',
    metadata = { orderId = 'order_2048' },
})

RegisterNetEvent('myshop:client:agencyPayResult', function(result)
    if result.status == 'paid' then
        -- deliver the goods
    end
end)

El resultado incluye status (paid / cancelled / failed), amount, cardId, balance y tus metadata.

Un paid que llega desde el cliente a tu resource no demuestra nada por sí solo. Pasa tu propio id a StartAgencyPayCheckout y llama a exports['agency-phone']:VerifyAgencyPayCharge(source, id, amount) en el servidor antes de entregar nada. Solo devuelve true y el importe si este jugador pagó ese cobro en los últimos 60 segundos, y consume el pago para que no se pueda reclamar dos veces.

🐛 Solución de problemas

SíntomaSolución
El icono no aparece (SDK)Actualiza agency-phone al último build de Keymaster, pon Wait(1500) antes de RegisterApp y añade dependency 'agency-phone' a tu manifest.
Tocar no hace nada (SDK)Tu handler de agency-phone:client:openApp tiene que coincidir exactamente con tu id (distingue mayúsculas y minúsculas).
La imagen propia no se veUsa una URL NUI completa https://cfx-nui-<your-resource>/path/icon.png y añade el archivo a files { } en tu manifest.
El icono no aparece (drop-in)enabled = true e installed = true en la entrada de la config.

¿Dudas o necesitas ayuda? Únete al Discord de Agency Scripts.

¿Sigues atascado después de esta página? Nuestro soporte se encarga.