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

# n8n: شغّل سير عمل عند تحرك عميل محتمل

> استقبل webhook موقّعًا في n8n، وتحقق منه، وتصرّف بناءً عليه — بلا استطلاع دوري.

عندما يبلغ عميل محتمل مرحلة تهمك، اجعل n8n يفعل شيئًا: ينشر في Slack، أو يكتب صفًا في Sheets، أو
يفتح مهمة في Jira، أو يراسل العميل عبرنا.

نحن ندفع إلى n8n. فلا تستطلع، ولا يحتاج n8n بيانات اعتماد لواجهتنا إلا إذا كان سير العمل يكتب
مجددًا.

## ما تحتاجه أولًا

<Steps>
  <Step title="سير عمل في n8n فيه عقدة Webhook">
    أضف عقدة **Webhook** بطريقة `POST`. ويمنحك n8n رابطين — رابط *اختبار* يستمع فقط أثناء فتح
    المحرر، ورابط *إنتاج* يعمل بعد تفعيل سير العمل. ابدأ برابط الاختبار.
  </Step>

  <Step title="نقطة نهاية webhook في لينكياسوفت">
    **التكاملات ← Webhooks ← نقطة نهاية جديدة**. الصق رابط n8n، واشترك في
    `lead.stage.changed`.
  </Step>

  <Step title="مفتاح التوقيع">
    يُعرض مرة واحدة عند إنشاء نقطة النهاية. انسخه — فـ n8n يحتاجه للتحقق من أن الطلب جاء منا فعلًا.
  </Step>
</Steps>

<Note>
  رابط الاختبار في n8n يقبل طلبًا **واحدًا** فقط لكل ضغطة على "Listen for test event". فإذا بدا أن
  اختبارك الثاني اختفى، فهذا هو السبب — اضغط الاستماع من جديد.
</Note>

## اختر حقولك

حمولة تغيّر المرحلة قد تحمل اسم العميل المحتمل وبريده وهاتفه وقيمته ومالكه وأكثر. وسير عمل n8n
ينتهي عادةً في قنوات Slack وجداول البيانات، فأرسل ما يستخدمه سير العمل فقط.

ولإشعار Slack، هذا يكفي عادةً:

| الحقل               | لماذا                      |
| ------------------- | -------------------------- |
| `lead_id`           | للرجوع إلى العميل المحتمل  |
| `name`              | من هو                      |
| `status`            | أين استقر                  |
| `previous_status`   | من أين جاء                 |
| `value`، `currency` | الرقم الذي يهم الناس فعلًا |

وأزل تحديد `email` و`phone` ما لم يكن سير العمل بحاجة إلى مراسلة أحد. راجع
[اختيار الحقول المرسلة](/ar/webhooks#choosing-which-fields-to-send).

## تحقق من التوقيع داخل n8n

أي شخص يعرف رابط n8n لديك يستطيع إرسال POST إليه. والتوقيع هو الفارق بين «تحرك عميل محتمل»
و«أخبرني أحدهم أن عميلًا محتملًا تحرك».

أضف عقدة **Code** مباشرة بعد عقدة Webhook:

```javascript theme={null}
const crypto = require('crypto');

const secret = 'whsec_...';               // better: $env.LINKIA_WEBHOOK_SECRET
const header = $input.first().headers['x-linkia-signature'] ?? '';
const rawBody = $input.first().body;

const parts = Object.fromEntries(header.split(',').map((p) => p.trim().split('=')));
const timestamp = Number(parts.t);

if (!Number.isFinite(timestamp) || Math.abs(Date.now() / 1000 - timestamp) > 300) {
  throw new Error('Signature timestamp missing or too old');
}

const expected = crypto
  .createHmac('sha256', secret)
  .update(`${timestamp}.${JSON.stringify(rawBody)}`)
  .digest('hex');

if (expected !== parts.v1) {
  throw new Error('Bad signature — this did not come from Linkiasoft');
}

return $input.all();
```

<Warning>
  `JSON.stringify(rawBody)` تعمل فقط لأن n8n حلّل الـ JSON بالفعل وأنت تعيد تسلسله. وهذا هشّ — فهو
  يعتمد على بقاء ترتيب المفاتيح كما هو بعد الرحلة.

  ولأي شيء تعتمد عليه، فعّل خيار **Raw Body** في عقدة Webhook وجزّئ النص الخام بدلًا من ذلك. راجع
  [التحقق من التوقيع](/ar/webhooks#verifying-the-signature) لمعرفة سبب أهمية ذلك.
</Warning>

وضع المفتاح في متغير بيئة في n8n بدل جسم العقدة — فملفات سير العمل تُصدَّر وتُشارك وتُودَع في
مستودعات الشيفرة.

## تصرّف بناءً عليه

بعد عقدة Code، تُوجّه عقدة **Switch** أو **IF** على `{{ $json.body.data.status }}` حسب المرحلة.
ثم ترسل عقدة Slack شيئًا مثل:

```
🎉 {{ $json.body.data.name }} moved to {{ $json.body.data.status }}
   ({{ $json.body.data.value }} {{ $json.body.data.currency }})
```

ولمراسلة العميل عبر واتساب، أضف عقدة **HTTP Request** تستدعي
[`POST /v1/conversations/send`](/api-reference/conversations/send-a-message) بمفتاح API نطاقه
`conversations:send`. واقرأ
[قاعدة الـ 24 ساعة](/ar/introduction#the-one-whatsapp-rule-that-catches-everyone) أولًا — فالإشعار
الذي يبدأه سير عملك يحتاج قالبًا معتمدًا في الغالب الأعم.

## الانتقال إلى الإنتاج

شيئان يتغيران عند الانتقال من رابط الاختبار:

1. **حدّث رابط نقطة النهاية في لينكياسوفت** إلى رابط الإنتاج في n8n. فهما مساران مختلفان — وإعادة
   استخدام رابط الاختبار تعني توقف التسليم لحظة إغلاق المحرر.
2. **فعّل سير العمل.** فسير العمل غير المفعّل يعيد `404`، ونحن نعتبرها نهائية ولا نعيد المحاولة أبدًا.

## عندما لا يصل شيء

تحقق بهذا الترتيب — والإجابة في الخطوة 1 دائمًا تقريبًا.

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

2. **رمز الحالة في ذلك السجل.**

   | الرمز            | يعني عادةً                                             |
   | ---------------- | ------------------------------------------------------ |
   | `404`            | سير العمل غير مفعّل، أو تستخدم رابط الاختبار           |
   | `403` / `401`    | لدى n8n مصادقة خاصة به على عقدة webhook                |
   | `500`            | عقدة Code لديك رمت خطأ — وغالبًا فشل التحقق من التوقيع |
   | *(لا شيء)*، مهلة | n8n غير متاح، أو استغرق أكثر من 10 ثوانٍ               |

3. **قائمة عمليات التنفيذ في n8n نفسه.** فإذا سجّلنا `2xx` ولم يحدث شيء، فالطلب وصل والخلل في سير
   العمل.

<Warning>
  عشرون إخفاقًا متتاليًا **تعطّل نقطة النهاية** وتتوقف الأحداث عن الاصطفاف. فإذا تركت سير عمل معطلًا
  يفشل طوال الليل، تحقق أولًا مما إذا كانت نقطة النهاية ما زالت مفعّلة قبل تصحيح أي شيء آخر.
</Warning>

## أمران يوقعان بك

**كلا الحدثين `lead.updated` و`lead.stage.changed` يقعان عند نقل المرحلة.** اشترك في واحد. فإن
أخذت الاثنين، شغّل كل نقل سير عملك مرتين.

**التسليم مرة واحدة على الأقل.** فمهلة انتهت بعد تشغيل سير عملك فعلًا تعني أننا نعيد المحاولة
فيعمل ثانية. وإذا كان ينشر في Slack، ستحصل على رسالتين؛ وإذا كان يخصم مالًا، فلديك مشكلة حقيقية.
أزل التكرار بالاعتماد على `{{ $json.body.id }}`، فهو ثابت عبر كل محاولات التسليم نفسه.
