من السهل أن تظن أن التحقق من رقم بطاقة الائتمان عملية واحدة. وهو في الواقع خمس عمليات متتابعة، لكل منها سبب مختلف ورسالة خطأ مختلفة. والفرق بين نموذج يعد المحارف ويقبل ما يمر، ونموذج يفهم ترتيب الفحوص، ليس جماليا؛ فهو الفرق بين مستخدم يصحح خطأه في ثانية وبين مستخدم يعيد كتابة رقم صحيح ثلاث مرات ثم يغادر.
تشرح المقاطع التالية ترتيب الفحوص ولماذا لا يكفي الفحص في المتصفح وحده، ثم تنتقل إلى ما يحتاجه من يكتب هذا الكود فعليا.
لماذا نتحقق من الرقم أصلا؟
لا يتحقق النموذج لأن الرقم قد يكون بطاقة محتال. فهذا سؤال لا تستطيع الواجهة الإجابة عنه، ولا يستطيع خادمك أيضا. والقرار الحقيقي يأتي من طلب تفويض يجيب عنه البنك.
التحقق يخدم أغراضا أخرى كلها عملية. فهو يمنع أخطاء الكتابة من أن تصير طلبات فاشلة تستدعي معاملة كاملة عبر المزود. وهو يمنح المستخدم ردا فوريا بدل انتظار دورة شبكة كاملة ليعلم أنه نسي رقما. وهو يحمي المسار الأبطأ في نظامك من حمولات لا معنى لها، لأن كل ما يمر إلى طلب تفويض يحسب على زمن استجابة الخدمة ومعدل استخدام المزود.
وباختصار، الفحص عند البوابة عمل دفاعي بالمعنى الجيد: تسقط المدخلات الخطأ عند أرخص نقطة ممكنة.
ما ترتيب الفحوص الصحيح؟
الترتيب مهم لأن كل فحص أفصح من الذي يليه. والصعود بالترتيب الصحيح يعني أن المستخدم يخبر بالمشكلة الأوضح أولا، وأن الكود لا يستدعي منطقا معقدا على مدخل غير مؤهل أصلا.
- الوجود. الحقل غير فارغ. هذا أرخص فحص وأكثره شيوعا في الحياة اليومية، ويجب أن يأتي أولا.
- مجموعة المحارف. كل ما بقي بعد إزالة محارف الفصل التي تعتزم تحملها هو أرقام. المدخل الذي يحتوي حرفا ممزوجا إنما هو خطأ لصق، وينبغي أن يقال ذلك صراحة بدل أن يحذف الحرف بصمت.
- الطول. الطول المنظف داخل النطاق المقبول، لا مطابق لقيمة واحدة. النطاق يشمل الأطوال المختلفة التي تنتجها الشبكات.
- البادئة. البادئة تنتمي إلى شبكة تعرفها. هذا هو الفحص الذي يحول مجموعة الأرقام إلى توقع محدد، وهو أيضا الفحص الذي يجب أن يعرف أكثر من رقم واحد كما تفصل مقالة تنسيق الرقم.
- مجموع التحقق. الحساب على الرقم بالكامل حسب خوارزمية Luhn. وهو تأكيد أخير لا بوابة أولى، فوضعه في المقدمة يجعل رسالة الخطأ مبهمة للمستخدم الذي أخطأ في رقم واحد.
وأنت تقرأ هذه القائمة، لاحظ ما لا تجده فيها: أي فحص يقول إن البطاقة صالحة. فالخمسة كلها تتحقق من الشكل، ولا أحد منها يلمس الحساب.
هل يكفي التحقق في المتصفح؟
لا. والسبب ليس أن التحقق في المتصفح عديم الفائدة، بل أن وظيفته مختلفة عن وظيفة الخادم.
الفحص في المتصفح يخص التجربة. هو الذي يجعل رسالة الخطأ تظهر بجانب الحقل قبل أن يضغط المستخدم زر الإرسال، وهو الذي يضبط طول حقل حسب الشبكة المكتشفة، وهو الذي يعرض المجموعات أثناء الكتابة. هذه كلها أعمال الواجهة، وإنجازها هناك أرخص وأسرع.
أما الفحص عند الخادم فيخص السلامة. فالمتصفح بيئة يملكها المستخدم، ويمكن تعطيل البرمجية فيه أو استدعاء النقطة النهائية مباشرة بأداة سطر أوامر. إذا كان فحصك الوحيد في الواجهة، فأنت تفحص المدخلات المرسلة من طرف لا تتحكم فيه.
والنهج السليم نسختان من المنطق نفسه: واحدة سريعة في الواجهة للتفاعل، وأخرى موثوقة عند الخادم للقرار. وأبق الاثنين متطابقين في القواعد، لأن الاختلاف بينهما ينتج حالة غريبة يمر فيها ما هو مقبول بصريا ويفشل عند الحفظ، أو العكس.
كيف تكتب رسائل الخطأ؟
رسالة الخطأ جزء من التجربة لا تفصيل بعدها. والمبادئ التي تصمد في كل الفحوص الخمسة أربعة.
الأول أن تقول ما هو الخطأ لا أن تنفي الصلاحية. فقول الرقم غير صحيح يترك المستخدم يعيد كتابة القيمة نفسها؛ أما القول إن الرقم أقصر من المتوقع فيوجه التصحيح.
الثاني أن تفصل بين أنواع الفشل. فالقصر عن الحد، والحرف غير المدعوم، والبادئة المجهولة، وفشل مجموع التحقق مشكلات مختلفة، والرسالة الواحدة لها جميعا تخدم الكود لا المستخدم.
الثالث ألا تظهر الصيغة المتوقعة بتفصيل يشي بالبنية الداخلية. ومشاركة نطاق البادئات المعروفة أو قواعد المجموع ليست معلومات سرية بمعنى الكارثة، لكنها لا تفيد المستخدم الحقيقي بأي شيء، فهي إشارة إلى نموذج آلي لا إلى إنسان يكتب رقما من بطاقته.
الرابع أن تظهر الرسالة عند الحقل نفسه وألا تفقد ما كتبه المستخدم. فمسح الحقل عند الفشل هو أسرع طريق إلى نموذج مهجور.
التحقق ليس الموافقة على الدفع
هذه العبارة تستحق أن تكتب في توثيق المشروع لا في مقاله فقط. فنجاح الفحوص الخمسة يعني أن السلسلة تبدو كرقم بطاقة معقول، ولا يعني أن أي بنك سيوافق.
وما يقرر الموافقة أمور كثيرة: حالة الحساب، والرصيد المتاح، وسياسات الجهة المصدرة، ونتائج أنظمة مكافحة الاحتيال، ووجود ما يمنع المعاملة على البطاقة. ولا يعرف نموذجك شيئا من ذلك.
وخطأ العرض الشائع هنا هو إظهار علامة نجاح أو إشارة إلى قبول البطاقة بعد اجتياز الفحص المحلي. والأسلم أن تبقى اللغة محايدة حتى يعود قرار المزود: أن الرقم مقبول في هذا الحقل، لا أن البطاقة مقبولة.
للمطورين: تفاصيل تنفيذية تنسى
في الممارسة، الأعطال الحقيقية تأتي من قائمة قصيرة ومتوقعة. تجميع ترتيب الفحوص في دالة واحدة مشتركة يمنع انحراف المسارات؛ فوجود ثلاث نسخ من قواعد التحقق في ثلاثة أماكن يعني أن واحدة منها ستحدث وحدها.
واحتفظ بالنص الأصلي بجانب الصيغة المنظفة. المستخدم الذي يلصق قيمة بفواصل يستحق أن يرى إدخاله كما كتبه إن فشل، لا نسخة معدلة لا يعرف من أين جاءت.
واكتب اختبارات للفشل لا للنجاح فقط. فمسار النجاح يختبر ضمنيا في كل تشغيل يدوي، أما حالات القصر والحرف الغريب والبادئة المجهولة وفشل المجموع فتحتاج اختبارا صريحا لكل منها.
وراجع من يتصل بدالة التحقق أصلا. فالوظيفة التي تتحقق ثم تتجاهل نتيجتها أسوأ من غيابها، لأنها توهم بأن هناك حماية. وتلمس أبسط حالات هذا الإهمال في مسار الإرسال، وتظهر الحالات الأصعب في طوابير إعادة المحاولة والمهام المجدولة والاستيراد من ملف.
وأخيرا استخدم بيانات منشأة في اختبارات الوحدة بدل قيم محفوظة عن ظهر قلب. فالخصائص التي تحتاجها في الاختبار هي الصحة البنيوية وتنوع البادئات وتغطية الأطوال، وكلها موصوفة في دليل أرقام الاختبار؛ ومجموعة واحدة من أداة إنشاء رقم البطاقة تكفيك لتمرين الفحوص الخمسة جميعا.
الخطوات التالية
اكتب الفحوص الخمسة بالترتيب في دالة واحدة، وأعد إليها كل مسار في النظام. ثم اختبر ما يحدث عندما يفشل كل فحص على حدة: هل الرسالة صحيحة، وهل الحقل محتفظ بالمدخل، وهل الطلب يتوقف فعلا. وأخيرا وثق أن اجتياز الفحوص ليس موافقة على الدفع، حتى لا يبني أحد ميزة على افتراض خاطئ.