# دليل دمج نظام ترخيص مخصص

يدعم الكود الحالي موفري ترخيص: Licentivo و `custom_http`. يختار التاجر أحدهما ويفعّله في **إعدادات النظام → نظام الترخيص** لجميع المنتجات وبيئتي sandbox/live؛ وتظل الاتصالات المخصصة وعمليات ربط الخطط مهيأة لكل منتج وبيئة على حدة. لا تتضمن هذه الميزة إنشاء نظام ترخيص ذاتي؛ ويواصل التاجر استخدام خدمة الترخيص وSDK الخاصة به.

تستمر عمليات تبادل حساب Licentivo وSDK باللغات التسع وإدارة الأجهزة وفق المسار الحالي. تزامن المنتجات المخصصة حالة الشراء عبر البروتوكول الوارد هنا، ويقرأ العملاء بيانات تسليم الترخيص في مركز الحساب دون المرور بمسار Licentivo SDK.

## البدء السريع

1. نفّذ واجهات HTTP الأربع التالية في خدمتك، واضبط مفتاح توقيع HMAC ومعرّفًا مستقلين لكل اتصال.
2. في «نظام الترخيص»، اختر «خدمة ترخيص مخصصة»، وأضف اتصالًا، وأدخل العنوان والبيئة ومعرّف الاتصال وkey ID ومفتاح Base64 القياسي، ثم احفظ بعد التحقق واضغط «تفعيل خدمة الترخيص المخصصة».
3. أنشئ مسودات المنتج وخطة البيع. تُدار أنواع الشراء والأسعار في Launch، وتُدار قواعد الترخيص في نظامك الخاص.
4. اختر المنتج والبيئة والاتصال، وأدخل مراجع المنتج والخطة الخارجية واحفظها. يحدد الاختيار العام للموقع الموفّر، ولا يمكن تفعيل Licentivo لمنتجات أخرى في الوقت نفسه.
5. انشر النسخة التجريبية في صفحة خطة البيع، وأكمل اختبارات قبول الدفع والتسليم والتجديد والترقية والاسترداد والتعافي من الأعطال، ثم اضبط بيئة الإنتاج بشكل مستقل.

لا يمكن تغيير العنوان والبيئة ومعرّف الاتصال وسياسة الوصول إلى الشبكة بعد الإنشاء؛ أنشئ اتصالًا جديدًا عند الحاجة. يمكن تدوير مفتاح التوقيع، وتركه فارغًا يبقي المفتاح السابق. عند وجود طلبات لنظام ترخيص آخر، لا يمكن تبديل الموفّر على مستوى الموقع مباشرة ويجب إكمال الترحيل أولًا. بعد التبديل تصبح الخطط السابقة للمعاينة فقط ويلزم إعادة نشرها؛ وتبقى بيانات اعتماد الاتصال والتعيينات المحفوظة. لا يمكن تغيير اتصال منتج له طلبات مباشرة، ولا تغيير تعيين معروض للبيع مباشرة؛ استخدم إصدار خطة جديدًا للسعر أو التعيين الجديد.

عند الإعداد عبر API، استدعِ أولًا `PUT /api/v1/admin/licensing/provider` بجسم الطلب `{"provider":"custom_http"}` أو `{"provider":"licentivo"}`، ثم احفظ تعيين المنتج. لا يمكن حفظ ربط ترخيص المنتج أو تعيين سياسة خطة Licentivo لموفّر غير مفعّل.

يتحقق فحص الاتصال من البروتوكول والمصادقة والبيئة وأنواع الشراء المدعومة، ولا ينشئ خطة خارجية أو يؤكدها نيابة عن التاجر. قبل تحصيل المدفوعات الفعلية يجب إكمال قبول التكامل في sandbox باستخدام خطة خارجية حقيقية.

## 3. عملية تكامل التاجر

1. نفّذ الواجهات الأربع الواردة هنا أمام نظام الترخيص الحالي، مع الاحتفاظ بمنطق التراخيص الموجود فيه.
2. أنشئ اتصال «خدمة ترخيص مخصصة» في Launch، واضبط عنوان HTTPS ومعرّف الاتصال والبيئة ومفتاح التوقيع.
3. يستدعي Launch واجهة فحص القدرات للتحقق من إصدار البروتوكول ودعم الشراء الدائم/محدود المدة وطريقة التسليم.
4. اختر هذا الاتصال للمنتج؛ وعيّن إصدار خطة البيع إلى `product_ref` و`plan_ref` الخارجيين. يجوز استخدام سلاسل التاجر الخاصة للأرقام الخارجية، ولا يُشترط استخدام UUID الخاص بـ Licentivo.
5. أكمل قبول الدفع والتجديد والترقية والاسترداد والتعافي من الأعطال في sandbox، ثم انشر إعداد live بصورة منفصلة.
6. بعد تحقق Launch من الدفع، يحفظ الطلب وتغطية الشراء والمهمة المنتظرة للإرسال ضمن معاملة قاعدة بيانات واحدة.
7. ترسل العملية الخلفية لقطة الشراء الكاملة إلى خدمة الترخيص المخصصة؛ وتؤكد الخدمة الاستلام بعد حفظ سجل الاستلام حفظًا دائمًا.
8. تعالج خدمة الترخيص الحالة المستهدفة. يستعلم Launch عن إيصال الحدث الأصلي، ولا يؤكد اكتمال المزامنة إلا عند `applied`.
9. يقرأ Launch معلومات التسليم للعملاء المسجلين دخولهم والمالكين للشراء، ويعرض رمز الترخيص أو مدخل التفعيل أو تعليمات نصية في مركز العملاء. يتكامل التطبيق مع نظام الترخيص الخاص بالتاجر.
10. ينتج التجديد والترقية والاسترداد وعكس الدفع والتعليق وانتهاء الصلاحية إصدارًا جديدًا من لقطة كاملة. تعالج خدمة الترخيص أحدث حالة مستهدفة.

يرتبط sandbox/live للمنتج نفسه باتصالين منفصلين. بعد وجود عمليات شراء يتطلب تغيير الموفّر عملية ترحيل مستقلة؛ ولا يجوز إرسال الطلبات والمهام القديمة بصمت إلى الخدمة الجديدة تبعًا لاختيار لوحة الإدارة.

## 4. واجهات API التي يجب على خدمة الترخيص المخصصة تنفيذها

جميع الواجهات التالية **تستقبلها خدمة ترخيص التاجر ويستدعيها خادم Launch**. يمكن أن يتضمن `base_url` بادئة مسار ثابتة؛ وتُضاف مسارات الجدول بعد هذه البادئة.

| الطريقة والمسار | الغرض |
| --- | --- |
| `GET /launch/v1/capabilities` | فحص الاتصال وإعلان البروتوكول والقدرات |
| `POST /launch/v1/events` | استلام الحالة المستهدفة الكاملة للشراء؛ تستخدم إعادة المحاولة الحدث الأصلي |
| `GET /launch/v1/events/{event_id}` | الاستعلام عما إذا طُبّق الحدث فعليًا واستعادة الاستجابة المفقودة |
| `GET /launch/v1/entitlements/{entitlement_ref}/delivery` | قراءة معلومات تسليم ترخيص موجود دون إنشاء ترخيص ثانٍ |

يستخدم الإصدار الأول الاستعلام النشط عن الإيصالات ولا يضيف مدخل رد اتصال خارجي لتعديل الطلبات. لا تملك الخدمة المخصصة صلاحية تأكيد الدفع أو تغيير السعر أو تعديل مدة الشراء.

### 4.1 الاتفاقيات العامة والمصادقة

- يستخدم JSON ترميز UTF-8؛ ويستخدم الوقت UTC RFC 3339؛ وتستخدم `version` عددًا صحيحًا موجبًا.
- استجابة النجاح هي `{"data": {...}, "request_id": "..."}`؛ واستجابة الخطأ هي `{"error": {"code": "...", "message": "..."}, "request_id": "..."}`.
- تستخدم كل بيئة وكل اتصال مفتاحًا مستقلًا. يتكون المفتاح من 32 بايت عشوائيًا على الأقل، ويُشار إليه من مخزن المفاتيح المشفر الموجود في Launch، ولا يوضع في إعدادات الواجهة أو الأمثلة أو حزمة تثبيت التطبيق.
- يحمل كل طلب `X-Launch-Key-Id` و`X-Launch-Timestamp` و`X-Launch-Nonce` و`X-Launch-Signature`.
- الطابع الزمني هو ثواني Unix عشرية. قيمة nonce عشوائية لا تقل عن 128 بت ومشفرة بصيغة base64url دون حشو؛ تُنشأ قيمة جديدة لكل محاولة اتصال.

مدخل التوقيع هو بايتات UTF-8 للعناصر السبعة التالية موصولة بمحرف سطر جديد واحد، دون إضافة سطر جديد في النهاية:

```text
v1
<key_id>
<timestamp>
<nonce>
<UPPERCASE HTTP method>
<encoded request path and raw query, including the base_url path prefix>
<lowercase hexadecimal SHA-256 digest of the exact request body>
```

تتكون `X-Launch-Signature` من `v1=` متبوعة بنتيجة `HMAC-SHA256` مشفرة بصيغة base64url دون حشو. جسم طلب GET فارغ. يتحقق المستقبل من التوقيع والنافذة الزمنية قبل فك التسلسل؛ ويستخدم مقارنة بزمن ثابت، ويسمح افتراضيًا بانحراف موجب أو سالب 300 ثانية، ويحتفظ بقيمة nonce لمدة 600 ثانية على الأقل لمنع إعادة التشغيل. لا تُعاد قيمة nonce بين المحاولات، لكن يجب أن يبقى معرّف الحدث وجسم طلب العمل دون تغيير.

لا يحل التوقيع محل HTTPS. لا يحمل الطلب كلمة مرور العميل أو مفاتيح الدفع أو مفتاح إدارة Licentivo؛ ويُرسل افتراضيًا مرجع حساب مجهول فقط دون بريد إلكتروني. يحتاج عميل HTTP على الخادم إلى مهلة وحد لطول الاستجابة ومنع اتباع إعادة التوجيه مع بيانات الاعتماد. تحقق من العنوان المستهدف عند إعداد عنوان مخصص؛ ويجب أن يكون الوصول إلى الشبكة الداخلية قدرة نشر أعدّها المسؤول صراحة.

### 4.2 فحص القدرات

يعيد `GET /launch/v1/capabilities` الرمز HTTP 200، مثلًا:

```json
{
  "data": {
    "protocol": "launch-external-licensing-v1",
    "connection_ref": "merchant-01-sandbox",
    "environment": "sandbox",
    "purchase_types": ["perpetual", "fixed_term"],
    "delivery_types": ["license_key", "activation_url", "instructions"],
    "devices": false,
    "identity_exchange": false
  },
  "request_id": "check-001"
}
```

الحقول `protocol` و`connection_ref` و`environment` و`purchase_types` و`delivery_types` مطلوبة. يجب أن يكون الأخيران مصفوفتين غير فارغتين، ولا يجوز نشر أنواع شراء غير مدعومة للبيع. في الإصدار الأول يجب أن تكون `devices` و`identity_exchange` بالقيمة `false`؛ ولا يجوز إعلان الدعم إلا بعد اكتمال عقد التوسعة وتنفيذه.

### 4.3 لقطة الشراء

مثال طلب `POST /launch/v1/events`:

```json
{
  "schema": "launch-external-licensing-v1",
  "event_id": "7bf84b91-2749-4b01-a6a7-bd527c488ee8",
  "connection_ref": "merchant-01-sandbox",
  "environment": "sandbox",
  "type": "entitlement.snapshot",
  "change_reason": "purchase",
  "account_ref": "customer_opaque_001",
  "entitlement_ref": "purchase_opaque_001",
  "launch_product_id": "c6dd463e-50f7-4b76-8239-0a8ec6fc304b",
  "launch_plan_version_id": "5459a073-9362-4b46-949d-9b0c5d84421a",
  "product_ref": "desktop-editor",
  "plan_ref": "professional-yearly-v1",
  "version": 1,
  "desired_state": "active",
  "valid_from": "2026-10-25T00:00:00Z",
  "valid_until": "2027-10-25T00:00:00Z"
}
```

جميع حقول المثال أعلاه مطلوبة. تعني قيمة `valid_until` البالغة `null` شراءً دائمًا؛ ويجب أن تكون القيم الأخرى لاحقة لـ `valid_from`.

| الحقل | القيود والمعنى |
| --- | --- |
| `event_id` | UUID ينشئه Launch؛ يبقى ثابتًا عند إعادة محاولة الحدث نفسه |
| `connection_ref` / `environment` | يجب أن يطابقا الاتصال والبيئة اللذين ينتمي إليهما مفتاح التوقيع |
| `account_ref` | مرجع حساب مجهول ثابت؛ يحدد المستقبل العميل بالاتصال والبيئة وهذا المرجع معًا |
| `entitlement_ref` | مرجع ثابت لعلاقة شراء واحدة؛ تستخدم إعادة الشراء بعد الإلغاء الكامل مرجعًا جديدًا |
| `launch_product_id` / `launch_plan_version_id` | UUID لمنتج Launch وإصدار الخطة غير القابل للتغيير |
| `product_ref` / `plan_ref` | مراجع خارجية يهيئها المتكامل؛ 1–128 محرف ASCII، وتُسمح الأحرف والأرقام و`_` و`-` و`.`؛ ولا تُنشأ الخطط الخارجية تلقائيًا |
| `version` | إصدار الحالة المستهدفة المتزايد رتيبًا للاتصال والبيئة ومرجع الشراء نفسه |
| `desired_state` | `active`、`suspended`、`expired`、`revoked` |
| `change_reason` | `purchase`、`renewal`、`upgrade`、`refund`、`reversal`、`suspension`、`resumption`、`expiry`、`reconciliation` |

يستخدم `account_ref` و`entitlement_ref` من 1–128 حرفًا أو رقمًا أو شرطة سفلية أو شرطة قصيرة. تثبت قيم `schema` و`type` كما في المثال. يطبق المستقبل النتيجة وفق `desired_state` والمدة المطلقة الكاملة، ولا يضيف أيامًا أو يلغي الترخيص كله من تلقاء نفسه بناءً على السبب.

خصوصًا الاسترداد: قد تبقى عملية شراء أساسية صالحة بعد استرداد طلب تجديد أو ترقية؛ ويمكن أن تظل اللقطة `active` مع تقصير المدة أو تغيير الخطة. لا تُرسل حالة الإنهاء المقابلة إلا عندما لا تبقى تغطية شراء صالحة بعد إعادة حساب السجل.

### 4.4 الاستلام والإيصال والاستعادة

يجب على المستقبل حفظ معرّف الحدث وملخص جسم الطلب الأصلي والمهمة المطلوب تنفيذها حفظًا دائمًا قبل إعادة HTTP 202؛ ويمكن للطلب المكرر الذي اكتملت مزامنته إعادة HTTP 200. يعيد كلاهما بنية الإيصال التالية.

```json
{
  "data": {
    "event_id": "7bf84b91-2749-4b01-a6a7-bd527c488ee8",
    "connection_ref": "merchant-01-sandbox",
    "environment": "sandbox",
    "entitlement_ref": "purchase_opaque_001",
    "version": 1,
    "payload_sha256": "<64-character lowercase hexadecimal SHA-256 digest of the exact event body>",
    "status": "pending",
    "error_code": null
  },
  "request_id": "receipt-001"
}
```

يجب استبدال العنصر النائب للملخص بالملخص الفعلي. جميع حقول الإيصال المذكورة أعلاه مطلوبة؛ وتكون `error_code` بقيمة `null` عند عدم وجود خطأ. يعيد الاستعلام `GET /launch/v1/events/{event_id}` البنية نفسها مع HTTP 200، وقد تكون الحالة:

| `status` | المعنى | معالجة Launch |
| --- | --- | --- |
| `pending` | حُفظ دائمًا ولم يكتمل تغيير الترخيص الفعلي بعد | أجّل الاستعلام؛ لا تضع علامة اكتمال المزامنة |
| `applied` | تؤكد خدمة الترخيص تطبيق الحالة المستهدفة فعليًا | أكد اكتمال المزامنة بعد مطابقة جميع الحقول المرتبطة والملخص |
| `rejected` | تأكد تعذر التطبيق، مثل عدم وجود الخطة الخارجية | أوقف إعادة المحاولة التلقائية واعرض خطأ واضحًا |
| `manual_review` | النتيجة غير مؤكدة أو الحالة متعارضة وتتطلب مراجعة يدوية | احتفظ بالمهمة والحدث الأصليين لحين معالجة قابلة للتدقيق |

حالة التسليم مستقلة عن إيصال المزامنة؛ ولا يمكن اعتبار `applied` إذن تشغيل لتطبيق العميل مباشرة.

متطلبات الموثوقية:

- التسليم مرة واحدة على الأقل؛ يجب أن يضمن المستقبل عدم تكرار أثر العملية التجارية، ولا يمكن الوعد بأن طبقة الشبكة «تستدعي مرة واحدة فقط».
- يعيد معرّف الحدث نفسه وجسم الطلب الأصلي نفسه النتيجة الموجودة؛ أما المعرّف نفسه مع جسم مختلف فيعيد HTTP 409 `IDEMPOTENCY_CONFLICT`.
- لا يجوز للإصدار القديم الكتابة فوق الإصدار الجديد. لا يجوز قبول أحداث أو حالات مستهدفة مختلفة لإصدار الشراء نفسه بصمت؛ ويجب إعادة HTTP 409 `STATE_VERSION_CONFLICT` للمراجعة.
- بعد فقد استجابة POST أو إعادة تشغيل العملية، يستعلم Launch أولًا عن الحدث الأصلي باستخدام GET؛ ولا يعيد إرسال المعرّف والجسم الأصليين إلا بعد إعادة `EVENT_NOT_FOUND` صراحة.
- عندما تكون نتيجة الإصدار الفعلية لدى الطرف البعيد غير واضحة، يجب على المتكامل مراجعتها باستخدام مرجع عدم التكرار الدائم الخاص به، ولا يجوز إنشاء ترخيص آخر بمجرد إعادة الإرسال.
- يتبع HTTP 429 القيمة `Retry-After`؛ ويُتعافى من المهلات وأخطاء 5xx بتأخير متزايد؛ وعند تجاوز الحد تُجرى مراجعة يدوية. لا يجوز اعتبار رفض المصادقة أو الإعداد أو الأعمال نجاحًا للمزامنة.

رموز الخطأ المقترحة: `SIGNATURE_INVALID`（401）、`SIGNATURE_EXPIRED`（401）、`NONCE_REPLAYED`（409）、`SCOPE_MISMATCH`（403）、`EVENT_NOT_FOUND`（404）、`IDEMPOTENCY_CONFLICT`（409）、`STATE_VERSION_CONFLICT`（409）、`PLAN_UNKNOWN`（422）、`PURCHASE_TYPE_UNSUPPORTED`（422）、`RATE_LIMITED`（429）、`SERVICE_UNAVAILABLE`（503）。يجب ألا تتضمن رسائل الخطأ بيانات اعتماد.

### 4.5 تسليم الترخيص

لا يقرأ `GET /launch/v1/entitlements/{entitlement_ref}/delivery` إلا نتيجة التسليم الموجودة في ذلك الاتصال والبيئة، ولا يجوز اعتبار الاستعلام أمر إصدار جديد. مثال HTTP 200:

```json
{
  "data": {
    "connection_ref": "merchant-01-sandbox",
    "environment": "sandbox",
    "entitlement_ref": "purchase_opaque_001",
    "version": 1,
    "status": "ready",
    "delivery": {
      "type": "license_key",
      "value": "EXAMPLE-ONLY-NOT-A-REAL-LICENSE",
      "expires_at": null
    }
  },
  "request_id": "delivery-001"
}
```

تكون `status` إحدى القيم `pending` أو `ready` أو `unavailable`؛ وعندما لا تكون ready تكون `delivery` بقيمة `null`. وعندما تكون ready يجب أن تكون `type` إحدى القيم المعلنة `license_key` أو `activation_url` أو `instructions`، وألا تتجاوز `value` عدد 4096 بايت UTF-8، وأن تكون `expires_at` وقت UTC أو `null`. يجب أن تطابق جميع حقول الارتباط في الاستجابة إصدار الشراء الحالي في Launch؛ ولا يجوز اعتبار تسليم إصدار قديم نتيجة حالية.

رمز الترخيص بيانات حساسة؛ تستخدم استجابة التسليم `Cache-Control: no-store` ولا يُسجل جسمها، ويُستخدم تخزين مشفر عند الحاجة للحفظ الدائم. لا يُقبل عنوان تفعيل URL إلا من مصادر HTTPS المسموح بها في إعداد الاتصال؛ وتُعرض instructions كنص عادي دون تنفيذ HTML أو نصوص برمجية. لا يمكن للحساب الملغى أو المسترد بالكامل أو الذي لا يملك شراءً صالحًا الاستمرار في الحصول على معلومات التسليم عبر Launch؛ ويتولى النظام الخارجي إبطال بيانات الاعتماد التي سُلّمت فعليًا.

## واجهات إدارة Launch والعملاء

تقع هذه الواجهات تحت origin الخاص بـ Launch الذي نشره التاجر، ولا تستخدم مفتاح HMAC للخدمة الخارجية للمصادقة. يستخدم المسؤول جلسة الموقع الموجودة، ويجب أن تحمل طلبات الكتابة `X-CSRF-Token`. لا يقرأ العميل إلا مشترياته الخاصة.

| الطريقة والمسار | الغرض |
| --- | --- |
| `GET /api/v1/admin/licensing/connections` | يعيد `connections` و`bindings` و`mappings` و`default_provider`؛ تتضمن قائمة الاتصالات الاتصالات المخصصة فقط، ويواصل Licentivo استخدام واجهة الإدارة السابقة |
| `POST /api/v1/admin/licensing/connections` | التحقق من اتصال مخصص وإضافته |
| `PUT /api/v1/admin/licensing/connections/{id}` | تعديل الاسم ومصادر التفعيل المسموح بها وإعداد التوقيع؛ يبقى عنوان الاستلام التاريخي دون تغيير |
| `POST /api/v1/admin/licensing/connections/{id}/check` | إعادة الفحص؛ تشير `last_check_error` غير null في HTTP 200 إلى فشل الفحص |
| `PUT /api/v1/admin/products/{id}/licensing` | إعداد الموفّر والاتصال وتعيين الخطة الخارجية لبيئة المنتج المحددة |
| `GET /api/v1/me/products/{id}/delivery?environment=sandbox` | يقرأ العميل الحالي تسليم ترخيص شراء مخصص صالح حاليًا؛ المصادقة باستخدام Cookie أو desktop Bearer |
| `GET /api/v1/licensing/documentation` | هذا المستند، دون تسجيل دخول |
| `GET /api/v1/licensing/protocol` | OpenAPI المطلوب تنفيذه للخدمة المخصصة، دون تسجيل دخول |

جسم طلب إضافة اتصال مخصص:

```json
{
  "provider": "custom_http",
  "name": "My licensing service",
  "base_url": "https://licenses.example.com",
  "environment": "sandbox",
  "connection_ref": "merchant-01-sandbox",
  "key_id": "key-1",
  "signing_key": "<standard Base64 encoding of 32 to 128 random bytes>",
  "allow_private_network": false,
  "allow_local_http": false,
  "activation_origins": ["https://activate.example.com"]
}
```

استجابة `data` هي كائن الاتصال بعد إخفاء البيانات الحساسة، ولا تعيد مفتاح التوقيع أو secret ID. يسمح allow_local_http فقط بعناوين localhost/loopback في sandbox؛ وتتطلب HTTPS للشبكة الخاصة إذنًا صريحًا من المسؤول. لا يجوز ترك المفتاح فارغًا إلا عند تعديل اتصال موجود. يظل إعداد Licentivo عبر `POST /api/v1/admin/connections/licentivo`.

جسم طلب إعداد المنتج:

```json
{
  "provider": "custom_http",
  "environment": "sandbox",
  "connection_id": "<id returned when creating the connection>",
  "mappings": [
    {
      "version_id": "<Launch plan version UUID>",
      "product_ref": "desktop-editor",
      "plan_ref": "professional-yearly-v1"
    }
  ]
}
```

عند اختيار Licentivo أرسل `{"provider":"licentivo","environment":"sandbox","mappings":[]}`؛ وتظل تعيينات المنتج/السياسة الخاصة به تستخدم الواجهة السابقة. يحوّل التبديل الأول المنشورات الحالية إلى معاينة، ويلزم إعادة فحصها ونشرها وفق الموفّر الجديد. يمكن أن تتضمن mappings الإصدارات المراد إضافتها أو إبقاؤها فقط؛ ولا يؤدي الإغفال إلى حذف التعيينات القديمة.

يستخدم تسليم العميل غلاف data القياسي مع HTTP 200؛ ويعيد عدم وجود شراء 404، ويعيد منتج Licentivo الرمز 409 `LICENSING_DELIVERY_UNSUPPORTED`، وتعيد الحالات غير المتزامنة أو المعلقة أو المنتهية أو المستردة بالكامل الرمز 409 `ENTITLEMENT_NOT_READY`، ويعيد تعذر الخدمة الخارجية مؤقتًا أو عدم تطابق الإيصال 503. يعيد خيار «عرض تسليم الترخيص» في مركز العملاء التحقق من الملكية والحالة، ولا يكتب بيانات الاعتماد في URL أو السجلات.

تعيد واجهات Licentivo identity وdevice وintegration-check للمنتجات المخصصة الرمز 409 `CUSTOM_LICENSING_SDK_REQUIRED`. وتواصل `/credential` القديمة إعادة 410. يجب أن يستخدم التطبيق SDK الخاص بالتاجر، وألا يعتبر حالة Launch `ready` ترخيصًا للتشغيل.

## الأمثلة والقبول

يوفر [مثال المحول الخفيف Python](/ar/launch-documents/custom-licensing-example/) إطار استقبال للتوقيع وnonce وإزالة تكرار الأحداث وحفظ الإيصالات؛ وتتطلب معالجة الترخيص الفعلية التكامل مع نظام التاجر.

يصف [OpenAPI](/ar/assets/launch/external-licensing-openapi.json) للبروتوكول المخصص و[OpenAPI](/ar/assets/launch/openapi.json) الخاص بـ Launch الاتجاهين كلًّا على حدة. لا يحتاج المستقبل إلى تنفيذ كتالوج منتجات Licentivo أو كتالوج سياساته أو واجهات الثقة بالهوية.

يستخدم التحقق المحلي MySQL معزولًا ومحول HTTP حقيقيًا وخدمات ترخيص/دفع محاكاة، ويغطي فقد الاستجابة وإعادة التشغيل والتجديد والترقية والاسترداد وتعطيل الحساب وعدم تطابق الإيصال وعزل التسليم. يتطلب قبول الإنتاج أيضًا خدمة الترخيص والتطبيق الخاصين بالتاجر. لا يستكمل Launch قدرات الأجهزة أو تسجيل دخول الحساب المشترك أو التشغيل دون اتصال التي لم يُعلن عنها.
