---
title: عمليات الاستدعاء | RunAPI
description: استقبال عمليات استدعاء المهام والتحقق منها بأمان.
url: https://runapi.ai/ar/docs/guides/task-api/callbacks.md
canonical: https://runapi.ai/ar/docs/guides/task-api/callbacks
locale: ar
---

> نسخة HTML: https://runapi.ai/ar/docs/guides/task-api/callbacks
> فهرس الموقع للوكلاء: https://runapi.ai/llms.txt

# عمليات الاستدعاء

استخدم عمليات الاستدعاء لتلقي أحداث دورة حياة Task على نقطة نهاية HTTPS عامة. تحقق من صحة كل عملية استدعاء قبل معالجة نص JSON الخاص بها حتى لا تتمكن إلا عمليات التسليم الموقّعة لحسابك من تغيير حالة التطبيق.

## إعداد عنوان URL لعملية الاستدعاء

أضف `callback_url` عبر HTTPS عام حين تنشئ مهمة. يعتمد نص الحدث
وحالات دورة الحياة على نقطة النهاية؛ راجع مرجع API الخاص بها
للاطلاع على حمولات الاستدعاء.

```json
{
  "model": "flux-2-pro-text-to-image",
  "prompt": "A product photograph on a clean studio background",
  "callback_url": "https://your-domain.com/webhooks/runapi"
}
```

## إنشاء سرّ عملية الاستدعاء

اتبع [دليل المصادقة](https://runapi.ai/ar/docs/guides/authentication.md) لتسجيل
الدخول، ثم افتح API Keys وأنشئ Callback Secret للحساب الذي يُنشئ المهمة. احتفظ بالقيمة في مدير الأسرار وأتِح الوصول إليها لمستقبل الاستدعاء فقط. إنه ليس مفتاح API ويجب ألا يُرسَل أبداً في طلب مهمة Task.

يوقّع السر عمليات الاستدعاء لذلك الحساب. يُغيّر تدويره التوقيع للتسليمات اللاحقة، لذا حدّث كل مُستقبِل لعمليات الاستدعاء فورًا واحتفظ بكلتا القيمتين متاحتَين فقط لوقت كافٍ للتعامل مع التسليمات الجارية.

## التحقق من توقيع عملية الاستدعاء

كل استدعاء هو طلب HTTP `POST` يحمل `Content-Type: application/json`.
لا تضيف RunAPI رأس `Authorization` إلى هذا الطلب. تحقق من هذه الرؤوس قبل إلغاء تسلسل الجسم:

| الترويسة | المعنى |
|----------
| `X-Callback-Id` | معرّف فريد لمحاولة التسليم هذه. |
| `X-Callback-Timestamp` | طابع زمني Unix بالثواني يحدد وقت توقيع التسليم. |
| `X-Callback-Signature` | توقيع HMAC-SHA-256 مشفر بـ Base64. |

أنشئ القيمة الموقَّعة بالضبط على النحو التالي، باستخدام بايتات جسم الطلب غير المعدَّلة:

```text
X-Callback-Id + "." + X-Callback-Timestamp + "." + raw request body
```

قم بفكّ ترميز Callback Secret بـ Base64، واحسب HMAC-SHA-256 على تلك
القيمة، ثم قم بترميز النتيجة بـ Base64، وقارنها مع
`X-Callback-Signature` باستخدام مقارنة آمنة زمنياً. لا تقم بتحليل
JSON وإعادة تسلسله قبل التحقق.

### JavaScript

```javascript
import { createHmac, timingSafeEqual } from "node:crypto";

export function verifyCallback({headers, rawBody, callbackSecret}) {
  const callbackId = headers["x-callback-id"];
  const timestamp = Number(headers["x-callback-timestamp"]);
  const signature = headers["x-callback-signature"];

  if (!callbackId || !signature || !Number.isSafeInteger(timestamp)) return false;
  if (Math.abs(Date.now() / 1000 - timestamp) > 300) return false;

  const signedContent = `${callbackId}.${timestamp}.${rawBody}`;
  const expected = createHmac("sha256", Buffer.from(callbackSecret, "base64"))
    .update(signedContent, "utf8")
    .digest();
  const received = Buffer.from(signature, "base64");

  return expected.length === received.length && timingSafeEqual(expected, received);
}
```

مرّر سلسلة نص جسم الطلب الخام من إطار العمل إلى `rawBody`؛ ولا تستدعِ
`JSON.stringify` على البيانات المحللة.

### Python

```python
import base64
import hashlib
import hmac
import time


def verify_callback(headers, raw_body, callback_secret):
    callback_id = headers.get("X-Callback-Id")
    timestamp = headers.get("X-Callback-Timestamp")
    signature = headers.get("X-Callback-Signature")

    if not callback_id or not timestamp or not signature:
        return False

    try:
        timestamp = int(timestamp)
        secret = base64.b64decode(callback_secret, validate=True)
        received = base64.b64decode(signature, validate=True)
    except (ValueError, TypeError):
        return False

    if abs(time.time() - timestamp) > 300:
        return False

    signed_content = f"{callback_id}.{timestamp}.{raw_body}".encode("utf-8")
    expected = hmac.new(secret, signed_content, hashlib.sha256).digest()
    return hmac.compare_digest(expected, received)
```

مرّر سلسلة نص جسم الطلب الخام التي استقبلها إطار عمل HTTP لديك
كـ `raw_body`.

## معالجة عمليات التسليم بأمان

* أرسل استجابة `2xx` فقط بعد قبول معالجة طلب الاستدعاء. في حالة الاستجابة غير `2xx` أو فشل النقل، تُحاوَل إعادة التسليم حتى 10 مرات.
* استجب في غضون 15 ثانية. أضف العمل الأبطأ إلى قائمة انتظار بعد التحقق بدلاً من تعطيل استجابة HTTP.
* ارفض عمليات الاستدعاء التي تفتقر إلى ترويسات التوقيع، أو تحمل توقيعاً غير صالح، أو تحتوي على طابع زمني خارج نافذة التسامح التي يحددها المستقبل.

## استكشاف أخطاء التحقق وإصلاحها

* **عدم تطابق التوقيع:** تأكد من أن Callback Secret ينتمي إلى الحساب ذاته الخاص بالمهمة، وفكّ ترميزه بـ Base64، ووقّع النص الأصلي للطلب لا JSON المُحلَّل.
* **رؤوس التوقيع مفقودة:** أنشئ Callback Secret قبل الاعتماد على عمليات الاستدعاء لتغييرات الحالة.
* **رُفض الطابع الزمني:** زامن ساعة المستقبِل واستخدم هامش تسامح مناسب لبيئة نشرك.

للاطلاع على إرشادات الإعداد ودورة الحياة، ارجع إلى [البدء السريع لـ Task API
](https://runapi.ai/ar/docs/guides/task-api/quickstart.md).

---

## المزيد من RunAPI

- [الرئيسية](https://runapi.ai/ar/.md)
- [كتالوج النماذج](https://runapi.ai/ar/models.md)
- [الأسعار](https://runapi.ai/ar/pricing.md)
- [مزودو الخدمة](https://runapi.ai/ar/models)
- [التوثيق](https://runapi.ai/ar/docs/guides)
- [حزم SDK](https://runapi.ai/ar/sdk.md)
- [CLI](https://runapi.ai/ar/cli.md)
- [خادم MCP](https://runapi.ai/ar/mcp.md)
- [Claude Code مقابل Cursor](https://runapi.ai/ar/claude-code-vs-cursor.md)
- [إعداد Cursor API](https://runapi.ai/ar/cursor-api-setup.md)
- [RunAPI مقابل OpenRouter](https://runapi.ai/ar/openrouter-alternative.md)
- [المؤسسات](https://runapi.ai/ar/contact.md)
- [اتصل بنا](https://runapi.ai/ar/contact.md)
- [الشروط](https://runapi.ai/ar/terms.md)
- [الخصوصية](https://runapi.ai/ar/privacy.md)
- [فهرس الموقع للوكلاء](https://runapi.ai/llms.txt)

التواصل: contact@runapi.ai

## البيانات المنظمة

```json
[
  {
    "@context": "https://schema.org",
    "inLanguage": "ar",
    "@type": "WebSite",
    "name": "RunAPI",
    "url": "https://runapi.ai/ar",
    "potentialAction": {
      "@type": "SearchAction",
      "target": {
        "@type": "EntryPoint",
        "urlTemplate": "https://runapi.ai/ar/models?q={search_term_string}"
      },
      "query-input": "required name=search_term_string"
    }
  },
  {
    "@context": "https://schema.org",
    "inLanguage": "ar",
    "@type": "Organization",
    "name": "RunAPI",
    "url": "https://runapi.ai/ar",
    "logo": {
      "@type": "ImageObject",
      "url": "https://runapi.ai/aricon.svg"
    },
    "sameAs": [
      "https://github.com/runapi-ai"
    ]
  },
  {
    "@context": "https://schema.org",
    "inLanguage": "ar",
    "@type": "TechArticle",
    "headline": "عمليات الاستدعاء",
    "description": "استقبال عمليات استدعاء المهام والتحقق منها بأمان.",
    "url": "https://runapi.ai/ar/docs/guides/task-api/callbacks",
    "mainEntityOfPage": "https://runapi.ai/ar/docs/guides/task-api/callbacks"
  }
]
```
