التوثيق
الدمجWebhooks

مرجع الأحداث

كل حدث webhook ممكن XPay يبعتهولك، إمتى بيتطلق، والكائن اللي بيحمله.

الأحداث هي الطريقة اللي بيها XPay بيقولّك إن حاجة حصلت على السيرفر بتاعك: دفعة نجحت، أو مبلغ اترد، أو عميل اتعمل. كل حدث بيوصل لنقطتك بيشترك في نفس غلاف الـ JSON؛ اللي بيتغير هو قيمة type والمورد اللي جوّه data.object.

الصفحة دي هي القائمة الرسمية للأحداث اللي تقدر تشترك فيها. علشان تعرف خطوات الاشتراك بالضغط، شوف إعداد نقطة نهاية. وعلشان كود التحقق، شوف التحقق من التوقيعات.

غلاف الحدث

كل تسليم webhook ليه نفس الشكل العام:

{
  "id": "evt_test_AbC123...",
  "object": "event",
  "api_version": "3.1.0",
  "created": "2026-05-01T12:00:00.000Z",
  "type": "checkout.session.completed",
  "livemode": false,
  "data": {
    "object": { "id": "cs_test_...", "object": "checkout.session" }
  }
}
الحقلالنوعالمعنى
idstringمعرّف الحدث، ببادئة evt_test_* أو evt_live_*. ثابت عبر كل محاولات الإعادة. استخدمه كمفتاح عدم التكرار (idempotency).
objectstringدايمًا "event".
api_versionstringنسخة الـ API المستخدمة في تكوين data.object.
createdISO 8601 stringوقت تسجيل الحدث لأول مرة.
typestringنوع الحدث (شوف الجداول تحت).
livemodebooleantrue لأحداث الحساب الفعلي، وfalse لأحداث وضع الاختبار.
data.objectobjectالمورد اللي الحدث بيخصّه. نفس شكل GET /<resource>/:id بالظبط.
requestobject | nullطلب الـ API اللي أنشأ الحدث: { id, idempotency_key }. القيمة request.idempotency_key هي الـ Idempotency-Key اللي بعتّه في الطلب ده (شوف عدم التكرار)، أو null لو ما بعتّش واحد.

الـ data.object مطابق تمامًا للي بيرجعهولك الـ GET endpoint المقابل. لو تقدر تقرا Checkout Session من GET /checkout/sessions/:id، يبقى معالِج checkout.session.completed بتاعك يقدر يقرا نفس الحقول بنفس الأسماء من data.object.

أحداث جلسة الدفع (Checkout Session)

بتتطلق على مراحل حياة جلسة الدفعAPI. دي الأحداث اللي معظم عمليات الدمج بتعتمد عليها.

الحدثبيتطلق لماdata.object
checkout.session.completedدفعة العميل على الجلسة تنجح. حالة الجلسة status بتبقى complete.جلسة الدفعAPI

اشترك في checkout.session.completed علشان تنفّذ الطلب. الحمولة بتحمل الـ paymentIntent والـ customer والـ lineItems بعد ما اتحلّوا، فحدث واحد بيكفي معظم منطق تنفيذ الطلبات. والـ lineItems بيسرد بس اللي العميل اشتراه؛ والإضافات الاختيارية اللي ماضافهاش مش متضمّنة.

أحداث الـ Charge

بتتطلق على مراحل حياة الـ ChargeAPI. الـ Charge هو محاولة واحدة لتحريك فلوس على وسيلة دفع العميل. الدفعة الناجحة بتنتج Charge واحد؛ والعميل اللي أعاد المحاولة بعد رفض بينتج كذا واحد.

الحدثبيتطلق لماdata.object
charge.succeededالـ Charge يتحصّل بنجاح. بيتطلق قبل checkout.session.completed في دفعات الدفع المستضاف.ChargeAPI
charge.failedمحاولة الـ Charge تفشل. بيحمل failureCode وfailureMessage بيوصّفوا السبب.ChargeAPI
charge.refundedاسترداد ناجح (كامل أو جزئي) يتطبّق على الـ Charge. المبلغ المسترد بيبقى في amountRefunded. ومصفوفة refunds.data بتاعت الـ Charge بتحمل كل استرداد اتعمل لحد دلوقتي.ChargeAPI

استخدم أحداث charge.* لو نموذج البيانات بتاعك بيتتبّع الفلوس على مستوى الـ charge (زي الحالات اللي فيها أكتر من تحصيل، أو دفعات معادة). لمعظم عمليات الدمج، الاستماع لـ checkout.session.completed وrefund.* بيكفي.

أحداث الاسترداد (Refund)

بتتطلق على مراحل حياة الـ RefundAPI.

الحدثبيتطلق لماdata.object
refund.createdسجل Refund جديد يتعمل.RefundAPI
refund.failedمحاولة استرداد تفشل. حالة الـ Refund بتبقى failed.RefundAPI

الأحداث دي بتتطلق على المبالغ المستردة سواء اتعملت عن طريق الـ API أو من لوحة التحكم. شوف المبالغ المستردة لمسار الـ API.

الحدث charge.refunded (فوق) بيحمل الـ Charge الأب والـ Refund الجديد متضمَّن جوّه refunds.data، فتقدر تبني تنفيذ الطلب على أي جنب على حسب الكيان اللي نموذج بياناتك بيتتبّعه.

أحداث العميل (Customer)

بتتطلق على مراحل حياة الـ CustomerAPI.

الحدثبيتطلق لماdata.object
customer.createdسجل عميل يتعمل (عن طريق الـ API أو لوحة التحكم).CustomerAPI
customer.updatedخصائص سجل عميل تتغير.CustomerAPI
customer.deletedسجل عميل يتحذف.CustomerAPI

علشان تعرف الفرق بين العميل المسجَّل والعميل الضيف، وإزاي مطابقة الضيوف بتشتغل، شوف دورة حياة العميل.

مراقبة الـ Webhook

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

علشان تعرف جدول الإعادة اللي ورا التنبيه ده، وإزاي تعيد إرسال تسليم بعد ما تصلّح المعالِج، شوف إعادة الإرسال والمحاولات.

الترتيب على دفعة ناجحة

الدفعة الواحدة بتطلق أكتر من حدث. بيوصلوا قريبين من بعض، بس مش بالضرورة بالترتيب؛ تعامل مع كل حدث على إنه مستقل، واعمل إزالة تكرار على event.id.

الترتيبالحدثليه
1charge.succeededالفلوس اتحركت.
2checkout.session.completedالجلسة بقت complete. ده ميعاد تنفيذ الطلب.

وفي حالة الاسترداد:

الترتيبالحدثليه
1refund.createdسجل Refund اتعمل.
2charge.refundedقيمة amountRefunded بتاعت الـ Charge الأب اتحدّثت.

مش لازم تستمع لكلهم. اختار الأحداث اللي نموذج بياناتك محتاجها وتجاهل الباقي.

قراءة data.object

حقل data.object بنفس الشكل اللي كنت هتاخده من الـ GET endpoint المطابق. ما تروحش تستدعي الـ API علشان تجيب المورد تاني بعد ما توصلك حدثه؛ الحمولة فيها كل حاجة النقطة دي كانت هترجّعها أصلًا.

علشان الشكل الرسمي لكل مورد، شوف صفحات الكائنات في مرجع الـ API:

علشان تعرف إزاي الموارد دي بتتركّب مع بعض (وأنهي معرّفات تحتفظ بيها في سجل الطلب بتاعك)، شوف نموذج الكائنات.

تذكير بعدم التكرار

كل حدث ممكن يتسلّم أكتر من مرة: XPay بيعيد المحاولة لما يرجع رد غير 2xx، وممكن تعيد الإرسال يدويًا من الـ Workbench، والرد الناجح اللي ما وصلش لـ XPay بينتج نسخة مكررة. استخدم event.id كمفتاح إزالة التكرار في المعالِج بتاعك.

علشان النمط الكامل، شوف التحقق من التوقيعات ← عدم التكرار.

رايح فين بعد كده

في الصفحة دي