> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# إعداد هاتف الويب (WebRTC) البرمجي

> امنح موظفيك سطح مكالمات كاملًا داخل المتصفح — من الهاتف البرمجي المدمج في لوحة التحكم إلى عميل SIP مضمّن في تطبيقك — مع التحكم في هوية المتصل، وبيانات اعتماد يمكنك تدويرها، ومسار إشعارات push للرنّ الوارد.

# إعداد هاتف الويب (WebRTC) البرمجي

يتيح الهاتف البرمجي في المتصفح للموظف إجراء مكالمات PSTN والرد عليها دون مغادرة المتصفح — لا هاتف مكتبي، ولا تطبيق SIP لسطح المكتب. ثمة ثلاث طرق لوضعه أمام الموظف، وتتشارك جميعها بيانات الاعتماد والبنية التحتية ذاتها في الأسفل:

1. **الهاتف البرمجي المدمج في لوحة التحكم** — توفر Orbit هاتفًا برمجيًا جاهزًا داخل لوحة التحكم. هذا هو المسار الخالي من الكود ونقطة البداية المناسبة لمعظم الفرق.
2. **هاتف برمجي مضمّن قائم على LiveKit** (`Softphone` في `@devotel-orbit/web`) — تركّب الهاتف البرمجي داخل مساحة عمل الموظف الخاصة بك (نظام CRM، أو حائط مركز الاتصال، أو أداة داخلية) بواجهة استخدام خاصة بك.
3. **هاتف برمجي مضمّن عبر SIP-over-WSS** (مسار تسجيل SIP) — عميل SIP تقليدي (مثل JsSIP) يسجّل مباشرة لدى بوابة Orbit التي تحول WebRTC إلى SIP، للفرق التي تريد دلالات SIP القياسية ومنطق تحكم مكالمات خاصًا بها.

يمشي هذا الدليل في الإعداد بالترتيب الذي ستنفذه فعليًا: سجّل الأجهزة، وأصدر بيانات الاعتماد، واختر كيف تجد المكالمات الواردة الهاتف البرمجي، وصِل عميلًا، ثم تحقق.

> [!NOTE]
>
> لا يحتاج الهاتف البرمجي في المتصفح سوى متصفح مزود بميكروفون. إشعارات push الواردة (القسم 1) رفيق متنقل ينتقل إليه الموظفون عند استخدام تطبيق Orbit للجوال — وهي غير مطلوبة للمتصفح نفسه.

## 1. تسجيل الأجهزة ورموز VoIP push (الجوال)

تجاوز هذا القسم إذا كان موظفوك يعملون في المتصفح فقط. سجّل **جهاز VoIP** فقط عندما يحتاج الموظف أيضًا إلى أن تُرنّ المكالمات الواردة على هاتفه كمكالمة أصلية — أي أن يستمر تطبيق Orbit للجوال، في الخلفية أو مقفلاً، في الرنين كمكالمة هاتفية بدل إظهار إشعار سلبي.

تسجيل جهاز VoIP استدعاء API واحد:

```bash theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/push/voip-devices \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "platform": "ios",
    "voip_token": "APNS_VOIP_TOKEN_HEX",
    "bundle_id": "com.yourcompany.orbit-agent"
  }'
```

* قيمة `platform` هي `ios` أو `android`. على iOS يكون `voip_token` رمز PushKit (CallKit)؛ وعلى Android رمز تسجيل FCM المستخدم لقناة المكالمات عالية الأولوية.
* قيمة `bundle_id` (iOS فقط) هي معرّف حزمة التطبيق — موضوع إشعار VoIP هو `<bundle_id>.voip`.
* يعيد الاستجابة الجهاز المسجل (`id`، `platform`، `last_seen_at`).

أدر الأسطول عبر `GET /push/voip-devices` (سرد) و`DELETE /push/voip-devices/:id` (إلغاء تسجيل جهاز). لا تستدعي هذه يدويًا عادة — تسجل حزمة SDK للجوال صفها الخاص وتحدّثه وتحذفه. الرمز الميت نهائيًا (ألغاه نظام التشغيل أو أُلغي تثبيت التطبيق) يُعلَّم revoked تلقائيًا ويُتجاوز في الرنّ الوارد التالي، فلا يحجب جهاز قديم دورة رنين الطابور أبدًا.

> [!WARNING]
>
> رمز VoIP **ليس** كرمز push العادي. يلغي iOS امتياز VoIP من التطبيقات التي تعيد استخدامه لإشعارات تسويقية أو تنبيهية، لذلك يُبقيان نوعي الرموز منفصلين بصرامة. لا ترسل أبدًا إشعارًا غير مكالمات إلى `voip_token`.

## 2. إصدار بيانات اعتماد الهاتف البرمجي

يحتاج متصفح الموظف إلى بيانات اعتماد قصيرة العمر قبل أن يتمكن من الاتصال. وتتوقف نقطة النهاية التي تصدر منها على العميل الذي اخترته — لوحة التحكم، أو LiveKit مضمّن، أو SIP مضمّن.

### الهاتف البرمجي المدمج في لوحة التحكم / المضمّن عبر LiveKit

أولى خطوات الهاتف البرمجي طلب رمز. يعيد `POST /voice/softphone/token` رمز وصول LiveKit قصير العمر مع عنوان URL للوسائط للاتصال به:

```bash theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/voice/softphone/token \
  -H "Authorization: Bearer YOUR_API_KEY"
```

الاستجابة (مختصرة):

```json theme={null}
{
  "data": {
    "token": "<livekit access token>",
    "media_url": "wss://..."
  }
}
```

يُحدَّد نطاق الرمز بغرفة لكل مستخدم فلا يتشارك موظفان جلسة أبدًا. إجراء مكالمة بعد الاتصال هو `POST /voice/softphone/dial` مع `{ "to": "+15550123", "from": "+15559876" }` — راجع المقطع الكامل في القسم 4.

### الهاتف البرمجي المضمّن عبر SIP/WSS

يسجل عميل SIP مباشرة عبر WebSocket. يستبدل `POST /voice/softphone/register` طلب API الموثق لديك ببيانات اعتماد SIP قصيرة العمر:

```bash theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/voice/softphone/register \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "callerIdNumber": "+15559876", "deviceLabel": "agent-desk-04" }'
```

الاستجابة (مختصرة):

```json theme={null}
{
  "data": {
    "sipUsername": "u_agent_x1a2b3",
    "sipPassword": "...",
    "sipDomain": "sip.orbit.devotel.io",
    "wssUrl": "wss://...",
    "iceServers": [{ "urls": "stun:..." }],
    "callerIdNumber": "+15559876",
    "expiresAt": 1716110400000
  }
}
```

الخصائص الأساسية التي تبني تصميمك حولها:

* تعيش بيانات الاعتماد **60 دقيقة** — أعد التسجيل قبل `expiresAt` وإلا انقطعت الجلسة.
* يجب أن يكون `callerIdNumber` رقمًا تملكه مؤسستك (وإلا فُرض 403) — هكذا يُحظر انتحال هوية المتصل الصادرة.
* يرتبط اسم المستخدم بمؤسستك، فلا يمكن إعادة تشغيل اسم مستخدم مسروق ضد مستأجر آخر.
* إصدار الرموز محدد النطاق بـ **owner/admin/developer** — ليست نقطة نهاية عامة ومجهولة.

> [!NOTE]
>
> ألغِ بيانات الاعتماد فورًا بـ `DELETE /voice/softphone/credentials/:username` إذا غادر موظف أو تسرب رمز. الإلغاء حكْر على owner فيبقى تسرب بيانات الاعتماد حدثًا صغير النطاق.

## 3. اختر كيف تصل المكالمات الواردة إلى الهاتف البرمجي

يجب توجيه المكالمات الواردة بحيث تهبط في متصفح موظف. لديك ثلاثة خيارات يملكها المستأجر — استخدم ما يطابق طريقة إعداد أرقام هاتفك.

* **DNIS → طابور → هاتف برمجي.** المسار الأشيع: يرسل التوجيه الوارد لرقم هاتفك المكالمة إلى طابور ACD، ويعرضها الطابور على الهاتف البرمجي في متصفح موظف متاح (وإن كان على تطبيق الجوال، فإشعار VoIP — القسم 1). تضبط هذا لكل رقم في توجيه الأرقام بلوحة التحكم، أو عبر منشئ التدفقات.
* **DNIS → توجيه SIP.** وجّه المكالمات الواردة إلى مجال SIP الذي تعيش عليه تسجيلات هاتفك البرمجي. استخدم هذا عندما تهبط حركتك الواردة أصلًا على SIP (مثلاً رقم DID محوَّل إلى عنوان SIP URI خاص بك) وتريد أن يجيب الهاتف البرمجي المسجل مباشرة.
* **هاتف المتصل البرمجي يجري المكالمات الصادرة.** للفرق التي تقودها المكالمات الصادرة لا تنشأ مسألة الوارد أصلًا — يبدأ الموظف المكالمات، وأية إجابة واردة تكون على رقم موجَّه إلى طابور (عودة إلى الخيار الأول).

أيًّا كان اختيارك، لا تتغير بيانات اعتماد الهاتف البرمجي نفسه أبدًا — الأقسام 1 و2 و4 متطابقة تحت أي بنية واردة. التوجيه الوارد خاصية *للرقم* لا للهاتف البرمجي.

## 4. مقطع JS كامل — الميكروفون، وإشعار VoIP، والاحتياط في المتصفح

هذا هاتف برمجي كامل في المتصفح جاهز للنسخ واللصق. يعمل مع خياري التضمين كليهما (LiveKit وSIP-over-WSS) ويعالج واقع الاحتياط في المتصفح: سيكون بعض الموظفين على متصفحات أو شبكات يتعذر فيها المسار الأساسي للوسائط، لذلك تصل دائمًا مسارًا احتياطيًا.

```js theme={null}
import { OrbitSoftphone } from "@devotel-orbit/web";

const softphone = new OrbitSoftphone({
  apiBaseUrl: "https://api.orbit.devotel.io",
  apiKey: "YOUR_API_KEY", // serve from your backend — never commit it
  // Optional: force a media URL. Omit to use the token response.
  // mediaUrl: "wss://...",
  onCallStateChange: (s) => console.log("softphone state:", s),
  onError: (e) => handleSoftphoneFailure(e), // ← fallback lives here
});

// 1. Mic is gated on the browser's getUserMedia. Ask for it on a user
//    gesture (a click) — not page load — so the permission prompt is
//    attributed and the mic isn't held open on an idle tab.
async function armMicrophone() {
  await navigator.mediaDevices.getUserMedia({ audio: true });
  await softphone.connect(); // mints token + publishes mic
}

// 2. Place an outbound call.
async function callCustomer(e164) {
  return softphone.dial(e164); // returns call_id when ringing
}

// 3. Fallback: if the browser/media path can't connect, hand the call
//    to a click-to-call bridge (the caller's desk phone or mobile
//    rings, and the agent talks there). This is also the path when an
//    enterprise network blocks WebRTC entirely.
function handleSoftphoneFailure(err) {
  console.warn("WebRTC unavailable, falling back:", err.message);
  // show "call me on my device" UI → POST /voice/click-to-call instead
}

// VoIP push (mobile only): the browser cannot receive a VoIP push -
// mobile handles it natively. From the browser, the inbound ring just
// arrives when an inbound call is routed to the agent's room.
```

> [!WARNING]
>
> يتطلب WebRTC منح `getUserMedia` وصفحة HTTPS. الهاتف البرمجي الذي "لا يفعل شيئًا" يكاد يكون دائمًا أحد الآتي: صفحة HTTP (غير آمنة)، أو مطالبة ميكروفون مرفوضة، أو شبكة مؤسسية تحجب UDP 3478 (أو الـ relay عبر TCP 5349). لقائمة السماح التي يحتاجها جدار ناري مؤسسي، راجع [متطلبات شبكة الهاتف البرمجي](https://docs.orbit.devotel.io/voice/network-requirements.md).

## 5. التحقق واستكشاف الأخطاء

**تحقق من الإعداد من طرف إلى طرف:**

1. أصدر بيانات اعتماد (القسم 2)، وصِل العميل (القسم 4)، وابحث عن حدث `connect` للغرفة أو `registered` لـ SIP.
2. أجرِ مكالمة صادرة إلى جوالك — ينبغي أن تسمع رنينًا ثم صوتًا في الاتجاهين عند الإجابة.
3. وجّه مكالمة واردة إلى رقمك (القسم 3) وتأكد أن الهاتف البرمجي يرن ويجيب.
4. إذا كنت قد سجلت جهاز VoIP للجوال (القسم 1)، فضع تطبيق الجوال في الخلفية وتأكد من ظهور واجهة مكالمة واردة أصلية.

**قواعد استكشاف الأخطاء، بالترتيب الذي ستصادفها به:**

| العرض | ما تتحقق منه |
| - | - |
| `403 Organisation does not own phone number …` عند التسجيل | قيمة `callerIdNumber` ليست رقمًا نشطًا في حسابك (إنها بوابة ملكية لا خلل تنسيق). |
| `SERVICE_UNAVAILABLE` / "softphone is not configured" | لم يضبط المشغل إعداد SIP WSS/HMAC في الخادم — لا يستطيع المتصفح المتابعة. |
| لا تظهر مطالبة الميكروفون أبدًا | الصفحة ليست HTTPS، أو تطلبها عند تحميل الصفحة بدل إيماءة مستخدم. |
| التسجيل/الاتصال ينجح والمكالمة صامتة | حجبت الشبكة المؤسسية UDP/TURN — تحقق من مضيفي الـ relay والمنافذ واستثناءات الوكيل في [صفحة متطلبات الشبكة](https://docs.orbit.devotel.io/voice/network-requirements.md). |
| تموت الجلسة بعد \~60 دقيقة | لا يُعاد إصدار بيانات الاعتماد عند `expiresAt` — حدّثها. |
| يرن الجوال دون المتصفح (أو العكس) | من المتوقع أن يرنا معًا — هذا الرنين المتوازي لا عطل. |
| لا يبلغ الوارد الهاتف البرمجي | الرقم غير موجَّه إلى الطابور أو عنوان SIP الذي يجلس عليه هاتفك البرمجي — أصلحه في القسم 3 لا في العميل. |

وتأكد أيضًا أنك لا تعيد استخدام نقطة النهاية الخطأ: register (SIP/WSS) ↔ عملاء SIP، وtoken ↔ عملاء LiveKit، و`voip-devices` ↔ إشعارات الجوال فقط.

## إلى أين تذهب بعد ذلك

* [متطلبات شبكة الهاتف البرمجي](https://docs.orbit.devotel.io/voice/network-requirements.md) —
  المنافذ والمضيفات وقائمة الوكيل لإدراجها في القائمة البيضاء لمكالمات
  المتصفح على جدار ناري مؤسسي أو VPN.
* [صفحة المكالمة التجريبية في SDK](https://docs.orbit.devotel.io/guides/sdk-demo-browser-softphone.md) —
  أجرِ مكالمة تجريبية صادرة حقيقية من لوحة التحكم (Developer → SDK Live Demo)
  للتأكد من سلامة هذا الإعداد من طرف إلى طرف.
* [إعداد SIP trunk](https://docs.orbit.devotel.io/guides/sip-trunk-setup.md) — إن أردت إحضار
  ناقل/trunk خاص بك إلى جانب الهاتف البرمجي في المتصفح.
* [طوابير الصوت](https://docs.orbit.devotel.io/guides/voice-queues.md) — طابور ACD الذي تمر عبره
  المكالمات الواردة قبل أن يجيب الهاتف البرمجي.
* [Web SDK](https://docs.orbit.devotel.io/sdks/web.md) — خريطة الأحداث الكاملة لـ `Softphone`
  وسائر أسطح SDK.
* [رحلة تأهيل الأسبوع الأول للموظفين](https://docs.orbit.devotel.io/guides/agent-first-week-onboarding-journey.md) —
  الرحلة التي تضع الهاتف البرمجي في الأسبوع الأول لموظف جديد
  (من المصدر الإنجليزي حتى يُنشر البديل المترجم).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.