دليل عملي لربط الشحن والدفع والخدمات الخارجية: حالات الطلب، مفاتيح منع التكرار، إعادة المحاولة، الإشعارات والسجلات، مع مثال شحنة لم يصل تأكيدها.
عندما تضغط زر إنشاء شحنة ولا يصل الرد، توجد احتمالات مختلفة: ربما لم يصل الطلب، وربما أنشأ المزود الشحنة وانقطع الاتصال أثناء العودة. إظهار كلمة «فشل» في الحالتين يدفع الموظف إلى المحاولة مجددًا، وقد ينتهي الأمر بشحنتين وفاتورتين. لذلك لا يُقاس نجاح ربط API بظهور استجابة صحيحة مرة واحدة؛ بل بقدرة النظام على تفسير ما يعرفه، وحفظ ما لا يعرفه، واستعادة المسار دون تكرار الأثر.
ابدأ باتفاق واضح حول كل عملية
اكتب بطاقة صغيرة لكل تكامل قبل البرمجة: ما العملية التجارية؟ ما البيانات اللازمة؟ من يملك النتيجة النهائية؟ هل يمكن الاستعلام عنها لاحقًا؟ وما كلفة التكرار؟ البحث عن مدينة في خدمة خرائط يختلف عن إصدار بوليصة شحن أو إنشاء اشتراك. وجود عنوان API ومفتاح وصول لا يجيب عن هذه الأسئلة.
في مثال افتراضي لمتجر كتب، يكون الهدف إنشاء شحنة واحدة للطلب الداخلي ORD-204، بعد اعتماد عنوان التسليم. احفظ عنوانًا معتمدًا ونسخة من العناصر المطلوبة للشحن، ولا تجعل إعادة فتح صفحة الطلب تغير البيانات التي أُرسلت أصلًا. اتفق كذلك على معنى الإلغاء: هل يعني سحب الطلب المحلي، أم أن لدى شركة الشحن إجراءً مستقلًا يجب تأكيده؟ ضع هذه الحدود في ملف متطلبات المشروع.
صمّم حالات تعكس الحقيقة، لا شكل الزر
في هذا المثال يمكن استخدام حالات «جاهز للإرسال»، و«جارٍ التنفيذ»، و«بانتظار التحقق»، و«مؤكد»، و«يتطلب تدخلًا». عند حفظ أمر الشحن أنشئ مرجع عملية ثابتًا قبل التواصل الخارجي. إذا وصلت استجابة ناجحة موثوقة، اربط معرّف الشحنة بذلك المرجع. وإذا انتهت المهلة دون جواب حاسم، انتقل إلى انتظار التحقق؛ لا تقل للعميل إن الشحنة أُلغيت ولا تنشئ أمرًا جديدًا تلقائيًا.
يميز شرح MDN لمفهوم idempotency بين تكرار الاستدعاء وتكرار أثره، ولا يضمن هذا السلوك لطلبات POST. بناءً على ذلك، صمّم إعادة المحاولة وفق عقد المزود، وليس وفق اسم دالة عامة مثل retry. تعطيل الزر مؤقتًا مفيد للتجربة، لكنه لا يحمي من تحديث الصفحة أو وصول طلبين متزامنين.
استخدم مفتاح منع التكرار استخدامًا صحيحًا
إذا كان المزود يدعم مفتاحًا لمنع التكرار، خصص المفتاح للعملية المنطقية الواحدة، وأعد استعماله عندما تعيد الطلب نفسه بالشروط نفسها. لا تولّد مفتاحًا جديدًا لكل ضغطة، ولا تستعمل مفتاح شحنة قديمة لشحنة أخرى. مثال Stripe الرسمي يوضح أن لهذه المفاتيح قواعد احتفاظ ومقارنة للمعلمات؛ لا تفترض أن مزودًا آخر يطبق القواعد نفسها.
لنفترض أن المزود أنشأ SH-781 لكن الرد ضاع. يظل ORD-204 مرتبطًا بالعملية الأصلية. يفحص عامل متابعة هذه العملية بالمفتاح أو مرجع التاجر إذا كانت الوثائق تدعم ذلك، ثم يحفظ SH-781 عند تأكيد التطابق. إذا لم يوفر المزود استعلامًا آمنًا ولا منع تكرار، تكون المراجعة البشرية خيارًا معقولًا قبل محاولة كتابة أخرى. هنا يكون التوقف المنضبط أقل كلفة من التخمين.
ضع ميزانية للوقت ولإعادة المحاولة
- حدد مهلة لكل استدعاء ومدة قصوى للعملية كلها؛ لا تجعل صفحة العميل تنتظر إلى ما لا نهاية.
- صنّف الأخطاء: بيانات عنوان ناقصة تحتاج تصحيحًا، ومفتاح غير صالح يحتاج مسؤول الربط، وانقطاع مؤقت قد يسمح بمحاولة لاحقة.
- اجعل التأخير بين المحاولات متدرجًا مع تفاوت عشوائي محدود، وبعدد محاولات واضح، إذا كان تكرار العملية آمنًا.
- عند استنفاد المحاولات، انقل السجل إلى قائمة مراجعة مع الخطوة المطلوبة، بدل إخفائه أو حذفه.
إذا أعاد المزود الترويسة Retry-After ففسّر موعد الانتظار أو عدد الثواني بحسب صيغتها. وفي JavaScript انتبه إلى أن fetch لا يرفض الوعد لمجرد حالة HTTP مثل 404؛ افحص الحالة ومحتوى الرد قبل تصنيف العملية. إيقاف الانتظار محليًا لا يعني إلغاء ما نفذه الخادم البعيد.
الإشعارات اللاحقة جزء من النظام
قد يؤكد المزود النتيجة عبر webhook بدل الاعتماد على زيارة العميل لصفحة العودة. وثائق أحداث Stripe تتناول التحقق من التوقيع والتعامل مع الأحداث المكررة؛ وهذه تفاصيل يجب مراجعتها في وثائق مزودك الفعلي. في متجر الكتب، لا تسمح لحدث قديم بإعادة الشحنة المسلمة إلى حالة التجهيز. صمم قواعد انتقال واضحة وسجلًا لما عولج، مع مقارنة الحساب والمرجع ونوع الحدث.
احفظ الإشعار الموثوق بشكل متين قبل إقرار استلامه إذا كنت ستعالجه لاحقًا. وأضف مصالحة دورية لعمليات انتظار التحقق، لأن وصول الإشعارات وحده ليس خطة استعادة. في لوحة الموظف اعرض المرجع، وآخر محاولة، والعمر الحالي للعملية، وما إذا كانت المتابعة آمنة. لا تعرض مفاتيح الاتصال أو الرد الخام الذي قد يحتوي بيانات شخصية.
ما الذي يجب اختباره قبل التسليم؟
- وصل الطلب إلى المزود لكن ضاع الرد: هل نستعيد النتيجة دون شحنة ثانية؟
- وصل تأكيد واحد مرتين: هل بقيت النتيجة واحدة؟
- تأخر حدث أقدم عن حدث أحدث: هل بقيت الحالة صحيحة؟
- أُعيد تشغيل العامل أثناء التنفيذ: هل يجد العملية السابقة ويواصلها بأمان؟
- فشل التكامل: هل يرى الموظف إجراءً مفهومًا ويمكنه التواصل مع العميل دون كشف أسرار؟
نفّذ هذه الحالات ببيانات اختبار ومزود محاكى أولًا، ثم اختبر حدود البيئة التجريبية المصرح بها. اربطها بخطة الاختبارات الآلية، واحتفظ بسجل أحداث منقح وفق إرشادات OWASP للسجلات. النتيجة المطلوبة ليست غياب الانقطاع تمامًا، بل أن يعرف الفريق ماذا حدث وماذا يفعل بعده.
هل تحتاج كل عملية إلى طابور خلفي؟ لا. قراءة معلومات سريعة قد تكفيها مهلة ورسالة واضحة. أما العملية البطيئة أو المكلفة أو التي تحتاج استعادة بعد إغلاق المتصفح، فتستفيد من سجل دائم وعامل متابعة. اختر البنية وفق أثر الفشل لا وفق شهرة الأداة.
أُعد هذا المقال بمساعدة الذكاء الاصطناعي؛ أُدرجت المراجع التقنية للتحقق من التفاصيل.
