خارطة الفنتك

الجزء 10 · هندسة أنظمة الفنتك

واجهات البرمجة والموثوقية APIsAPIs, idempotency and reliability

في المدفوعات ستنقطع الشبكة في منتصف العملية. ولا يعرف تطبيق العميل هل نجحت، فيحاول مجدداً، وبلا حماية يُخصم منه مرتين.

قراءة 6 دقائق

شارك المقال:

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

لا تخبرك مهلة الشبكة هل نُفذت العملية، بل تخبرك فقط أنك لم تتلق جواباً.

انقطع الاتصال وأنا أدفع. هل انخصم مني أو لا؟

وهذا الموقف الذي عاشه كل مستخدم، وهو أيضاً أصعب مشكلة في هندسة المدفوعات.

فتخيّل تطبيقك: أرسل طلب دفع إلى البنك، ثم انقطعت الشبكة قبل وصول الرد. فماذا حدث؟ لا تعرف. فقد يكون الطلب لم يصل أصلاً. وقد يكون وصل ونُفّذ وضاع الرد في الطريق.

والاحتمالان يبدوان متطابقين تماماً من جهتك. ولا توجد طريقة للتفريق بينهما بالنظر إلى ما لديك.

فماذا تفعل؟ إن أعدت المحاولة، فقد تخصم من العميل مرتين. وإن لم تُعِد، فقد تترك دفعة لم تتم وعميلاً ينتظر.

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

وتُسمّى هذه الخاصية «الجمود» Idempotency، ومعناها أن تكرار الطلب لا يغيّر النتيجة.

فالقاعدة التي تحكم هذا المجال: لا تفترض أن الصمت يعني الفشل. فالصمت يعني أنك لا تعرف، وهذه حالة ثالثة يجب أن يتعامل معها نظامك صراحة.

صمم للنتيجة المجهولة

وقد يرسل تطبيق العميل طلب خصم ١٠٠ ريال، فينفذه الخادم، ثم ينقطع الاتصال قبل رجوع الرد. ويرى التطبيق خطأ فيعيد الطلب. وإذا عامل الخادم الإعادة كعملية جديدة، يخسر العميل ٢٠٠ ريال بسبب عطل واحد.

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

ويُسمى المرجع الفريد المرفق بالطلب «مفتاح عدم التكرار» Idempotency key. فينشئ التطبيق قيمة مثل pay_8f31 ويرسلها مع العملية. ويحفظ الخادم المفتاح والنتيجة. فإذا وصل المفتاح نفسه مرة أخرى، يعيد النتيجة المحفوظة ولا يحرك المال ثانية.

ثبت معنى المفتاح

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

واحفظ حالة قيد التنفيذ أيضاً. فقد تصل الإعادة بينما الطلب الأول ما زال يعمل. وعندها ينتظر الخادم النتيجة أو يرجع حالة معلقة، ولا يبدأ عاملاً ثانياً. ويحتاج الحفظ مدة أطول من نافذة إعادة المحاولات المتوقعة.

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

أعد المحاولة بانضباط

وتعني «إعادة المحاولة» Retry إرسال الطلب نفسه بعد فشل أو مهلة. ولا ينبغي إعادته فوراً بلا نهاية. فذلك يحول عطلاً صغيراً عند المزود إلى سيل يستهلكه ويؤخر تعافيه.

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

وفرق بين خطأ مؤقت ورفض تجاري ونتيجة مجهولة. فرمز 500 قد يسمح بإعادة آمنة، ورمز 400 يحتاج تصحيح المدخلات، وانقطاع بعد إرسال الطلب يحتاج استعلاماً عن الحالة. ولا تخف هذا الفرق داخل رسالة فشل عامة.

لا تثق بوصول خطاف الويب

ويعني «خطاف الويب» Webhook رسالة يرسلها المزود إلى خادمك عند تغير حدث. فقد يبلغك مقدم الدفع أن العملية نجحت أو عُكست. وهو يوفر الاستعلام المستمر، لكنه ليس قناة مضمونة ولا مرتبة.

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

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

وافحص حداثة الوقت لمنع إعادة رسالة صحيحة قديمة. واحتفظ بالنص الأصلي للتحقيق وفق سياسة الخصوصية. ولا تسجل الأسرار أو بيانات البطاقة الكاملة مع الرسالة.

أكد مع المصدر

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

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

ولا يعني الاستعلام المتكرر ضرب الواجهة كل ثانية. فاختر وتيرة تناسب زمن العملية وحدود المزود. ويحتاج الدفع الفوري ثواني، بينما قد تحتاج التسوية المصرفية ساعات.

اعزل الشريك المتعطل

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

ويُسمى مكان الرسائل التي استنفدت المحاولات «طابور الرسائل الفاشلة». ولا يكون مقبرة منسية. فله تنبيه ولوحة ومالك وطريقة لإعادة التشغيل بعد إصلاح السبب. ويجب أن تحتفظ الرسالة بمعرفها وسياقها دون أسرار زائدة.

وإذا تعطل نظام المخاطر، فحدد مسبقاً ما الذي يتوقف وما الذي يستمر. فقد تمنع التحويلات الجديدة وتسمح بعرض الحساب. ولا تحول العطل إلى موافقة شاملة، ولا تسقط التطبيق كله إذا كانت وظيفة آمنة تستطيع البقاء.

أعط العميل حالة صادقة

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

وإذا نجحت العملية بعد مغادرة العميل، أرسل إشعاراً واضحاً. وإذا فشلت نهائياً، حرر الحجز وأظهر السبب القابل للإجراء. ولا تجعل موظف الدعم يطلب من العميل الانتظار بينما لا يملك طريقاً للبحث.

اختبر الفشل المقصود

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

وسجل معرف الطلب ومفتاح عدم التكرار ومعرف المزود ومعرف القيد في سلسلة واحدة. فيستطيع المهندس تتبع العملية عبر الخدمات. ويستطيع المدقق إثبات أن إعادة المحاولة لم تكرر المال.

وتصبح الواجهة موثوقة حين تعامل الشبكة كشيء يفشل عادة. فلا تعتمد على وصول وحيد ولا ترتيب مثالي ولا رد سريع. واعتمد على هوية ثابتة للعملية، ونتيجة قابلة للاستعلام، وتاريخ لا يكرر الأثر.

كلمات جديدة هنا

مفتاح عدم التكرارIdempotency key
مرجع فريد يُرسل مع الطلب بحيث لا يؤدي تكراره إلى تكرار الإجراء.
خطّاف الويبWebhook
رسالة ترسلها خدمة أخرى إلى خادمك عند وقوع حدث، بدل أن تسأل أنت باستمرار.
إعادة المحاولةRetry
إرسال الطلب نفسه مجدداً بعد فشل أو انتهاء مهلة. وهي آمنة فقط إذا كانت العملية غير قابلة للتكرار.

الخلاصة

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

اختبر فهمك

أجب قبل أن تقرأ التفسير. والخطأ هنا أنفع لك من تخمين صحيح.

  1. 1.أرسلت طلب دفع فانقطعت الشبكة قبل وصول الرد. فهل خُصم من العميل؟
  2. 2.تعيد المحاولة بمفتاح عدم التكرار نفسه. فماذا يفعل الخادم؟
  3. 3.يصل مفتاح عدم التكرار نفسه بمبلغ مختلف. فما الرد الصحيح؟
  4. 4.يصل خطاف ويب يقول إن دفعة عُكست. فهل تتصرف بناءً عليه مباشرة؟
  5. 5.النتيجة مجهولة فعلاً. فماذا تعرض للعميل؟

هذا دليل تعليمي مبني على خبرة ميدانية. وهو ليس استشارة قانونية أو تنظيمية أو استثمارية، ولا يُغني عن مشورة مهنية مؤهّلة. وأنظمة التقنية المالية تتغيّر بسرعة وتختلف من دولة إلى أخرى، فراجع المصدر الرسمي قبل أي قرار مهم.

العودة إلى الخارطة

واجهات البرمجة والموثوقية APIs | Roadmap FinTech