Agency-Phone Własne Aplikacje
Teraz z AgencyOS27: darmowa aktualizacja dla wszystkich, którzy już mają telefon.

🧩 Stwórz własną aplikację dla Agency-Phone
Są dwa sposoby na dodanie aplikacji do telefonu. Wybierz ten, który ci odpowiada:
| Metoda | Najlepsze dla | Czego dotykasz |
|---|---|---|
| A. SDK (zasób zewnętrzny) | Sprzedawcy i skrypty dodające aplikację z własną ikoną | Tylko Twój własny resource. Zero edycji w agency-phone. |
| B. Drop-in (wewnątrz agency-phone) | Właściciele serwerów dodający natywny ekran w UI telefonu | config.lua + apps/ (+ html/js dla ekranu) |
Jeśli udostępniasz aplikację na inne serwery, użyj Metoda A. Nie wymaga kodu źródłowego od nas i działa niezmiennie pomiędzy aktualizacjami.
A SDK: zarejestruj aplikację z własnego resource
agency-phone udostępnia exporty, które pozwalają dowolnemu resource dodać aplikację z własną ikoną na ekranie głównym telefonu w czasie działania. Interfejs Twojej aplikacji znajduje się w Twoim własnym resource; telefon wyświetla ikonę i przekazuje Ci kontrolę, gdy gracz w nią kliknie. Bez edycji agency-phone, bez odblokowanego buildu.
Minimalny przykład
-- 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)
Konfiguracja RegisterApp
| Pole | Typ | Wymagane | Opis |
|---|---|---|---|
id | string | tak | Unikalne ID, małe litery, bez spacji. |
label | string | tak | Nazwa wyświetlana pod ikoną. |
icon | string | nie | Klasa FontAwesome 6. Ignorowane, jeśli image jest ustawiony. |
image | string | nie | Własna ikona, np. https://cfx-nui-<resource>/icon.png. |
color / colorDark | string | nie | Gradient za ikoną (hex). |
slot | liczba | nie | Pozycja na ekranie głównym. Rozmieszczana automatycznie, jeśli pominięto. |
storeDesc | string | nie | Krótki opis na stronie Twojej aplikacji w sklepie. Domyślnie używana jest etykieta. |
Eksporty SDK (client)
| Eksport | Opis |
|---|---|
RegisterApp(config) | Dodaj lub zaktualizuj swoją aplikację. Zwraca true, lub false, err. |
UnregisterApp(id) | Usuń swoją aplikację. Dzieje się to również automatycznie, gdy Twój resource zostanie zatrzymany. |
GetRegisteredApps() | Tabela wszystkich zarejestrowanych aplikacji zewnętrznych. |
ClosePhone() | Zamknij telefon, np. przed otwarciem własnego NUI. |
Zdarzenie tapnięcia
Gdy gracz dotknie twojej ikony, agency-phone wywołuje oba te zdarzenia na kliencie. Użyj tego, które wolisz:
| Event | Argumenty |
|---|---|
agency-phone:client:openApp | appId (filtruj po swoim ID) |
agency-phone:client:openApp:<yourId> | brak (już przypisane do twojej aplikacji) |
Dodaj dependency 'agency-phone' do Twojego fxmanifest.lua aby kolejność uruchamiania była poprawna.
B Drop-in: natywny ekran wewnątrz telefonu
Dla ekranu renderowanego przez sam telefon (nie twój zasób). To edytuje własne pliki agency-phone.
| Krok | Plik | Możliwość edycji w wersji escrow? |
|---|---|---|
1. Wpis aplikacji w AgencyConfig.Apps | config.lua | ✓ tak |
2. RegisterNUICallback logika | apps/<id>_client.lua (+ _server.lua) | ✓ tak |
3. Ekran <div id="app-<id>"> | html/index.html | ✗ zaszyfrowany |
4. case '<id>': w openApp() + loader | html/js/phone.js | ✗ zaszyfrowany |
Kroki 3 i 4 znajdują się w plikach zaszyfrowanych przez escrow, więc natywny ekran wymaga wersji źródłowej / odblokowanej. Jeśli masz tylko wersję escrow, użyj Metoda A zamiast tego (twój ekran znajduje się we własnym zasobie). Pliki referencyjne wewnątrz zasobu: apps/testapp_client.lua i apps/dispatch_client.lua.
📋 Inne exporty telefonu
Klient
| Eksport | Zwraca | Opis |
|---|---|---|
IsPhoneOpen() | boolean | Telefon jest obecnie otwarty. |
IsPhonePoweredOn() | boolean | Urządzenie włączone. |
HasPhone() | boolean | Gracz posiada przedmiot telefonu. |
HasCarrierContract() | boolean | Aktywny eSIM / umowa. |
GetPhoneData() | tabela | Migawka stanu telefonu. |
PhoneNotification(title, text, icon, color, timeout, acceptIcon, denyIcon) | void | Powiadomienie w telefonie. |
StartCall(contact) | void | Zadzwoń { name, number }. |
StartAgencyPayCheckout(opts) | void | Płatność AgencyPay (patrz poniżej). |
Serwer
| Eksport | Opis |
|---|---|
SendMail(identifier, mailData) | Dostarcz pocztę do gracza (online lub offline). |
AddChirp(data) | Opublikuj wiadomość w feedzie społecznościowym Pulse. |
VerifyAgencyPayCharge(source, requestId, minAmount) | Potwierdź opłacony checkout AgencyPay na serwerze, zanim wydasz przedmioty (patrz poniżej). |
⇄ Mostek NUI ↔ Lua (metoda B)
| Kierunek | Strona JS | Strona Lua |
|---|---|---|
| JS → Lua | fetchNUI('callbackName', data) | RegisterNUICallback('callbackName', fn) |
| Lua → JS | nasłuchuj action w window.onmessage | SendNUIMessage({ action = '...' }) |
💳 Płatność AgencyPay
Obciąż portfel gracza z poziomu dowolnego zasobu.
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)
Payload wynikowy zawiera status (paid / cancelled / failed), amount, cardId, balance i Twój metadata.
A paid wynik, który trafia do twojego zasobu od klienta, sam w sobie niczego nie dowodzi. Przekaż własny id do StartAgencyPayCheckout i wywołaj exports['agency-phone']:VerifyAgencyPayCharge(source, id, amount) na serwerze, zanim cokolwiek wydasz. Zwraca true oraz kwotę tylko wtedy, gdy ten gracz opłacił to zamówienie w ciągu ostatnich 60 sekund, a całość wykorzystuje charge up, więc ta sama płatność nie może zostać odebrana dwukrotnie.
🐛 Rozwiązywanie problemów
| Objaw | Poprawka |
|---|---|
| Ikona się nie pojawia (SDK) | Zaktualizuj agency-phone do najnowszej wersji Keymaster, Wait(1500) przed RegisterApp, i dodaj dependency 'agency-phone' do Twojego manifestu. |
| Dotknięcie nic nie robi (SDK) | Twój agency-phone:client:openApp handler musi pasować do twojego id dokładnie (z uwzględnieniem wielkości liter). |
| Własny obraz się nie wyświetla | Użyj pełnego adresu URL NUI https://cfx-nui-<your-resource>/path/icon.png i umieść plik na liście w files { } w Twoim manifeście. |
| Ikona się nie pojawia (drop-in) | enabled = true i installed = true we wpisie w konfiguracji. |
Masz pytania lub potrzebujesz pomocy? Dołącz do Agency Scripts Discord.