كل نقاط النهاية الخاصة بالدناكل: تطبيق سطح المكتب (تفعيل/قراءة) + إدارة المخزون والتفعيلات، مع شرح بسيط وأمثلة جاهزة.
http://alraed.space/api/alraed
نسخة التطبيق المطلوبة: 1.6.2.5
المصادقة: Bearer Token
الرمز الثابت للشركة: alraed
النظام صار شركة واحدة (single-tenant)، فرمز الشركة ثابت alraed في كل المسارات. جهاز الدنكل (تطبيق ويندوز القديم) يتكلّم مع الخادم عبر HTTP، ويكفي تغيير عنوان الخادم في التطبيق إلى http://alraed.space/api/alraed/.
كل رد من الـAPI يرجع بنفس الشكل (نجاح أو فشل):
{
"success": true, // نجحت العملية؟
"message": "تم التفعيل", // رسالة عربية للعرض
"data": { ... } // الحمولة (تختلف حسب النقطة)
}
success:false ورسالة الخطأ في message، مع رمز HTTP مناسب (400 تحقق، 401 غير مصرّح، 403 صلاحية ناقصة، 404 غير موجود).التطبيق يسجّل الدخول مرة، يأخذ accessToken، ويرسله في كل طلب لاحق بترويسة Authorization: Bearer <token>.
/api/alraed/auth/loginversion (نسخة التطبيق المطلوبة — بوابة «حدّث النظام») وapplicationlist (الأنظمة التي لها «تفعيل دنكل» بأرقامها).{ "username": "admin", "password": "******" }
{
"accessToken": "eyJhbGciOi...",
"accessTokenExpiresAt": "2026-07-24T12:00:00Z",
"refreshToken": "...",
"user": { ... },
"permissions": ["dongles.activate", "dongles.view"],
"version": "1.6.2.5", // لو نسخة التطبيق أقدم ⇒ يطلب تحديث
"applicationlist": [
{ "id": 12, "name": "الرائد لإدارة العقود", "number": 3,
"editions": [
{ "id": 7, "name": "Professional", "number": 3 },
{ "id": 8, "name": "Lite", "number": 4 }
] }
]
}
Product.DongleAppNumber) — يُرسَل لاحقاً بالتفعيل في حقل appNumber. الأنظمة التي بلا «تفعيل دنكل» لا تظهر هنا.number هنا هو الذي يُرسَل بالتفعيل في حقل versionType. تُدار من صفحة «البرامج» بالنظام (لكل إصدار حقل «رقم الدنكل»)، فبدل ما تكون النسخ مكتوبة داخل التطبيق، عبّي قائمة «نوع النسخة» من هنا حسب النظام المختار. الإصدار بلا رقم يرجع number: null (لا يصلح للإرسال)./api/alraed/auth/refresh{ "refreshToken": "..." }
كل المسارات تبدأ بـ /api/alraed.
| الأسلوب | المسار | الوظيفة | الصلاحية |
|---|---|---|---|
| POST | /auth/login | دخول (توكن + نسخة + الأنظمة) | — |
| تطبيق الدنكل (سطح المكتب) | |||
| POST | /activation/app-activate | تفعيل/إعادة تفعيل دنكل | activate / reactivate / manage |
| POST | /activation/app-tablet | تفعيل تابلت (الخادم يولّد الكود) | activate / manage |
| GET | /activation/dongles/by-key?key= | قراءة آخر تفعيل دنكل بالمفتاح | view |
| مخزون الدناكل | |||
| GET | /activation/dongles?q= | قائمة بسيطة (بحث بالمفتاح) | view |
| GET | /activation/dongles/paged | قائمة مُرقّمة + إحصائيات | view |
| POST | /activation/dongles | إضافة دنكل للمخزون | manage |
| PUT | /activation/dongles/{id} | تعديل دنكل | manage |
| DEL | /activation/dongles/{id} | حذف دنكل | manage |
| POST | /activation/dongles/import | استيراد مخزون (ملف) | manage |
| تفعيلات الدناكل | |||
| GET | /activation/dongle-activations | قائمة التفعيلات (فلاتر + ترقيم) | view |
| GET | /activation/dongle-activations/{id} | تفاصيل تفعيل | view |
| POST | /activation/dongle-activations | إنشاء تفعيل (من الويب) | activate / reactivate / manage |
| POST | /activation/dongle-activations/{id}/action | إيقاف/قفل/فتح/ترقية/مطابقة | manage |
| DEL | /activation/dongle-activations/{id} | حذف تفعيل | manage |
| مساعدة وتقارير | |||
| GET | /activation/dongles/{id}/lifecycle | الخط الزمني لدنكل | view |
| GET | /activation/dongle-dashboard | لوحة إحصائيات الدناكل | view |
| GET | /activation/reports?year= | تقرير سنوي | view |
| GET | /activation/cities?country= | قائمة المدن | view / requests.view |
| GET | /activation/countries | قائمة الدول | view / requests.view |
هذي النقاط التي يناديها تطبيق الدنكل (WinForms) بعد الدخول. كلها تحتاج ترويسة Authorization: Bearer.
activationCode، والخادم يخزّنه كما هو (مطابقة للنظام القديم). أمّا التابلت فالخادم هو من يولّد الكود ويرجّعه.baseCode/activationCode مطلوباً؟ فقط في الترقية من النظام القديم (isUpgrade:true) وفي تفعيل التابلت (app-tablet — لأنه مُدخَل التوليد). التفعيل العادي وإعادة التفعيل يُقبلان بلا الكودين ويُخزَّنان فارغين.versionType): يُؤخذ من editions الخاصة بالنظام (من ردّ الدخول). إذا كان النظام معرَّفة له أرقام إصدارات، فأي رقم خارجها يُرفض برسالة تذكر الأرقام المتاحة. 0 = غير محدَّد ومقبول دائماً. والأنظمة التي لم تُضبط أرقام إصداراتها بعد تقبل أي رقم (توافقاً مع القديم: 1=Economy، 2=Standard، 3=Professional، 4=Lite).0x00 ملتصقة به (مخزن ثابت الطول) — وإرسالها خاماً داخل JSON يجعل الطلب غير صالح كلياً. الخادم صار ينظّفها تلقائياً من جسم الطلب ومن القيم قبل التخزين، لكن يُفضَّل تنظيفها بالتطبيق أيضاً: id.Split('\0')[0].Trim() (لاحظ أن Trim() وحده لا يشيل \0)./activation/app-activatedongleKey) يُربط بالمخزون تلقائياً، وإن لم يكن موجوداً يُضاف تلقائياً. النظام يُحدَّد برقمه (appNumber).isReactivation:false) على دنكل مفعّل سابقاً ⇒ يفشل: «هذا الدنكل مفعّل سابقاً (التفعيل #…) — استعمل «إعادة تفعيل» بدل التفعيل».dongle-activations/{id}/action بـ{"action":"unlock"}.dongles.activate (للتفعيل) أو dongles.reactivate (لو isReactivation:true) أو dongles.manage أو مدير.{
"appNumber": 3, // رقم النظام (من applicationlist)
"dongleKey": "b897e1404c27ba...", // سيريال الدنكل (يُربط/يُضاف تلقائياً)
"baseCode": "ABC123", // كود أساسي من جهاز العميل (مطلوب للترقية فقط)
"activationCode": "XYZ789", // الكود جاهزاً من التطبيق (مطلوب للترقية فقط)
"isServer": true, // سيرفر (true) أم شبكي (false)
"isUpgrade": false,
"isReactivation": false,
"versionType": 3, // رقم الإصدار من editions النظام (0 = غير محدَّد)
"cityValue": 5, // رقم المدينة (من /cities)
"countryValue": 0, // 0=العراق 1=ليبيا
"companyName": "شركة النور",
"address": "بغداد - الكرادة",
"phone": "07701234567",
"job": "محاسب",
"note": null
}
{
"id": 64867, // معرّف التفعيل الجديد
"activationCode": "XYZ789", // كما أُرسل
"productId": 12, "productName": "الرائد لإدارة العقود",
"dongleId": 68586, "dongleKey": "b897e1404c27ba...",
"dongleCreated": false // true لو أُضيف الدنكل للمخزون الآن
}
/activation/app-tabletdongles.activate أو dongles.manage أو مدير.{
"appNumber": 5,
"baseCode": "IMEI-or-BaseCode", // مُدخَل التوليد (مطلوب)
"keyCode": "device-key",
"cityValue": 5,
"companyName": "...", "address": "...", "phone": "...", "job": "...", "note": null
}
{ "id": 771, "activationCode": "a1b2c3d4e5f60718", "productId": 14, "productName": "..." }
/activation/dongles/by-key?key={سيريال}found:false.dongles.view{
"found": true, "dongleId": 68586, "dongleKey": "b897...", "dongleActive": true,
"hasActivation": true, "activationId": 64867,
"appNumber": 3, "productId": 12, "productName": "الرائد لإدارة العقود",
"isServer": true, "versionType": 3, "isUpgrade": false,
"isStop": false, "isLocked": false,
"companyName": "شركة النور", "address": "...", "phone": "...", "job": "...", "note": null,
"cityValue": 5, "cityName": "النجف", "countryValue": 0, "countryName": "العراق",
"activatedAt": "2026-01-15T09:00:00Z"
}
found:true وhasActivation:false./activation/unlock-requestsdongles.view أو activate أو reactivate أو manage.{ "dongleKey": "b897e1404c27ba...", "reason": "الزبون غيّر الجهاز بعد فورمات" }
{ "id": 14, "dongleKey": "b897...", "status": "pending", "reason": "...",
"requestedByName": "أحمد", "createdAt": "...", "productName": "..." }
/activation/unlock-requests/by-key?key={سيريال}status: pending · approved · rejected). بعد approved يكون القفل مفتوحاً فعلاً.مخزون الدناكل = المفاتيح الفريدة (سيريالات) المتاحة للربط بتفعيل.
/activation/dongles?q={بحث}{ id, dongleKey, isActive, note, createdAt }.dongles.view/activation/dongles/paged?q=&flag=&page=1&pageSize=50flag = active | inactive | used | unused (تصفية).dongles.view{
"items": [{ "id":1, "dongleKey":"...", "isActive":true, "note":null, "createdAt":"...", "activationsCount":1 }],
"total": 1240,
"stats": { "total":1240, "active":1200, "inactive":40, "used":1100, "unused":140 }
}
/activation/dongles · PUT /activation/dongles/{id}dongles.manage{ "dongleKey": "NEW-SERIAL-001", "isActive": true, "note": null }
/activation/dongles/{id}dongles.manage/activation/dongles/importfile). الرد: { imported, skipped, duplicates, errors[] }.dongles.manage/activation/dongle-activationsdongles.viewcustomerId | تصفية بعميل | productId | تصفية بنظام |
q | بحث (كود/شركة/هاتف…) | flag | server/stop/locked/upgrade/matching… |
from / to | مدى تاريخ | page / pageSize | ترقيم (افتراضي 1 / 50) |
/activation/dongle-activations/{id}dongles.view/activation/dongle-activationsdongles.activate / reactivate (حسب isReactivation) / manage.{
"customerId": 31908, // اختياري
"productId": 12, // اختياري
"dongleId": 68586, // اختياري (من المخزون)
"isServer": true,
"baseCode": "ABC123", // مطلوب
"activationCode": "XYZ789", // مطلوب
"isUpgrade": false, "isReactivation": false,
"cityValue": 5, "countryValue": 0,
"companyName": "...", "address": "...", "phone": "...", "job": "...", "note": null,
"openGateway": false // افتح بوابة زبون لهذا الدنكل (بلا اشتراك)
}
{ "id": 64868, "activationCode": "XYZ789", "gatewayId": null, "gatewayCode": null }
/activation/dongle-activations/{id}/actiondongles.manage{ "action": "stop", "value": true }
| action | المعنى | value |
|---|---|---|
stop | إيقاف/إلغاء إيقاف التفعيل | true=إيقاف، false=إلغاء |
lock | قفل التفعيل | — |
unlock | فتح القفل | — |
upgrade | تعيين حالة الترقية | true/false |
matching | تعيين حالة المطابقة | true/false |
/activation/dongle-activations/{id}dongles.manage/activation/dongles/{id}/lifecycledongles.view{ "id":68586, "dongleKey":"...", "isActive":true, "activationsCount":2,
"events": [{ "id":9, "type":"activated", "userName":"أحمد", "details":"BaseCode: ABC", "createdAt":"..." }] }
/activation/dongle-dashboarddongles.view/activation/reports?year={سنة}dongles.view/activation/countries[{ value, name }] — 0=العراق، 1=ليبيا./activation/cities?country={0|1}[{ value, name }].dongles.view أو activationrequests.view (مشتركة مع التابلت).الدناكل تُحكَم حصرياً بصلاحيات فئة «الدناكل» (فُصلت عن activation.* القديمة).
| المفتاح | يسمح بـ |
|---|---|
dongles.view | عرض المخزون والتفعيلات واللوحة والتقارير ودورة الحياة والقراءة بالمفتاح. |
dongles.activate | تفعيل دنكل/تابلت جديد (app-activate / app-tablet / إنشاء تفعيل غير مُعاد). |
dongles.reactivate | إعادة التفعيل (isReactivation:true) — جهاز مبدّل/فورمات. |
dongles.manage | كل شيء: إدارة المخزون، الإجراءات (إيقاف/قفل…)، الحذف — ويشمل ضمناً التفعيل وإعادته. |
# 1) دخول والحصول على التوكن
curl -s -X POST https://alraed.space/api/alraed/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"******"}'
# خذ data.accessToken من الرد، ثم:
TOKEN="eyJhbGciOi..."
# 2) تفعيل دنكل
curl -s -X POST https://alraed.space/api/alraed/activation/app-activate \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"appNumber":3,"dongleKey":"b897...","baseCode":"ABC123","activationCode":"XYZ789","isServer":true,"versionType":3,"cityValue":5,"countryValue":0,"companyName":"شركة النور","phone":"07701234567"}'
# 3) قراءة آخر تفعيل بالمفتاح
curl -s -H "Authorization: Bearer $TOKEN" \
"https://alraed.space/api/alraed/activation/dongles/by-key?key=b897..."
var client = new RestClient("https://alraed.space/api/alraed/");
// 1) دخول
var login = new RestRequest("auth/login", Method.Post)
.AddJsonBody(new { username = "admin", password = "******" });
var res = client.Execute(login);
// استخرج data.accessToken (الغلاف {success,message,data})
string token = JObject.Parse(res.Content)["data"]["accessToken"].ToString();
// 2) أرسل التوكن بكل طلب لاحق
var act = new RestRequest("activation/app-activate", Method.Post);
act.AddHeader("Authorization", "Bearer " + token);
act.AddJsonBody(new {
appNumber = 3, dongleKey = "b897...",
baseCode = "ABC123", activationCode = "XYZ789",
isServer = true, versionType = 3, cityValue = 5, countryValue = 0
});
var actRes = client.Execute(act);
Authorization: Bearer بكل طلب → اقرأ data من الغلاف الموحّد. للدنكل أنت تحسب الكود وترسله؛ للتابلت الخادم يحسبه ويرجّعه لك.