بيانات اعتماد الروبوتات وخطافات الويب

لكل روبوت بيانات اعتماد خاصة به، تختلف عن مفتاح API الخاص بمؤسسة الشريك.

نموذج الأمان (موصى به)

بيانات الاعتمادالهدفالتخزين
مفتاح API للشريك (sk_…)إدارة جميع الروبوتات وتدوير الأسرار وإرسال رسائل المركزمخزّن بالتجزئة
رمز الروبوت (bot_….…)استدعاءات API مقيدة بالروبوت (خطاف ويب وارد وواجهات روبوت مستقبلية)مخزّن بالتجزئة؛ ويُعرض مرة واحدة فقط
سر خطاف الويب (whsec_…)توقيع / التحقق من أجسام خطافات الويب باستخدام HMACمخزّن (لازم للتوقيع)؛ عامله ككلمة مرور
عنوان URL لخطاف الويبنقطة نهاية HTTPS للشريك لأحداث MorisBoxعنوان URL بنص عادي

لماذا لا نستخدم client_id + client_secret من OAuth؟

تناسب بيانات اعتماد عميل OAuth الوصول المفوّض من المستخدم بصورة أفضل. تتواصل الروبوتات من آلة إلى آلة؛ لذلك يكون رمز روبوت واحد عالي العشوائية + توقيعات HMAC لخطافات الويب أبسط وأكثر متانة في حالة الاستخدام هذه.

أفضل الممارسات

  1. استخدم خطافات ويب HTTPS فقط (يُسمح بـlocalhost أثناء التطوير)
  2. أضف توقيع HMAC-SHA256 للجسم إلى كل حدث صادر
  3. أعد اختياريًا قائمة IP مسموح بها لكل روبوت
  4. دوّر الرمز / السر من دون إعادة إنشاء الروبوت
  5. لا تسجّل الرموز الكاملة مطلقًا

إنشاء روبوت (تُعاد الأسرار مرة واحدة)

POST /api/v1/bots

{
  "code": "portail",
  "name": "SEED Portail",
  "runtime_mode": "local",
  "webhook_url": "https://partner.example/hooks/morisbox/portail"
}

الاستجابة 201

{
  "bot": {
    "code": "portail",
    "credentials": {
      "token_prefix": "bot_a1b2c3",
      "token_configured": true,
      "webhook_url": "https://partner.example/hooks/morisbox/portail",
      "webhook_secret_prefix": "whsec_ab12",
      "inbound_webhook_path": "/api/v1/bots/portail/webhook"
    }
  },
  "bot_token": "bot_a1b2c3d4e5f6.xxxxxxxx",
  "webhook_secret": "whsec_xxxxxxxx",
  "warning": "Store bot_token and webhook_secret now…"
}

احفظ bot_token وwebhook_secret في مدير الأسرار لديك. لا يمكن قراءتهما لاحقًا؛ بل يمكن تجديدهما بالتدوير فقط.


إدارة بيانات الاعتماد

الطريقةالمسارالمصادقةالوصف
GET/bots/{code}/credentialsمفتاح الشريك أو رمز الروبوتالبادئات فقط
POST/bots/{code}/token/rotateمفتاح الشريكbot_token جديد (مرة واحدة)
PUT/bots/{code}/webhookمفتاح الشريكتعيين webhook_url؛ وخيار rotate_secret
POST/bots/{code}/webhook/secret/rotateمفتاح الشريكسر خطاف ويب جديد
POST/bots/{code}/webhook/testمفتاح الشريكإرسال حدث اختبار موقّع
PATCH/bots/{code}مفتاح الشريكتحديث الاسم والقنوات وallowed_ips وغيرها

تعيين خطاف الويب

PUT /api/v1/bots/portail/webhook
Authorization: Bearer sk_…
{
  "webhook_url": "https://partner.example/hooks/morisbox/portail",
  "rotate_secret": true,
  "allowed_ips": "203.0.113.10"
}

خطافات الويب الصادرة (من MorisBox إلى نظامك)

عندما يرسل MorisBox طلب POST إلى webhook_url الخاص بك:

POST https://partner.example/hooks/morisbox/portail
Content-Type: application/json
X-Seed360-Event: bot.webhook.test
X-Seed360-Bot: portail
X-Seed360-Signature: sha256=<hex>
X-Seed360-Bot-Secret: <webhook_secret>

الجسم

{
  "event": "bot.webhook.test",
  "bot": {
    "ref": "…",
    "code": "portail",
    "partner_code": "seed"
  },
  "payload": {}
}

التحقق من التوقيع (Python)

import hmac, hashlib

def verify(raw_body: bytes, header_sig: str, secret: str) -> bool:
    sig = header_sig.removeprefix("sha256=")
    expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, sig)

فضّل التحقق من HMAC بدلًا من الاعتماد على ترويسة السر وحدها.


خطافات الويب الواردة (من نظامك إلى MorisBox)

POST /api/v1/bots/{code}/webhook

صادق باستخدام إحدى الطرق التالية:

  1. Authorization: Bearer <bot_token>
  2. X-Seed360-Bot-Secret: <webhook_secret>
  3. X-Seed360-Signature: sha256=<hmac of body with webhook_secret>
{
  "event": "custom.event",
  "data": { "ok": true }
}

استخدام رمز الروبوت

GET /api/v1/bots/portail
Authorization: Bearer bot_a1b2c3d4e5f6.xxxx

تكون رموز الروبوت مقيدة بذلك الروبوت. أما مفاتيح API للشركاء فتدير المؤسسة بأكملها.


قائمة التحقق التشغيلية

  1. إنشاء الروبوت ← حفظ bot_token + webhook_secret
  2. نشر مستقبل HTTPS ← PUT …/webhook
  3. تنفيذ POST …/webhook/test حتى الحصول على ok: true
  4. عند حدوث تسرّب، التدوير عبر token/rotate / webhook/secret/rotate