عمليات المخاطر / 4 دقائق قراءة

إعادة إرسال Webhooks دون تكرار الحالات

استقبل الـ Webhook بسرعة، واحفظ المعرّفات، واجعل كل تحديث آمنًا عند تكراره، حتى لا يفتح الإرسال الثاني حالة مراجعة جديدة.

بقلم Naiza

١١‏/٠٧‏/٢٠٢٦ · آخر تحديث ٠٥‏/١٠‏/٢٠٢٦

لا ينتهي قرار الاحتيال بعودة رد الواجهة؛ فما زال على أحد المحللين أن يفتح حالة ويكتب ملاحظة، وربما يعلّق عملية صرف، ثم يرسل تصنيفًا لاحقًا. هذا العمل يصلك عبر Webhooks، وقد يصل مرتين. وإذا لم يكن المعالج idempotent فالتسليم الثاني يعني حالة مكررة، أو تذكرة يُعاد فتحها، أو عميلًا يصله بريدان بعنوان «نراجع دفعتك».

استخدم نقطة استقبال الـ Webhook لاستلام الرسائل والتحقق منها، لا لإنشاء الحالات.

استقبل واحفظ ثم أرسل الرد

تحقق من التوقيع، واحفظ بيانات الطلب والمعرّفات التي ستستخدمها كمفاتيح: eventType مع data.id (مفتاح منع التكرار الموثّق)، ومعرّف الحدث أو القرار داخل بيانات الطلب، ومعرّف الحالة لديك إن وُجد. ضع الرسالة في قائمة المهام، ثم أعد استجابة نجاح بعد حفظها. لا تنشئ الحالة أو ترسل إشعارًا للعميل أو تستدعِ خدمات أخرى داخل طلب HTTP، فهذه الخطوات قد تتجاوز المهلة وتسبب إعادة إرسال الرسالة.

POST /webhooks/naiza/risk

وللتفاصيل ابدأ بـمرجع Webhooks. والنمط واحد في الاحتيال وفي AML: استقبل بسرعة، وعالج مرة واحدة.

نفّذ العمل الطويل عبر قائمة مهام تعيد المحاولة بفواصل زمنية متزايدة، وأبقِ معالج HTTP بسيطًا.

حدث واحد، حالة واحدة

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

سجّل آخر قرار طُبّق. رسائل REVIEW أو BLOCK المتكررة يجب ألا تعيد فتح حالة أغلقها المراجع كنشاط سليم. وALLOW المتكرر يجب ألا يلغي تعليقًا طبقته لسبب آخر. ويجب أن تمر تغييرات الحالة التي يراها العميل عبر مسار انتقال واحد واضح في منتجك: بانتظار المراجعة، مدفوعة، مرفوضة. والـ Webhook مدخل لهذا المسار، لا مسار ثانٍ يتعارض معه.

احفظ معرّف الفحص لرسائل AML. يستخدم الاحتيال ALLOW وREVIEW وBLOCK، ويستخدم فحص AML AUTO_CLEAR وREVIEW وCONFIRMED، فاحتفظ بكل تصنيف على حدة. يحتاج المراجع إلى معرفة ما إذا كان التنبيه ناتجًا عن قاعدة تكرار العمليات أو تطابق محتمل مع قائمة.

إعادة محاولة واضحة لفريق التشغيل

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

لا تتعامل مع استجابة 4xx من معالجك على أنها خلل عابر يُحل بإعادة المحاولة، بل أصلح التوقيع أو العنوان أو قراءة بيانات الطلب. أما 5xx وانتهاء المهلة فتُعاد محاولتهما من جهة التسليم مع jitter، وفي طابور المعالجة لديك أعد محاولة مهمة المعالجة نفسها لا استلام طلب HTTP.

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

أكمل دورة التحقيق بإرسال النتيجة

عند انتهاء التحقيق، أرسل التصنيف النهائي ومرجع الحالة إلى نيزا مرة واحدة. اربط الإرسال بمعرّف الحدث ومعرّف الحالة حتى لا ينشئ النقر المزدوج في أداة الحالات تصنيفين. هذا السجل هو ما ستحتاجه حين يسأل أحدهم لماذا شُدّدت قاعدة.

لا ترسل نتائج التحقيق تلقائيًا من معالج الـ Webhook. الـ Webhook يخبرك بقرار نيزا، ونتيجة التحقيق تخبر نيزا بما توصلت إليه. الخلط بينهما يجعل نتيجة REVIEW الأولى تُسجَّل كأنها احتيال مؤكد.

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

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