Qoyod
الأسعار

 دليل المعرفة

الـ Webhooks في الفوترة الإلكترونية

عند بناء تكامل مع منصة فاتورة لإصدار الفواتير الإلكترونية ومقاصتها، تتعامل واجهات برمجة التطبيقات (API) مع كل فاتورة عبر طلب واستجابة فوريين. لكن التكامل الحقيقي لا يعيش داخل هذا الطلب وحده. حوله تجري أحداث كثيرة: المنصة الوسيطة تنهي معالجة دفعة فواتير، نظام قيود يكمل ربط شهادة، عملية إبلاغ مؤجّلة تصل إلى نتيجتها بعد ثوانٍ أو دقائق. كيف يعرف نظامك بهذه الأحداث دون أن يستجوب الخادم كل ثانية؟ الجواب هو الـ Webhooks.

هذا الدليل يشرح ما الـ Webhook، ومتى يكون أداة التكامل الصحيحة ومتى لا يكون، وكيف تستقبل استدعاءات الحالة غير المتزامنة بأمان، وكيف تتحقق من توقيع الرسالة، وكيف تتعامل مع التسليم المكرر بشكل خامل (idempotent)، وكيف تعالج إعادات المحاولة من المرسِل. الهدف أن يخرج المطوّر بنموذج عملي يصمد في الإنتاج، مبني على فهم دقيق لما هو متزامن وما هو غير متزامن في الفوترة الإلكترونية.

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

ما الـ Webhook ولماذا نحتاجه

الـ Webhook هو استدعاء HTTP يرسله نظام مصدر إلى رابط (URL) تملكه أنت، فور وقوع حدث يهمّك. بدل أن يسأل نظامك الخادم باستمرار «هل اكتملت العملية؟»، ينقلب الاتجاه: الخادم هو من يطرق بابك حين تصبح النتيجة جاهزة. لذلك يوصف الـ Webhook أحياناً بأنه «API معكوس»، فأنت هنا الخادم الذي يستقبل، لا العميل الذي يطلب.

الفرق الجوهري بين النمطين يتلخص في من يبدأ الاتصال. في الاستجواب الدوري (Polling) يبدأ نظامك الطلب على فترات ثابتة، فيهدر طلبات كثيرة فارغة وينتظر النتيجة بتأخير قد يبلغ مدة الفاصل الزمني كاملة. في الـ Webhook يبدأ المصدر الاتصال لحظة وقوع الحدث، فتصل النتيجة شبه فورية دون طلبات فارغة. هذا يجعل الـ Webhook الخيار الأنسب للأحداث غير المتزامنة التي لا تعرف متى تقع بالضبط.

متى يكون الـ Webhook أداة صحيحة في الفوترة الإلكترونية

هنا تجب الدقة لتفادي خطأ شائع. مقاصة الفاتورة (Clearance) للفواتير الضريبية B2B لدى منصة فاتورة عملية متزامنة: ترسل الفاتورة في طلب واحد وتنتظر الاستجابة في نفس الاتصال، فتعرف فوراً هل قُبلت أم رُفضت. كذلك الإبلاغ (Reporting) للفواتير المبسّطة B2C يجري عبر طلب واستجابة، حتى وإن كان قريباً من الفوري لا فورياً تماماً. أي أن نتيجة الهيئة لا تصلك عبر Webhook، بل في جسم الاستجابة المباشرة للطلب الذي أرسلته. هذه نقطة لا تقبل الخلط.

إذن أين يصلح الـ Webhook؟ يصلح في الطبقة التي تحيط بالتكامل، لا في نداء الهيئة نفسه. الأمثلة العملية:

  • أحداث يصدرها نظام قيود نفسه: «اكتمل إصدار الفاتورة»، «اكتملت مقاصة الفاتورة بنجاح»، «رُفضت الفاتورة وتحتاج تصحيحاً»، «اكتمل ربط شهادة CSID».
  • أحداث من منصة وسيطة (middleware) تدير دفعات الفواتير نيابة عنك وتبلغك بنتيجة كل دفعة حين تنتهي معالجتها.
  • عمليات تعمل في الخلفية لديك: مثل مزامنة ليلية تعالج آلاف الفواتير، فتُعلِم نظام المحاسبة بانتهائها عبر Webhook بدل إبقائه ينتظر.

الخلاصة: المقاصة والإبلاغ لدى الهيئة متزامنان، والـ Webhook يخدم الأحداث التي تدور حول هذه العملية داخل منصات التكامل وأنظمة قيود، لا داخل نداء الهيئة المباشر.

الاستجواب الدوري مقابل الـ Webhook: متى تختار أيّهما

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

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

الاستجواب الدوري مقابل Webhook
لماذا الـWebhook أكفأ من سؤال الخادم المتكرر.
المعيار الاستجواب الدوري Webhook
النمط طلبات متكررة غالبها فارغ حدث واحد عند توفّر النتيجة
الكفاءة يهدر الموارد فوري وموفّر
التوقيت متأخر بفاصل السؤال لحظي عند الحدث
واجهات فاتورة للمقاصة والإبلاغ متزامنة؛ الـWebhook لأحداث التكامل المحيطة.

بنية حمولة الـ Webhook (Payload)

حين يقع الحدث، يرسل المصدر طلب HTTP من نوع POST إلى رابطك، وجسمه عادة JSON يصف الحدث. الحمولة الجيدة تحمل ما يكفي لتعرف ماذا وقع، ومتى، ولأي كيان، ومعرّفاً فريداً للتسليم نفسه. فيما يلي نموذج لحمولة حدث «اكتمال مقاصة فاتورة» كما قد تصلك من طبقة التكامل:

POST /webhooks/qoyod HTTP/1.1
Host: your-app.example.com
Content-Type: application/json
X-Qoyod-Event: invoice.cleared
X-Qoyod-Delivery: 8f3c1d2a-7b44-4e90-9a21-6c5e0f2b1d77
X-Qoyod-Signature: sha256=4a7d1ed414474e4033ac29ccb8653d9b...
X-Qoyod-Timestamp: 1718900000

{
  "id": "evt_01HZX9K2M7",
  "type": "invoice.cleared",
  "createdAt": "2026-06-20T10:13:20Z",
  "data": {
    "invoiceId": "inv_77219",
    "invoiceUuid": "3cf1f8a0-9d2b-4c11-bf3e-2a91d0c4e5b6",
    "status": "CLEARED",
    "clearedAt": "2026-06-20T10:13:19Z"
  }
}

الحقول الأساسية التي يجب أن تتعامل معها بعناية:

  • id أو ترويسة X-Qoyod-Delivery: معرّف فريد لهذا التسليم بالذات. هو مفتاحك لمنع المعالجة المكررة كما سنرى لاحقاً.
  • type: نوع الحدث (مثل invoice.cleared أو invoice.rejected). على أساسه توزّع المعالجة.
  • createdAt وX-Qoyod-Timestamp: زمن وقوع الحدث، يفيد في الترتيب وفي رفض الرسائل القديمة جداً.
  • X-Qoyod-Signature: توقيع رقمي تتحقق منه قبل أن تثق بالحمولة.
  • data: تفاصيل الحدث، وهنا معرّف الفاتورة وحالتها.

لاحظ أن الحمولة لا تحمل قرارات الهيئة مباشرة. هي تصف نتيجة عملية تمّت بالفعل عبر نداء متزامن سابق. أي أن الـ Webhook هنا يُعلِم نظامك بما اكتمل، لا يطلب منك أن تنادي الهيئة.

استقبال الحدث بأمان: التحقق من التوقيع

رابط الـ Webhook عندك مكشوف على الإنترنت. أي طرف يعرف الرابط يستطيع إرسال طلب POST مزيّف يدّعي أن فاتورة قد قُبلت أو رُفضت. لذلك القاعدة الأولى: لا تثق بأي حمولة قبل أن تثبت أنها صدرت فعلاً من المصدر المعلن. وسيلة الإثبات المعتادة توقيع HMAC.

المبدأ بسيط. يشترك المصدر ونظامك في سر واحد (signing secret). يحسب المصدر بصمة HMAC-SHA256 على جسم الطلب الخام باستخدام هذا السر، ويضعها في ترويسة X-Qoyod-Signature. عند الاستقبال، تحسب أنت البصمة نفسها على الجسم الخام بالسر ذاته، ثم تقارن. إن تطابقت البصمتان فالرسالة أصيلة ولم تُعدَّل.

const crypto = require("crypto");

function verifySignature(rawBody, signatureHeader, secret) {
  // احسب البصمة المتوقعة على الجسم الخام كما وصل تماماً
  const expected = "sha256=" + crypto
    .createHmac("sha256", secret)
    .update(rawBody, "utf8")
    .digest("hex");

  const a = Buffer.from(expected);
  const b = Buffer.from(signatureHeader || "");
  // المقارنة بزمن ثابت لتفادي تسريب المعلومة عبر فروق التوقيت
  if (a.length !== b.length) return false;
  return crypto.timingSafeEqual(a, b);
}

ثلاث قواعد لا تتهاون فيها عند التحقق:

  • احسب البصمة على الجسم الخام (raw body) قبل أي تحليل JSON. تحليل الجسم ثم إعادة تسلسله يغيّر البايتات فتفشل المطابقة.
  • قارن البصمتين بدالة مقارنة ثابتة الزمن مثل timingSafeEqual، لا بمساواة النص العادية، حتى لا تسرّب معلومة عبر فروق توقيت الرفض.
  • افحص الطابع الزمني في X-Qoyod-Timestamp، وارفض الرسائل التي يتجاوز عمرها نافذة معقولة (خمس دقائق مثلاً)، حتى تحبط هجمات إعادة الإرسال (replay) بحمولة قديمة موقّعة.

أضف إلى ذلك شرطاً بسيطاً وحاسماً: استقبل الـ Webhooks على HTTPS فقط. الرابط بـ HTTP عادي يمرّر التوقيع والحمولة بنص مكشوف على الشبكة، فيسهل اعتراضهما والعبث بهما. منصات التكامل الجادة ترفض أصلاً تسليم أي Webhook إلى رابط غير مؤمَّن.

تصميم نقطة الاستقبال بعقلية دفاعية

تعامل مع رابط الـ Webhook كأي واجهة عامة معرّضة للهجوم. ضع حداً أعلى لحجم الجسم المقبول حتى لا يُغرق طرف خبيث ذاكرتك بحمولة ضخمة. لا تفترض أن الحمولة JSON صالح بنيوياً، بل حلّلها داخل كتلة معالجة أخطاء، وإن فشل التحليل أرجع 400 دون أن ينهار الطلب. سجّل لكل تسليم معرّفه الفريد وزمن وصوله ونتيجة معالجته، فهذا السجل أداتك الأولى حين تشخّص مشكلة لاحقاً.

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

استقبال حدث Webhook بأمان
كيف يتحقق نظامك من صحة الحدث الوارد.
1

استقبال POST عبر HTTPS

2

التحقق من توقيع HMAC

3

التحقق من نافذة الطابع الزمني

4

الرد 200 ثم المعالجة

أي فشل في التحقق يُرفَض الحدث (401/400) قبل المعالجة.

الردّ الصحيح على المرسِل وأثره في إعادة المحاولة

المصدر يحكم على نجاح التسليم من رمز حالة HTTP الذي ترجعه. إن أرجعت رمزاً ضمن النطاق 2xx اعتبر التسليم ناجحاً وتوقف. إن أرجعت 5xx أو انتهت المهلة دون رد، اعتبر التسليم فاشلاً وأعاد المحاولة لاحقاً. هذه القاعدة تربط هذا الدليل مباشرة بـمنطق إعادة المحاولة، لكن من جهة المرسِل لا المرسَل إليه.

من هنا تنبثق قاعدة تصميمية مهمة: أرجع 200 بسرعة، ثم عالج الحدث في الخلفية. إن انتظرت حتى تنهي معالجة ثقيلة (مزامنة محاسبية، تحديث قاعدة بيانات، إرسال إشعارات) قبل أن ترد، فقد تتجاوز مهلة المصدر فيظنّ التسليم فاشلاً ويعيد إرساله، فتعالج الحدث مرتين. الأسلم أن تتحقق من التوقيع، تحفظ الحدث في طابور داخلي، ترجع 200 فوراً، ثم تعالجه بعامل منفصل.

متى ترجع رمز خطأ عمداً؟ أرجع 401 حين يفشل التحقق من التوقيع، و400 حين تكون الحمولة مشوّهة أو الطابع الزمني خارج النافذة. أما حين تستقبل حدثاً صحيحاً لكن يخفق نظامك الداخلي مؤقتاً في معالجته، فأرجع 5xx كي يعيد المصدر المحاولة بدل أن يسقط الحدث صامتاً.

المعالجة الخاملة: التعامل مع التسليم المكرر

أهم حقيقة في عالم الـ Webhooks: التسليم «مرة واحدة على الأقل»، لا «مرة واحدة بالضبط». بمعنى أن المصدر يضمن أن يصلك الحدث، لكنه لا يضمن ألا يصلك مكرراً. قد يصلك الحدث ذاته مرتين لأن ردّك الأول تأخّر، أو لأن الشبكة قطعت الرد بعد أن عالجت أنت الحدث فعلاً، فأعاد المصدر المحاولة ظنّاً منه أن التسليم فشل.

لذلك يجب أن تكون معالجتك خاملة (idempotent): تنفيذ الحدث ذاته مرتين يعطي نفس النتيجة كأنه نُفّذ مرة واحدة. وإلا فقد تسجّل الفاتورة مرتين، أو ترسل إشعارين، أو تحدّث رصيداً مرتين. المفتاح هو معرّف التسليم الفريد id أو X-Qoyod-Delivery.

async function handleEvent(event) {
  // سجّل المعرّف الفريد أولاً. عمود فريد في قاعدة البيانات يمنع التكرار.
  try {
    await db.insert("processed_events", { event_id: event.id });
  } catch (err) {
    if (err.code === "UNIQUE_VIOLATION") {
      // وصل هذا الحدث وعولج من قبل. تجاهله بهدوء وأرجع 200.
      return { status: 200, note: "duplicate_ignored" };
    }
    throw err;
  }

  // أول مرة نرى فيها هذا الحدث: عالجه فعلياً
  await applyBusinessLogic(event);
  return { status: 200 };
}

قاعدة عملية: اجعل عمود event_id مفتاحاً فريداً في جدول الأحداث المعالَجة. الإدراج الأول ينجح فتعالج الحدث، والإدراج الثاني يفشل بانتهاك القيد الفريد فتتجاهل التكرار بهدوء وترجع 200. هكذا يصبح التكرار غير مؤذٍ بنيوياً، لا بمجرد الأمل.

انتبه إلى تمييز دقيق: لا تخلط بين «الحدث» و«الكيان». معرّف الحدث event.id يخص هذا التسليم، أما معرّف الفاتورة invoiceUuid فيخص الكيان نفسه. قد تصلك أحداث مختلفة عن الفاتورة ذاتها (أُصدرت، ثم قُبلت)، فلا ترفضها بحجة أنها لنفس الفاتورة. الخمول يقوم على معرّف الحدث الفريد، لا على معرّف الكيان.

المعالجة الخاملة (Idempotency)
كيف تتعامل مع تكرار تسليم نفس الحدث.
1

حدث بمعرّف event_id

2

تسليم مكرر لنفس المعرّف

3

مفتاح فريد: تجاهل وأعد 200

التسليم مرة-على-الأقل يتطلب معالجة خاملة لمنع التكرار.

سيناريو كامل: من وقوع الحدث إلى تحديث نظامك

لنجمع الطبقات في مسار واحد. عميل يصدر فاتورة B2B عبر منصة تكامل. المنصة تنادي واجهة المقاصة لدى الهيئة في طلب متزامن، فتعود الاستجابة بأن الفاتورة قُبلت. حتى هنا لا Webhook في الصورة، فالنتيجة وصلت في جسم الاستجابة المباشرة.

بعد ذلك تريد المنصة إبلاغ نظامك المحاسبي بأن المقاصة تمّت كي تحدّث حالة الفاتورة عندك. هنا يدخل الـ Webhook. ترسل المنصة طلب POST إلى رابطك بحدث invoice.cleared موقّعاً بـ HMAC. نظامك يتحقق من التوقيع، يفحص الطابع الزمني، يسجّل معرّف الحدث الفريد، يرجع 200 فوراً، ثم يحدّث حالة الفاتورة إلى «مقبولة» في الخلفية.

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

ترتيب الأحداث: لا تفترض الوصول بالتسلسل

قد تصلك أحداث الفاتورة الواحدة بترتيب مختلف عن ترتيب وقوعها. مثلاً يصلك حدث «تغيّرت الحالة إلى مقبولة» قبل حدث «أُصدرت الفاتورة»، لأن الشبكة وإعادات المحاولة لا تحفظ التسلسل. إن بنيت منطقك على افتراض الوصول المرتّب، فقد تكتب حالة قديمة فوق حالة أحدث.

العلاج أن تعتمد على الطابع الزمني داخل الحمولة لا على ترتيب الوصول. خزّن مع كل فاتورة زمن آخر حدث طبّقته، ثم تجاهل أي حدث أقدم منه. هكذا يبقى نظامك متّسقاً حتى لو وصلت الأحداث مبعثرة. القاعدة: رتّب بالمحتوى (createdAt) لا بزمن الاستقبال.

async function applyIfNewer(invoiceId, event) {
  const current = await db.get("invoices", invoiceId);
  // طبّق الحدث فقط إن كان أحدث من آخر حالة مسجّلة
  if (current && current.lastEventAt >= event.createdAt) {
    return; // حدث متقادم، تجاهله للحفاظ على الاتساق
  }
  await db.update("invoices", invoiceId, {
    status: event.data.status,
    lastEventAt: event.createdAt
  });
}

إعادة المحاولة من جهة المرسِل وطابور الرسائل الميتة

حين ترجع 5xx أو تنتهي مهلتك، لا ييأس المرسِل من المحاولة الأولى. يعيد التسليم على فترات متزايدة وفق تراجع أسّي: بعد ثوانٍ، ثم دقائق، ثم ساعات، حتى عدد محاولات أقصى. هذا يمنح نظامك فرصة للتعافي من عطل لحظي دون أن يسقط الحدث. وهي القاعدة نفسها المشروحة في منطق إعادة المحاولة، لكن منفّذة لدى مرسِل الـ Webhook هذه المرة.

ماذا يحدث إن بقي نظامك معطّلاً حتى تستنفد كل المحاولات؟ هنا يدخل طابور الرسائل الميتة (dead-letter queue). المرسِل الجاد يحتفظ بالأحداث التي تعذّر تسليمها نهائياً في طابور منفصل، ويتيح لك مراجعتها وإعادة إرسالها يدوياً بعد إصلاح العطل. ومن جهتك أنت أيضاً، من الحكمة أن تحتفظ بنسخة من كل حدث تستقبله قبل معالجته، حتى لو فشلت المعالجة الداخلية تستطيع إعادة تشغيلها لاحقاً دون انتظار إعادة إرسال من المصدر.

الفكرة الجوهرية أن لا حدث يضيع صامتاً. إما يصل ويُعالَج، أو يُعاد تسليمه، أو يُحفظ في طابور للمراجعة. أسوأ حالة هي حدث اختفى دون أثر، لأنه يترك فاتورة بحالة قديمة لا يكتشفها أحد إلا متأخراً.

إدارة السر وتدويره

سر التوقيع (signing secret) هو حجر الأساس في أمان الـ Webhook. تعامل معه كما تعامل كلمة مرور حساسة. لا تضعه في الكود المصدري ولا في مستودع git، بل في متغيرات بيئة أو خزنة أسرار. ولا تطبعه في سجلاتك.

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

  • خزّن السر خارج الكود في متغير بيئة أو خزنة أسرار.
  • ادعم سرّين في نافذة التدوير ثم احذف القديم.
  • لا تطبع السر ولا التوقيع الكامل في السجلات.
  • دوّر فوراً عند أي اشتباه في تسرّب.

قائمة تحقق لتكامل Webhook سليم

  • الرابط يستقبل على HTTPS حصراً، لا HTTP.
  • تتحقق من توقيع HMAC على الجسم الخام بمقارنة ثابتة الزمن.
  • تفحص الطابع الزمني وترفض الرسائل المتقادمة خارج النافذة.
  • ترجع 200 سريعاً ثم تعالج الحدث في الخلفية.
  • ترجع 5xx عند الفشل الداخلي المؤقت ليُعاد التسليم.
  • معالجتك خاملة عبر معرّف الحدث الفريد، فالتكرار غير مؤذٍ.
  • ترتّب الأحداث بالطابع الزمني داخل الحمولة لا بزمن الوصول.
  • تحفظ كل حدث قبل معالجته لتتمكن من إعادة التشغيل.
  • السر مخزّن بأمان وتدعم تدويره دون فقدان رسائل.
  • لا تفترض أن الـ Webhook يحمل نتيجة الهيئة المباشرة.

الأخطاء الشائعة في تكامل الـ Webhooks

  • الثقة بالحمولة دون تحقق من التوقيع. أخطر خطأ. يتيح لأي طرف حقن أحداث مزيّفة. التحقق من HMAC غير قابل للتفاوض.
  • افتراض التسليم مرة واحدة بالضبط. يؤدي إلى ازدواج التسجيل. اجعل المعالجة خاملة عبر معرّف الحدث الفريد.
  • المعالجة الثقيلة قبل الرد. تتسبب في تجاوز المهلة فإعادة الإرسال فالتكرار. أرجع 200 سريعاً وعالج لاحقاً.
  • الخلط بين الـ Webhook ونداء الهيئة. توقّع نتيجة المقاصة أو الإبلاغ في جسم الاستجابة المباشرة، لا عبر Webhook. الهيئة لا تسلّمك نتائجها بهذه الطريقة.
  • إرجاع 200 عند فشل داخلي مؤقت. يسقط الحدث صامتاً. أرجع 5xx ليعيد المصدر المحاولة.
  • قبول HTTP غير المؤمَّن. يكشف التوقيع والحمولة. استقبل على HTTPS حصراً.
  • إهمال نافذة الطابع الزمني. يفتح الباب لهجمات إعادة الإرسال بحمولة قديمة موقّعة. ارفض الرسائل المتقادمة.

كيف يساعدك قيود في طبقة الـ Webhooks

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

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

يستحق التذكير أن قيود لا يسجّل العميل لدى الهيئة نيابة عنه. تسجيل شهادة CSID لدى الهيئة خطوة يقوم بها العميل بنفسه، ويرشده قيود خلالها. كذلك لا يقدّم قيود إقرار ضريبة القيمة المضافة نيابة عن العميل، بل يولّد بيانات الإقرار ليقدّمها العميل عبر بوابة الهيئة.

ابدأ اليوم

فوترة إلكترونية جاهزة دون بناء طبقة تكامل بنفسك

يدير قيود المقاصة والإبلاغ مع منصة فاتورة، ويدير شهادة CSID آلياً، ويبقي حالة فواتيرك محدّثة. ابدأ تجربتك المجانية واترك الطبقة التقنية لقيود.

ابدأ تجربتك المجانية وأصدر فواتيرك المتوافقة

الخطوات التالية في مركز المطوّرين

بعد إتقان استقبال الأحداث عبر الـ Webhooks، الموضوعان المكمّلان مباشرة هما معالجة الأخطاء ومنطق إعادة المحاولة. معالجة الأخطاء في API تشرح كيف تقرأ رموز حالة HTTP وبنية رسائل الأخطاء والتحذيرات القادمة من منصة فاتورة، وهي القواعد ذاتها التي تطبّقها حين ترد على مرسِل الـ Webhook. ومنطق إعادة المحاولة يشرح متى تُعاد المحاولة وكيف تبني تراجعاً أسّياً مع توزيع عشوائي، وهو ما يفعله مرسِل الـ Webhook حين ترجع له 5xx أو تنتهي مهلته.

للمراجعة، تأكد أنك ملمّ بأساس التكامل عبر نقاط نهاية API لمنصة فاتورة، وبشروط قبول الفاتورة عبر قواعد التحقق من الفاتورة. هذه الأدلة مع هذا المقال تكوّن الأساس المتين لأي تكامل ناضج يستقبل أحداث الفوترة الإلكترونية بأمان.

خلاصة عملية

الـ Webhook هو API معكوس يطرق بابك فور وقوع الحدث بدل أن تستجوب الخادم. في الفوترة الإلكترونية لا يصلك عبره قرار الهيئة، لأن المقاصة والإبلاغ يجريان عبر طلب واستجابة متزامنين. الـ Webhook يخدم الأحداث المحيطة: اكتمال الإصدار، نتيجة المقاصة، تغيّر الحالة، اكتمال دفعة لدى منصة وسيطة.

تكامل الـ Webhook الناضج يقوم على أربع ركائز. يتحقق من توقيع HMAC على الجسم الخام بمقارنة ثابتة الزمن. يفحص الطابع الزمني ويرفض المتقادم. يرجع 200 سريعاً ثم يعالج في الخلفية، ويرجع 5xx عند الفشل المؤقت ليُعاد التسليم. ويجعل المعالجة خاملة عبر معرّف الحدث الفريد فلا يؤذيه التكرار. من يفضّل عدم بناء هذه الطبقة بنفسه يحصل عليها جاهزة عبر قيود.

مركز المساعدة

لم تجد ما تبحث عنه؟

لا تقلق، لدينا المزيد من أدوات المساعدة.

ندوات مباشرة يقدمها فريق قيود لمساعدتك في استخدام البرنامج بسهولة والرد على أسئلتك.

تعرّف على أحدث تحديثات فيود والتحسينات المستمرة والخصائص الجديدة في مكان واحد.

فريقنا جاهز لمساعدتك وتقديم الدعم الفوري لأي مشكلة تواجهها على مدار الساعة