Agency Docs
QBESXStandalone

Agency-Phone Custom Apps

Jetzt mit AgencyOS27: kostenloses Update für alle, die das Phone schon haben.

v27.1.2Bezahlt8 Seiten

🧩 Eine eigene App für das Agency-Phone bauen

Es gibt zwei Wege, eine App auf das Phone zu bringen. Nimm den, der zu dir passt:

WegPasst fürWas du anfasst
A. SDK (eigene Resource)Anbieter und Scripts, die eine App mit eigenem Icon mitbringenNur deine eigene Resource. Keine Änderung an agency-phone.
B. Drop-in (in agency-phone)Serverbetreiber, die einen nativen Bildschirm in der Oberfläche des Phones wollenconfig.lua + apps/ (+ html/js für einen Bildschirm)

Wenn du eine App an andere Server auslieferst, nimm Weg A. Er braucht keinen Quelltext von uns und funktioniert auch nach Updates weiter.

A SDK: eine App aus der eigenen Resource anmelden

agency-phone stellt Exports bereit, mit denen jede Resource zur Laufzeit eine App mit eigenem Icon auf den Startbildschirm des Phones bringt. Die Oberfläche deiner App liegt in deiner eigenen Resource; das Phone zeigt das Icon und übergibt dir die Kontrolle, sobald der Spieler es antippt. Keine Änderung an agency-phone, kein freigeschalteter Build.

Minimalbeispiel

-- 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)

Konfiguration von RegisterApp

FeldTypPflichtBeschreibung
idstringjaEindeutige id, kleingeschrieben, ohne Leerzeichen.
labelstringjaName unter dem Icon.
iconstringneinFontAwesome-6-Klasse. Wird ignoriert, wenn image gesetzt ist.
imagestringneinEigenes Icon-Bild, z. B. https://cfx-nui-<resource>/icon.png.
color / colorDarkstringneinFarbverlauf hinter dem Icon (Hex).
slotnumberneinPosition auf dem Startbildschirm. Ohne Angabe wird sie automatisch gewählt.
storeDescstringneinKurzbeschreibung auf der Store-Seite deiner App. Ohne Angabe gilt das Label.

SDK-Exports (Client)

ExportBeschreibung
RegisterApp(config)App hinzufügen oder aktualisieren. Gibt true zurück, oder false, err.
UnregisterApp(id)App entfernen. Passiert auch von selbst, wenn deine Resource stoppt.
GetRegisteredApps()Tabelle aller angemeldeten externen Apps.
ClosePhone()Phone schließen, z. B. bevor deine eigene NUI aufgeht.

Das Antipp-Event

Tippt der Spieler auf dein Icon, löst agency-phone beide Events auf dem Client aus. Nimm das, was dir lieber ist:

EventArgumente
agency-phone:client:openAppappId (nach deiner id filtern)
agency-phone:client:openApp:<yourId>keine (gilt schon nur für deine App)

Trag dependency 'agency-phone' in deine fxmanifest.lua ein, damit die Startreihenfolge stimmt.

B Drop-in, ein nativer Bildschirm im Phone

Für einen Bildschirm, den das Phone selbst zeichnet (nicht deine Resource). Dabei werden Dateien von agency-phone geändert.

SchrittDateiIm Escrow-Build änderbar?
1. App-Eintrag in AgencyConfig.Appsconfig.lua✓ ja
2. Logik mit RegisterNUICallbackapps/<id>_client.lua (+ _server.lua)✓ ja
3. Bildschirm <div id="app-<id>">html/index.html✗ verschlüsselt
4. case '<id>': in openApp() + Loaderhtml/js/phone.js✗ verschlüsselt

Schritt 3 und 4 liegen in Dateien, die Escrow verschlüsselt, ein nativer Bildschirm braucht also einen Build mit Quelltext bzw. einen freigeschalteten Build. Hast du nur die Escrow-Version, nimm stattdessen Weg A (dein Bildschirm liegt dann in deiner eigenen Resource). Beispieldateien in der Resource: apps/testapp_client.lua und apps/dispatch_client.lua.

📋 Weitere Exports des Phones

Client

ExportRückgabeBeschreibung
IsPhoneOpen()booleanPhone ist gerade offen.
IsPhonePoweredOn()booleanGerät ist eingeschaltet.
HasPhone()booleanSpieler hat ein Phone-Item.
HasCarrierContract()booleanAktive eSIM bzw. aktiver Vertrag.
GetPhoneData()tableMomentaufnahme des Phone-Zustands.
PhoneNotification(title, text, icon, color, timeout, acceptIcon, denyIcon)voidBenachrichtigung auf dem Phone.
StartCall(contact)voidRuft { name, number } an.
StartAgencyPayCheckout(opts)voidAgencyPay-Kasse (siehe unten).

Server

ExportBeschreibung
SendMail(identifier, mailData)Mail an einen Spieler zustellen (online oder offline).
AddChirp(data)Beitrag im Pulse-Feed veröffentlichen.
VerifyAgencyPayCharge(source, requestId, minAmount)Eine bezahlte AgencyPay-Kasse auf dem Server bestätigen, bevor du Ware ausgibst (siehe unten).

⇄ Brücke zwischen NUI und Lua (Weg B)

RichtungJS-SeiteLua-Seite
JS → LuafetchNUI('callbackName', data)RegisterNUICallback('callbackName', fn)
Lua → JSin window.onmessage auf action hörenSendNUIMessage({ action = '...' })

💳 AgencyPay-Kasse

Belaste die Wallet des Spielers aus jeder beliebigen 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)

Das Ergebnis enthält status (paid / cancelled / failed), amount, cardId, balance und deine metadata.

Ein paid, das vom Client bei deiner Resource ankommt, beweist für sich allein nichts. Gib StartAgencyPayCheckout eine eigene id mit und ruf auf dem Server exports['agency-phone']:VerifyAgencyPayCharge(source, id, amount) auf, bevor du etwas herausgibst. Das liefert true und den Betrag nur, wenn dieser Spieler genau diese Kasse in den letzten 60 Sekunden bezahlt hat, und verbraucht die Zahlung, damit dieselbe Zahlung nicht zweimal eingelöst werden kann.

🐛 Fehlersuche

ProblemLösung
Icon erscheint nicht (SDK)agency-phone auf den neuesten Keymaster-Build aktualisieren, Wait(1500) vor RegisterApp und dependency 'agency-phone' ins Manifest eintragen.
Antippen bewirkt nichts (SDK)Dein Handler für agency-phone:client:openApp muss genau deine id prüfen (Groß- und Kleinschreibung zählt).
Eigenes Bild wird nicht angezeigtEine vollständige NUI-Adresse https://cfx-nui-<your-resource>/path/icon.png verwenden und die Datei im Manifest unter files { } eintragen.
Icon erscheint nicht (Drop-in)enabled = true und installed = true im Config-Eintrag.

Fragen oder Hilfe nötig? Komm in den Discord von Agency Scripts.

Kommst du nach dieser Seite nicht weiter? Dann übernimmt unser Support.