Agency-Phone تطبيقات مخصصة
الآن مع AgencyOS27: تحديث مجاني لكل من يملك الهاتف بالفعل.

🧩 بناء تطبيق مخصّص لـ Agency-Phone
هناك طريقتان لإضافة تطبيق إلى الهاتف. اختر ما يناسبك:
| الطريقة | الأنسب لـ | ما الذي تعدّله |
|---|---|---|
| A. SDK (مورد خارجي) | المطورون والسكربتات التي تضيف تطبيقًا بأيقونتها الخاصة | موردك الخاص فقط. بلا أي تعديل على agency-phone. |
| B. Drop-in (داخل agency-phone) | أصحاب الخوادم الذين يضيفون شاشة أصلية داخل واجهة الهاتف | config.lua + apps/ (+ html/js للشاشة) |
إذا كنت توزّع تطبيقًا على خوادم أخرى فاستخدم الطريقة A. لا تحتاج إلى الشيفرة المصدرية منا وتستمر في العمل بعد التحديثات.
A SDK: تسجيل تطبيق من موردك الخاص
يوفّر agency-phone تصديرات تتيح لأي مورد أن يضع أثناء التشغيل تطبيقًا بأيقونته الخاصة على الشاشة الرئيسية للهاتف. تبقى واجهة تطبيقك في موردك؛ ويعرض الهاتف الأيقونة ويسلّمك التحكم عندما ينقر عليها اللاعب. بلا تعديلات على agency-phone وبلا نسخة مفتوحة.
مثال مختصر
-- 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)
إعدادات RegisterApp
| الحقل | النوع | مطلوب | الوصف |
|---|---|---|---|
id | string | نعم | معرّف فريد بأحرف صغيرة ودون مسافات. |
label | string | نعم | الاسم الظاهر تحت الأيقونة. |
icon | string | لا | فئة FontAwesome 6. تُتجاهل إذا ضُبط image. |
image | string | لا | صورة أيقونة خاصة، مثل https://cfx-nui-<resource>/icon.png. |
color / colorDark | string | لا | التدرّج اللوني خلف الأيقونة (hex). |
slot | number | لا | الموضع على الشاشة الرئيسية. يُحدَّد تلقائيًا إن لم يُذكر. |
storeDesc | string | لا | وصف قصير في صفحة تطبيقك داخل Store. يُستخدم label إن لم يُذكر. |
تصديرات SDK (العميل)
| التصدير | الوصف |
|---|---|
RegisterApp(config) | يضيف تطبيقك أو يحدّثه. يُرجع true أو false, err. |
UnregisterApp(id) | يزيل تطبيقك. يحدث ذلك تلقائيًا أيضًا عند توقف موردك. |
GetRegisteredApps() | جدول بكل التطبيقات الخارجية المسجّلة. |
ClosePhone() | يغلق الهاتف، مثلًا قبل فتح واجهة NUI الخاصة بك. |
حدث النقر
عندما ينقر اللاعب على أيقونتك، يطلق agency-phone هذين الحدثين على العميل. استخدم ما تفضّله:
| الحدث | الوسائط |
|---|---|
agency-phone:client:openApp | appId (صفِّ حسب معرّفك) |
agency-phone:client:openApp:<yourId> | لا شيء (مخصّص لتطبيقك مسبقًا) |
أضف dependency 'agency-phone' إلى ملف fxmanifest.lua ليكون ترتيب التشغيل صحيحًا.
B Drop-in، شاشة أصلية داخل الهاتف
لشاشة يرسمها الهاتف نفسه (وليس موردك). يتطلب ذلك تعديل ملفات agency-phone.
| الخطوة | الملف | قابل للتعديل في نسخة escrow؟ |
|---|---|---|
1. إدخال التطبيق في AgencyConfig.Apps | config.lua | ✓ نعم |
2. منطق RegisterNUICallback | apps/<id>_client.lua (+ _server.lua) | ✓ نعم |
3. الشاشة <div id="app-<id>"> | html/index.html | ✗ مشفّر |
4. case '<id>': في openApp() + المُحمِّل | html/js/phone.js | ✗ مشفّر |
الخطوتان 3 و4 في ملفات يشفّرها escrow، لذلك تحتاج الشاشة الأصلية إلى نسخة بالشيفرة المصدرية أو نسخة مفتوحة. إذا كانت لديك نسخة escrow فقط فاستخدم الطريقة A بدلًا منها (تبقى شاشتك في موردك الخاص). ملفات مرجعية داخل المورد: apps/testapp_client.lua وapps/dispatch_client.lua.
📋 تصديرات أخرى للهاتف
العميل
| التصدير | يُرجع | الوصف |
|---|---|---|
IsPhoneOpen() | boolean | الهاتف مفتوح حاليًا. |
IsPhonePoweredOn() | boolean | الجهاز قيد التشغيل. |
HasPhone() | boolean | يملك اللاعب عنصر هاتف. |
HasCarrierContract() | boolean | شريحة eSIM أو عقد فعّال. |
GetPhoneData() | table | لقطة لحالة الهاتف. |
PhoneNotification(title, text, icon, color, timeout, acceptIcon, denyIcon) | void | إشعار على الهاتف. |
StartCall(contact) | void | يتصل بـ { name, number }. |
StartAgencyPayCheckout(opts) | void | دفع AgencyPay (انظر أدناه). |
الخادم
| التصدير | الوصف |
|---|---|
SendMail(identifier, mailData) | يوصل بريدًا إلى لاعب (متصل أو غير متصل). |
AddChirp(data) | ينشر رسالة في خلاصة Pulse الاجتماعية. |
VerifyAgencyPayCharge(source, requestId, minAmount) | يؤكّد على الخادم عملية دفع AgencyPay مدفوعة قبل تسليم البضاعة (انظر أدناه). |
⇄ جسر NUI ↔ Lua (الطريقة B)
| الاتجاه | جهة JS | جهة Lua |
|---|---|---|
| JS → Lua | fetchNUI('callbackName', data) | RegisterNUICallback('callbackName', fn) |
| Lua → JS | استمع إلى action في window.onmessage | SendNUIMessage({ action = '...' }) |
💳 الدفع عبر AgencyPay
اخصم من محفظة اللاعب من أي مورد.
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)
تتضمن النتيجة status (paid / cancelled / failed) وamount وcardId وbalance وmetadata الخاصة بك.
نتيجة paid القادمة من العميل إلى موردك لا تثبت شيئًا وحدها. مرّر id خاصًا بك إلى StartAgencyPayCheckout واستدعِ exports['agency-phone']:VerifyAgencyPayCharge(source, id, amount) على الخادم قبل تسليم أي شيء. لا يُرجع true والمبلغ إلا إذا دفع هذا اللاعب هذه العملية خلال آخر 60 ثانية، ثم يستهلك الدفعة حتى لا يمكن المطالبة بها مرتين.
🐛 حل المشكلات
| العَرَض | الحل |
|---|---|
| الأيقونة لا تظهر (SDK) | حدّث agency-phone إلى أحدث نسخة من Keymaster، وضع Wait(1500) قبل RegisterApp، وأضف dependency 'agency-phone' إلى ملف manifest. |
| النقر لا يفعل شيئًا (SDK) | يجب أن يطابق معالج agency-phone:client:openApp معرّفك id تمامًا (مع مراعاة حالة الأحرف). |
| الصورة الخاصة لا تظهر | استخدم عنوان NUI كاملًا https://cfx-nui-<your-resource>/path/icon.png وأدرج الملف في files { } داخل manifest. |
| الأيقونة لا تظهر (drop-in) | enabled = true وinstalled = true في إدخال الإعدادات. |
لديك أسئلة أو تحتاج إلى مساعدة؟ انضم إلى Discord الخاص بـ Agency Scripts.