يُوثَّق نشاط المصادقة وتسليم webhooks المرتبط بالإصدار في أحداث المصادقة وwebhooks. لا تسجّل أنواع أحداث المصادقة غير المدرجة مع واجهة برمجة التطبيقات الحالية للوجهات.
نظرة عامة
تُعد webhooks الطريقة التي تُرسل بها Didit تحديثات فورية إلى الخادم الخلفي لديك كلما تغيّرت حالة جلسة تحقق، أو جلسة شركة، أو مستخدم مورّد، أو شركة مورّد، أو معاملة. يتيح لك الاشتراك بوجهة واحدة أو أكثر في الأحداث التي تهمك الاستجابةَ بمجرد جاهزية النتيجة، وعادةً خلال ثوانٍ من إكمال المستخدم الخاضع للتحقق لسير عمله. تُعد webhooks نمط التكامل الموصى به. الاستطلاع عبرGET /v3/session/{id}/decision/ مدعوم كخيار احتياطي، لكنه أبطأ، ويستهلك طلبات أكثر، ويتجاوز أحداثاً مثل data.updated وtransaction.status.updated والتغييرات على مستوى الكيان، وهي أمور لا تُرسل إلا عبر webhooks. اعتبر تسليم webhook مصدر الحقيقة، ولا تستطلع إلا عند بدء التشغيل البارد أو لأغراض المطابقة.
يبدأ هذا الفصل من درس التكامل في أكاديمية Didit من نظرة عامة على webhooks.
يغطي درس الأكاديمية الخاص بالتكامل موضوع webhooks من الدقيقة 3:12: إضافة وجهة، واختيار الأحداث، والسر المشترك الذي ستستخدمه للتحقق أدناه.
مستخدمو Cloudflare / WAF. تُرسل Didit webhooks من عنوان IP الثابت
18.203.201.92 مع User-Agent: DiditWebhook/2.0 +https://didit.me. إذا كانت الحافة لديك تحجب العملاء غير المعروفين، فاسمح بهذا العنوان في Security > WAF > Tools > IP Access Rules، واختر سماح لاسم المضيف المستقبِل.أنواع الأحداث
استخدم القيمة الدقيقة في مصفوفةsubscribed_events الخاصة بالوجهة. لا يوجد حرف بدل للاختيار الشامل، لذا اذكر كل فئة تريد استلامها، ويمكنك توزيع الأحداث على وجهات متعددة.
القيم الواردة في هذا الجدول هي المجموعة الكاملة من الأحداث القابلة للاشتراك، ولا يوجد فيها
session.status.updated ولا kyc.completed أو ما شابه ذلك. أما الإرسال الوحيد الآخر الذي تُجريه Didit فهو الاستدعاء غير الموقّع kyb.registry_search.resolved، ويُرسل إلى webhook_url لكل طلب على حدة تمرّره إلى POST /v3/kyb/search/، وليس إلى وجهة webhook.
بنية الحمولة
الهيكل العام
يشترك كل webhook في الهيكل العام نفسه. تُسلسَل الحقول دائمًا باستخدامsort_keys=True وبفواصل مضغوطة (, / :)، حتى تنتج الحمولة نفسها التوقيع نفسه على الطرفين.
بالنسبة إلى أحداث الجلسة (
status.updated وdata.updated للجلسات العادية وجلسات الشركات)، يتضمن الهيكل العام الحقول التالية أيضًا:
مثال على الهيكل العام للجلسة
مصفوفات V3 المتعددة (مهم)
داخلdecision، تكون كل نتيجة لكل ميزة مصفوفة تحتوي على عدة عناصر، بحيث يمكن لسير عمل واحد أن يتضمن عدة نسخ من الميزة نفسها (على سبيل المثال، عدة فحوصات للهوية عبر مستندات متعددة):
node_id يطابق رسم سير العمل، إضافةً إلى status خاص بالميزة. لا تقرأ الحقول المفردة القديمة في V2 (id_verification وnfc وliveness وface_match وphone وemail وpoa وaml وip_analysis وdatabase_validation)؛ فهي تظهر فقط إذا كانت الوجهة مثبتة صراحةً على webhook_version: "v2".
تُخزَّن نتائج التوقيع الإلكتروني في signatures[]، ولا تظهر إلا عندما يتضمن سير العمل خطوة التوقيع الإلكتروني: عنصر واحد لكل موقّع، يتضمن الموقّع، وتأكيد الرمز، والشهادة، والطابع الزمني، وتجزئات كل مستند ومسارات تنزيله، وملف PDF الخاص بالأدلة. لا يوجد حدث توقيع منفصل: يخبرك status.updated بوقت قراءتها. راجع تقرير التوقيع الإلكتروني.
تُخزَّن نتائج التحقق المصرفي في bank_verifications[]، عنصر واحد لكل خطوة من خطوات التحقق المصرفي. يوضح method في كل عنصر الطريقة التي تم بها التحقق من الحساب: open_banking (تسجيل الدخول إلى البنك)، وaccount_lookup (فحص الحساب)، أو بديل statement أو microdeposits، ويكون null حتى يتم تقييم حساب. عندما يختار الشخص المتابعة من دون استخدام بنكك، تكون قيمة continued_without_bank هي true، ويوضح continuation السبب. تكون قيمة method عندئذٍ none، إلا إذا جرت محاولة تقييم سابقة: راجع متى لا يتمكن الشخص من التحقق من حسابه المصرفي. لا تتم قراءة أي بيانات مالية عند التحقق من الحساب عبر فحص الحساب، لذلك يسرد financial_data.not_collected الأرصدة أو المعاملات أو الدخل التي طلبتها الخطوة. راجع طرق التحقق المصرفي.
قسم Investigator
يحملdecision من الإصدار V3 لجلسة مستخدم أو شركة أيضاً الحقل investigator: وهو آخر مراجعة Investigator للجلسة، أو null إذا لم تكن لها أي مراجعة قط.
ميزات جمع المستندات، وهي مستندات KYB وDocument AI، ليس لها مصفوفة مخصصة بصيغة الجمع، بل تظهر في قائمة
features[] ضمن القرار على شكل { "feature": "DOCUMENT_AI", "node_id": "…" } (عنصر واحد لكل عقدة). راجع Document AI.
تحمل قرارات التحقق من المستخدمين أيضاً كائن biometric_consent واحداً يحدد ما إذا كانت الجلسة تتطلب موافقة بيومترية صريحة، وtrigger، وحالة الإجابة status، وأدلتها. تعني الحالة status: "pending" مع reason: "BIOMETRIC_CONSENT_UNSUPPORTED_SDK" أن حزمة SDK أصلية أقل من 4.10.0 التقطت وجهاً دون خطوة الموافقة. راجع الموافقة البيومترية.
مفاتيح طريقة التحقق من الهوية
يحدد كل عنصر فيid_verifications[] طريقة التحقق من الهوية التي أنتجته، حتى يتمكن المعالج من التفرع بحسب الدليل الذي حصل عليه فعلاً:
تستمر المعالجات الحالية في العمل دون أي تعديل: تضبط جلسة المستند القيمة
verification_method على document وتترك باقي الحقول null. توجد أنواع الحقول تفصيلاً في نماذج البيانات.
جلسة المحفظة المقبولة (status.updated)
حمولات أحداث الكيانات
ACTIVE أو FLAGGED أو BLOCKED. يحتفظ الحدثان user.data.updated وbusiness.data.updated بالحقل status، ويضيفان مصفوفة changed_fields بالإضافة إلى خريطة changes بالصيغة { field: { previous, current } }. تستخدم أحداث business.* الحقل vendor_business_id بدلاً من vendor_user_id.
حمولات أحداث المعاملات
تعمل webhook المعاملات على البنية التحتية نفسها للتوزيع المتعدد وتستخدم الغلاف نفسه، لكنها تعرّف المعاملة بدلاً من الجلسة:action_required هي null، أو الإجراء المعلّق للمستخدم (type بقيمة wallet_ownership أو verification_session، مع url الخاص به) كما هو موضح في الإجراءات المطلوبة من المستخدم.
تُعيَّن المعاملات الجديدة افتراضياً إلى APPROVED. إذا غيّرت قاعدة أو قائمة حظر أو سير عمل حالة المعاملة أثناء إنشائها، فإن الحمولة الأولية transaction.created تعكس الحالة النهائية. يحمل transaction.status.updated الشكل نفسه مع قيمة status المحدّثة. حالات المعاملة هي APPROVED وIN_REVIEW وDECLINED أو AWAITING_USER؛ وseverity هي UNKNOWN / LOW / MEDIUM / HIGH / CRITICAL وdirection هي INBOUND / OUTBOUND. لا يُرسل transaction.created وtransaction.status.updated إلا للتطبيقات في بيئة الإنتاج فقط. أما تبادلات Travel Rule في البيئة التجريبية فتُرسل فعلاً travel_rule.status.updated مع environment: sandbox.
استدعاء نتائج بحث سجل KYB
يُرسل مسارPOST /v3/kyb/search/ غير المتزامن حمولة إضافية واحدة ليست حدث وجهة: عند تمرير webhook_url إلى طلب البحث، يرسل Didit طلب POST بالاستدعاء kyb.registry_search.resolved إلى ذلك الرابط بمجرد أن يُحلّ السجل. وتختلف عن webhook الوجهة في ثلاث نواحٍ:
- هو غير موقّع ولا يحمل ترويسات
X-Signature*؛ بدلاً من ذلك يضع Didit عليه العلامةX-Didit-Unsigned-Callback: true، ويُتحقق منه بمطابقةrequest_idمع المعرّف الذي أعاده طلب البحث. - يُخزَّن اسم الحدث في
event_type(وليسwebhook_type)، ولا يوجدapplication_idولاenvironment. timestampوcreated_atأعداد صحيحة بصيغة epoch، مثل webhooks الأخرى، على خلافcreated_atبصيغة ISO في نقطة نهاية البحث.
timestamp وتبقى غير موقّعة). راجع KYB Registry API للاطلاع على مخطط قائمة المرشحين الكامل.
التحقق من التوقيع
يُوقَّع كل webhook باستخدام HMAC-SHA256 والمفتاحsecret_shared_key الخاص بالوجهة. تُرسَل ثلاثة رؤوس توقيع حتى تختار الرأس الذي يناسب بنيتك التقنية:
الرؤوس التي يرسلها Didit دائمًا:
لمدة 24 ساعة بعد تدوير سر التوقيع للوجهة، تحمل عمليات التسليم أيضًا الرؤوس
X-Signature-Previous وX-Signature-V2-Previous وX-Signature-Simple-Previous (انظر تدوير سر التوقيع).
تدوير سر التوقيع
تُدوِّر سر التوقيع لوجهة webhook من داخل Business Console. لمدة 24 ساعة بعد التدوير، تحمل كل عملية تسليم إلى تلك الوجهة ثلاثة رؤوس إضافية، وهي موقّعة بالسر الذي تم استبداله:
المعالج الذي يقبل التطابق مع رأس التوقيع العادي أو مع رأس
-Previous الخاص به يستمر في التحقق أثناء نشر السر الجديد، إذ يطابق السر القديم رأس -Previous، ويطابق السر الجديد الرأس العادي.
تطبّق نماذج الكود أدناه هذا السلوك.
انشر السر الجديد خلال 24 ساعة، لأنه بعد ذلك لا يتحقق إلا السر الجديد.
يخبرك الحقل previous_secret_expires_at في GET /v3/webhook/destinations/{destination_uuid}/ بموعد انتهاء الساعات الأربع والعشرين.
تُوقَّع عمليات إعادة المحاولة وإعادة الإرسال من جديد بالسر الحالي للوجهة وقت إرسالها، وتحمل رؤوس -Previous فقط خلال الساعات الأربع والعشرين.
إذا أُجري تدوير آخر خلال الساعات الأربع والعشرين، يُلغى أقدم سر فورًا، ولا يبقى صالحًا للتحقق عبر رؤوس -Previous إلا السر الذي كان حاليًا حتى التدوير الجديد، ولمدة 24 ساعة من التدوير الجديد.
رؤوس -Previous موجودة فقط لوجهات webhook.
أما secret_shared_key على مستوى التطبيق، الذي يوقّع webhook_url القديم، فليس له تداخل: إذ يؤدي تدويره عبر rotate_secret_key في PATCH /v3/webhook/ إلى إبطال السر القديم فورًا.
X-Signature-Simple مهمَل
هذا قيد للتوافق، ولا يمكن إصلاحه في مكانه. فالسلسلة القياسية المكونة من أربعة حقول عقد على مستوى البروتوكول: كل مستقبِل يتحقق من X-Signature-Simple يعيد حساب هذه الحقول الأربعة بالضبط، ولذلك فإن تغيير ما يوقّعه الرأس سيكسر كل هؤلاء المستقبِلين بصمت في مسار التحقق من التوقيع. كما أن تغطية الجسم تتطلب شكلًا قياسيًا محددًا لـ JSON يعيد الطرفان إنتاجه بايتًا بايتًا، وقد وفّرت Didit هذا الشكل بالفعل عبر X-Signature-V2. بدلًا من إضافة متغير ثانٍ يغطي الجسم مع قواعد تطبيع خاصة به، يبقى الرأس كما هو ويُهمَل لصالح المتغيرات الموجودة التي تغطي payload كاملة.
وما يعنيه ذلك لك:
- لا يتغير شيء على الشبكة. يستمر إرسال
X-Signature-Simpleمع كل عملية تسليم، وبالطريقة نفسها. تستمر أدوات التحقق القائمة في العمل، وسنعلن أي إزالة مسبقًا بوقت كافٍ. - يجب أن تستخدم التكاملات الجديدة
X-Signature-V2. فهو آمن مع الوسيط البرمجي ويغطي payload كاملة. - إذا لم تستطع الانتقال عن
X-Signature-Simple، فتحقق منه، ثم اجلب السجل من الواجهة البرمجية بدلًا من قراءته من جسم الـ webhook.
لماذا ثلاثة متغيرات
تُعيد بعض أطر الويب (محللات الجسم في Express، والوسيط البرمجي في Django، وبوابات الواجهات البرمجية) ترميز JSON بصمت قبل أن يقرأه المعالج الخاص بك. فإذا احتوى الجسم الأصلي على"José" وأعاد الوسيط كتابته إلى "José"، تتغير البايتات مع أن البيانات واحدة. عندئذٍ يفشل X-Signature. أما X-Signature-V2 فيُحسب من شكل JSON قياسي (ترتيب المفاتيح، وفواصل بلا مسافات، ويونيكود غير مُهرَّب) يعيد معظم الوسطاء إنتاجه بشكل حتمي. وعندما يفشل ذلك أيضًا، يعود X-Signature-Simple المهمَل إلى توقيع سلسلة قصيرة لا تعتمد على المحلل، ولا يوقّع الجسم أبدًا، لذلك لا يستطيع أن يضمن سلامة الجسم.
ترتيب التحقق الموصى به
- جرّب
X-Signature-V2أولاً. أعد ترميزJSON.parse(body)مع فرز المفاتيح والحفاظ على Unicode، ثم احسبHMAC-SHA256(secret, canonical)وقارن الناتج بالرأس باستخدامtimingSafeEqual. - إذا فشل V2 ويمكنك قراءة البايتات الخام، جرّب
X-SignatureمقابلHMAC-SHA256(secret, rawBody). - فقط إذا فشلت الطريقتان، ارجع إلى
X-Signature-Simpleالمتقادمة مقابلHMAC-SHA256(secret, "{timestamp}:{session_id}:{status}:{webhook_type}"). هذه الطريقة تصادق الغلاف وحده: عاملdecisionفي النص على أنه غير موثوق، وأعد جلبه منGET /v3/session/{session_id}/decision/قبل أن تتصرف بناءً عليه.
-Previous المقابل، فاقبل التطابق مع أيٍّ من الرأسين (راجع تدوير السر المشترك للتوقيع).
في جميع الحالات، ارفض أي طلب أقدم من 5 دقائق (abs(now - X-Timestamp) > 300) للحماية من إعادة التشغيل.
سياسة إعادة المحاولة
إذا ردّ endpoint الخاص بك بالرمز5xx أو 404، يعيد Didit المحاولة حتى مرتين مع تأخير متزايد:
- إعادة المحاولة الأولى: بعد نحو دقيقة واحدة من الفشل الأول.
- إعادة المحاولة الثانية: بعد نحو 4 دقائق من إعادة المحاولة الأولى.
attempt: القيمة 1 لأول تسليم لحدث، وواحد زائد على رقم المحاولة التي تكرّرها في كل إعادة محاولة أو إعادة إرسال.
تُرسل إعادات المحاولة التلقائية إلى العنوان الذي أُرسلت إليه المحاولة الأولى، حتى لو غيّرت url الوجهة بعد ذلك.
تُرسل إعادة الإرسال اليدوية إلى عنوان URL الحالي للوجهة، لذلك فإن تصحيح العنوان يصحح إعادة الإرسال اليدوية أيضاً.
قواعد أخرى للتسليم يجب معرفتها:
- تنتهي مهلة طلب HTTP الصادر بعد 5 ثوانٍ.
- يمنع Didit التسليم إلى العناوين الخاصة / localhost كحماية من SSRF، ولا يتبع إعادات التوجيه أبداً. استخدم endpoint عاماً عبر HTTPS يجيب مباشرة.
- يُرفض عنوان
urlللوجهة الذي يحتوي على شرطة مائلة عكسية خام أو محرف تحكم أو أكثر من@واحدة في جزء authority من عنوان URL، باعتباره غير صالح. لا يمكن إنشاء مثل هذا العنوان، ولا يمكن إعادة تسليم عنوان موجود أو إعادة تشغيله. استخدم عنوانhttps://host/pathبسيطاً مع قسم معلومات مستخدم واحد على الأكثر (لعناوين webhook بأسلوب basic-auth). - تُعامَل الاستجابة
2xxعلى أنها نجاح. تُعدّ المهلات وفشل الاتصال قابلة لإعادة المحاولة (وتظهر بالرمزين504و503في سجل التسليم)، أما الاستجابات3xxو4xxباستثناء404فلا تُعاد محاولتها. - عند إعادة المحاولة يعيد Didit حساب التواقيع باستخدام
X-Timestampجديد، فيبقى زوج الطابع الزمني والتوقيع متوافقاً دائماً. - تُوقَّع إعادات المحاولة وإعادات الإرسال بسر التوقيع الحالي للوجهة وقت إرسالها.
ترتيب التسليم
لا يضمن Didit ترتيب وصول webhook إليك. يُضاف كل تسليم إلى قائمة الانتظار بشكل مستقل، وتصل إعادة المحاولة بعد دقائق من المحاولة الأولى، لذلك قد يصلكstatus.updated بالحالة Approved قبل حدث سابق بالحالة In Progress.
ابنِ المستقبِل لديك وفق ذلك:
- عامل webhook على أنه إشارة بأن شيئاً قد تغيّر. عندما يهم الترتيب، استدعِ
GET /v3/session/{session_id}/decision/وتصرّف بناءً علىstatusالحالي. - لا تدع حدثاً أقدم يكتب فوق حالة أحدث: قارن
created_atللحدث مع آخر حدث خزّنته لذلك السجل، وتجاهل الحدث الأقدم. - اعتمد
event_idمفتاحًا للتكرارات، فهو يبقى كما هو عبر إعادات المحاولة.
إعداد وجهة
يمكنك إدارة الوجهات من Business Console > API & Webhooks أو عبر Management API.1
إنشاء الوجهة
استدعِ
POST /v3/webhook/destinations/ (أو انقر إضافة وجهة في الكونسول) مع label وurl عام وwebhook_version ("v3") ومصفوفة subscribed_events تحتوي على كل عائلة أحداث يجب أن يستقبلها هذا endpoint. مطلوب حدث واحد على الأقل، ولا يوجد أي حرف بدل.2
خزّن secret_shared_key
تُعيد استجابة الإنشاء
secret_shared_key الخاص بالوجهة. خزّنه مع أسرار خادمك الأخرى: فهو خاص بهذه الوجهة وحدها، وهو المدخل لجميع صيغ توقيع HMAC-SHA256 الثلاثة. تعيده GET /v3/webhook/destinations/{destination_uuid}/ مرة أخرى لمستدعي API الذين يستخدمون مفتاح API ولمستخدمي الكونسول الذين يمكنهم قراءة webhook.3
نفّذ endpoint
أتِح مسار
POST عاماً عبر HTTPS، واقرأ الجسم الخام، وتحقق من التوقيع (مع تفضيل X-Signature-V2)، وتحقق من نافذة الطابع الزمني، ثم وجّه الحدث حسب webhook_type. أعد 2xx بمجرد إضافة العمل إلى قائمة الانتظار، ونفّذ المعالجة الثقيلة بشكل غير متزامن.4
أكّد الاستلام
راقب تبويب التسليمات الخاص بالوجهة. تُعيد الـ webhooks السليمة الاستجابة
200 خلال ثانية أو ثانيتين. يؤدي 5xx/404 إلى تفعيل سياسة إعادة المحاولة لدى Didit، وتُسقط الإخفاقات المستمرة بعد إعادة المحاولة الثانية.5
كرّر الاختبار باستخدام Try Webhook
استخدم سيناريوهات Try Webhook في الكونسول لتوجيه endpoint الخاص بك عبر payload مقبولة (approved)، ومرفوضة (declined)، وقيد المراجعة (in-review)، وKYB، والكيان، والنشاط، والمعاملة، قبل تفعيل حركة الإنتاج.

أرسل webhook اختباريًا مباشرة من Business Console للتحقق من endpoint الخاص بك قبل الإطلاق.
نماذج الكود
لضمان أمان نقطة نهاية الـ webhook، تحقّق من أصالة الطلبات الواردة باستخدامsecret_shared_key الخاص بالوجهة.
Node.js / Express (المُوصى به: X-Signature-V2)
X-Signature الأصلي يعمل بالطريقة نفسها، لكنه يوقّع النص الخام. احتفظنا به في القسم القديم أدناه للتوثيق الكامل.
Python / FastAPI (المُوصى به: X-Signature-V2)
PHP / Laravel (المُوصى به: X-Signature-V2)
تخالف الإعدادات الافتراضية لـ JSON في PHP الشكلَ المعياري. يجب تجاوز أربعة منها، وأي إغفال لواحد منها يغيّر البايتات الموقّعة، فلا تتطابق البصمة أبدًا:
فخ الكائن الفارغ هو الأشدّ إيلامًا. تحمل payloads الخاصة بـ Didit عادةً خرائط فارغة مثل
risk_view.countries.risk_scores وrisk_view.crimes.risk_scores وrisk_view.custom_list، لذلك يكسر التحويل الترابطي ذهابًا وإيابًا التوقيعَ في الجلسات المقبولة العادية، لا في حالة نادرة استثنائية.
- الأعداد العشرية ذات القيم الصحيحة لا تحتاج إلى معالجة خاصة في PHP. تُسلسلها Didit أعدادًا صحيحة (
100.0→100)، ويكتبjson_encodeفي PHP العدد العشري ذي القيمة الصحيحة بالطريقة نفسها، لذا لا تحتاج إلى خطوةshortenFloats، على عكس نموذج Node.js أعلاه. - أبقِ
serialize_precisionعلى-1(القيمة الافتراضية منذ PHP 7.1). إذا غيّر مضيفك القيمة إلى17، فإنjson_encodeيكتب87.42بوصفه87.420000000000002، وتفشل كل عملية تحقق منX-Signature-V2.
verifySignatureRaw أعلاه هو البديل الأبسط: تُرجع $request->getContent() في Laravel البايتات دون أي تعديل، فيعمل X-Signature طالما لم يُعِد أي شيء قبل PHP ترميزَ النص. وهذه بالضبط الحالة التي صُمّم X-Signature-V2 لتجاوزها، ولهذا يُجرَّب V2 أولًا.
الاختبار
لا تحتاج إلى تشغيل تحقق كامل لاختبار نقطة النهاية الخاصة بك.- من Business Console > API & Webhooks > Try Webhook، اختر سيناريو (مثل
approved_full_featuresوdeclined_face_mismatchوin_review_aml_hitوbusiness_session_approvedوtransaction_createdوactivity_createdوuser_status_updated)، ثم أرسل webhook مكتملة البنية إلى عنوان URL الخاص بالوجهة. - يُوقَّع كل سيناريو بالرؤوس الثلاثة نفسها للتوقيع وبالترميز المعياري نفسه المستخدم في حركة المرور في بيئة الإنتاج، بما في ذلك بيانات اختبار Unicode مثل
approved_kyc_with_unicode، حتى تتأكد من أنX-Signature-V2يعمل عبر البرمجيات الوسيطة لديك. تحمل عمليات التسليم التجريبية بيانات نموذجية، وتُعلَّم برأس إضافي هوX-Didit-Test-Webhook: trueولاحقة(Test)فيUser-Agent، حتى تستطيع استبعادها من الحالة الإنتاجية. - أعِد تشغيل أي تسليم سابق من تبويب التسليمات الخاص بالوجهة إذا احتجت إلى تصحيح تراجع.
أمثلة
جلسة KYC مقبولة (status.updated)
جلسة مرفوضة مع تحذيرات (status.updated)
جلسة شركة مقبولة (status.updated، KYB)
تم إنشاء معاملة (transaction.created)
تغيّرت حالة تبادل Travel Rule (travel_rule.status.updated)
travel_rule_status إحدى حالات التبادل الثلاث عشرة الموثّقة في Travel Rule.
القيمة rail هي INTERNAL أو TRP أو GTR أو TRUST أو VERIFYVASP أو SYGNA أو EMAIL (قيمة فارغة إلى أن يُختار مسار، أو إذا تعذّر تحديد أي مسار، ودائماً في تسجيلات sunrise)، أو TEST_VASP لتحويل في البيئة التجريبية ردّ عليه Didit Test VASP، وقيمة direction هي INBOUND أو OUTBOUND.
يحمل حدث البيئة التجريبية "environment": "sandbox"، ويحمل حدث TEST_VASP أيضاً test_vasp: true وtest_vasp_scenario (السيناريو الذي قدّم الاستجابة).
عندما تُنشئ Didit معاملة لتحويل Travel Rule (استدعاء POST /v3/transactions/، أو تسجيل sunrise بعد الإيداع، أو استفسار TRP وارد، أو المرحلة الواردة على المسار INTERNAL)، فإنها ترسل حدث transaction.created الخاص بتلك المعاملة أولاً، ثم أحداث travel_rule.status.updated الخاصة بالتحويل بعدها.
قد ترسل أيضاً قاعدة تغيّر حالة المعاملة خلال تلك الخطوة الحدث transaction.status.updated قبل transaction.created، وتسجيل sunrise الذي يرتبط بمعاملة إيداع سبق أن أنشأتها لا يرسل transaction.created.
يُسلَّم كل webhook وتُجرى إعادة المحاولة له على حدة، لذا قد يصل حدث أُعيد إرساله بعد حدث لاحق له: اجعل معالجك يعتمد على transaction_id، وأعد قراءة المعاملة عندما تحتاج إلى حالتها الحالية.
لا يحصل التحويل المُرسل عبر TRUST أبداً على حدث COMPLETED، لأن TRUST لا يعيد أي شيء تستطيع Didit قراءته: تبقى الحالة AWAITING_COUNTERPARTY حتى الموعد النهائي للتأكيد ثم تنتهي إلى EXPIRED. أما عبر GTR وVerifyVASP وSygna Bridge، فتقرأ Didit ردّ الطرف المقابل من الشبكة ويأتي الحدث بعده (راجع شبكات Travel Rule).
تغيّر امتثال سير العمل (workflow.compliance_changed)
transition.from وtransition.to إحدى القيم التالية: compliant أو gaps_detected أو pending_change أو unknown_coverage أو not_evaluated.
تكون قيمة severity هي actionable عند رصد فجوات، وindicative في حالة تغيير معلّق، وinformative عند حل الفجوات.
ترسل Didit حدثاً واحداً لكل سير عمل تغيّر.
أُنشئت اقتراحات قواعد المعاملات (transaction_rule_suggestions.created)
kind هي ADD لقاعدة جديدة، وTWEAK لتعديل قاعدة موجودة، وDISABLE لإيقاف قاعدة. تكون قيمة rule_id هي null عند ADD.
open_count هو عدد الاقتراحات التي ما زالت مفتوحة بعد التشغيل، بما فيها الجديدة.
تتحكم إعدادات اقتراحات القواعد في تفعيل هذا webhook أو تعطيله؛ راجع webhooks المعاملات.
أحداث Investigator (investigator.*)
تستخدم الأحداث الاثني عشر investigator.* الغلاف نفسه (event_id، وwebhook_type، وtimestamp، وcreated_at، وapplication_id، وenvironment) ورؤوس التوقيع نفسها التي تستخدمها سائر الأحداث. وهي تحمل المعرّفات والأرقام فقط: لا تتضمن أبداً اسماً، ولا سبباً كتبه المراجِع، ولا سرداً، ولا أي شيء كتبه المستخدم النهائي. ولا تحتوي على session_id؛ والعنصر الذي يتعلق به الحدث مذكور في item.
تحدد
provenance الإصدار الذي كتب به Investigator التقرير:
engineهو إصدار محرّك Investigator: معرّف مبهم مكوّن من ثمانية محارف. يتغيّر كلما تغيّر المحرّك، لذا فإن أي تقريرين يحملان القيمة نفسها لـengineكتبهما المحرّك نفسه.agent_versionهو إصدار الوكيل.policy_versionهو إصدار سياستك الخاصة التي اتّبعها التقرير.model_idاسم بديل مُهمَل يحمل القيمة نفسها التي يحملهاengine. اقرأengineبدلاً منه.- لم يعد يُرسل
prompt_hash.
item.kind نوع العنصر (جلسة، أو جلسة شركة، أو معاملة، أو حالة)، ويحدّد item.id معرّفه. الطوابع الزمنية التي تنتهي بـ _at هي سلاسل نصية بصيغة ISO 8601. اشترك في هذه الأحداث بإدراج السلاسل النصية الدقيقة في subscribed_events، كما في أي حدث آخر.
تغيّرت حالة كيان المستخدم (user.status.updated)
الجلسة المعاد تقديمها
القديم: X-Signature مع الجسم الخام
لا يزالX-Signature يُرسَل مع كل تسليم، وهو HMAC-SHA256 على البايتات الدقيقة التي يرسلها Didit (json.dumps(..., sort_keys=True, separators=(",", ":"))). استخدمه فقط عندما تستطيع قراءة الجسم الخام قبل أن يعدّله أي وسيط برمجي.
- Node.js
- Python
القديم: تنسيق webhook من V2
كائنات الميزات نفسها في الإصدارين متطابقة: تتلقى الوجهة المثبّتة على V2 بالضبط
match_score وrisk_score وscore_breakdown وrisk_view وreview_status لكل تطابق، والدرجة الإجمالية score كما يتلقاها V3 (انظر تقرير AML). التثبيت على V2 يغيّر مكان تقرير AML داخل decision، لا محتواه.
إذا كان مستهلك لاحق ما زال يحتاج إلى بنى V2، فأنشئ وجهة منفصلة مثبّتة على webhook_version: "v2"، وأبقِ مستهلكيك الجدد على V3.
ذات صلة
- واجهة API لوجهات webhook: عرض الوجهات وإنشاؤها وتحديثها وحذفها وفحص سجلات التسليم.
- إنشاء وجهة webhook: مخطط الطلب والاستجابة، ويشمل
secret_shared_keyالخاص بالوجهة. - نماذج البيانات: المخطط المرجعي لكل كائن خاص بميزة مضمَّن في
decision. - مخطط القرار: قائمة الحقول الكاملة لكائن
decisionالمضمَّن في webhooks الخاصة بالجلسات. - حالات التحقق: قيم
statusالدقيقة والانتقالات المشار إليها أعلاه. - تحديد المعدل: الحدود التي تنطبق عند الاستعلام الدوري عن
GET /v3/session/{id}/decision/كخيار احتياطي.