أمان الدفع في أودو: رابط نجاح مزوّر لا يجعل الطلب مدفوعًا
كيف يستطيع رابط رجوع مزوّر أو ويب هوك معاد إرساله أن يجعل طلب أودو مدفوعًا، وكيف يمنع ذلك قراءة حالة الدفعة من واجهة تابي وتمارا نفسها بنداء موثّق.
في أي عملية دفع تعتمد على إعادة التوجيه، النقطة الأضعف ليست البوابة ولا الشبكة. النقطة الأضعف هي لحظة رجوع العميل. متجرك يرسل العميل إلى تابي أو تمارا، يصير شيء ما عند المزوّد، ثم يأتي متصفح لا تتحكم فيه ويطلب رابطًا على نطاقك أنت. ومهما كان هذا الطلب يقول، الوحدة عندك لازم تقرر: هل الطلب مدفوع أو لا؟
إذا كانت الوحدة تصدّق ما يقوله الرابط، فأي شخص يعرف يقرأ رابطًا يقدر يشتري من متجرك مجانًا. هذا المقال يشرح كيف يبدو هذا الهجوم فعليًا على متجر أودو، ثم كيف تتعامل معه Tabby & Tamara for Odoo. مكتوب للمطوّر الذي سيوقّع على قرار الشراء، أو الذي يريد مراجعة الوحدة المركّبة عنده اليوم.
الطلب الوحيد الذي لا تتحكم فيه
إطار الدفع في أودو يستقبل من مزوّد إعادة التوجيه ثلاثة أحداث، وهي ليست متساوية في الثقة أبدًا.
- رابط الرجوع. متصفح العميل يرجع إلى مسار على نطاقك، غالبًا طلب GET ومعه باراميترات. هذا الطلب تحت سيطرة العميل بالكامل: يقدر يعدّله، ويحفظه، ويعيد إرساله بعد ساعات، ويرسله لغيره.
- الويب هوك. المزوّد يرسل إشعارًا إلى نقطة نهاية عامة. وكونها عامة يعني أن أي شخص على الإنترنت يقدر يرسل لها هو أيضًا.
- النداء الصادر من خادمك. خادمك يسأل المزوّد مباشرة، عبر اتصال خاص به وبمفتاحك السري. العميل ليس طرفًا في هذه المحادثة إطلاقًا.
الحدث الثالث وحده هو مصدر الحقيقة. الأول والثاني مجرد تنبيه بأن شيئًا قد تغيّر. الربط الآمن يتعامل معهما بهذا المنطق، والربط غير الآمن يتعامل مع رابط الرجوع كأنه كشف حساب بنكي.
ولا تنسَ أن رابط الرجوع يُفتح في حالات بريئة تمامًا. عميل تراجع عن الخطة في صفحة تابي يقدر يضغط زر الرجوع في المتصفح، أو يفتح الرابط من سجل التصفح بعد يومين. أي منطق يفترض أن «وصل إلى رابط الرجوع» تعني «دفع» سينكسر مع عميل صادق قبل أن يصل إليه عميل غير صادق.
كيف يبدو رابط رجوع مزوّر
افترض أن الوحدة تسجّل مسارًا باسم /payment/tabby/return. الرابط الحقيقي قد يكون بهذا الشكل:
https://shop.example.com/payment/tabby/return?payment_id=9d7f1a2c&status=authorized
والمعالجة الساذجة تكون غالبًا بهذا الشكل:
@http.route('/payment/tabby/return', type='http', auth='public', csrf=False)
def tabby_return(self, **data):
tx = request.env['payment.transaction'].sudo().search(
[('reference', '=', data.get('order'))], limit=1)
if data.get('status') == 'success':
tx._set_done() # يثق بما جاء في الرابط
return request.redirect('/payment/status')
لاحظ أن هذا الكود لا يكلّم تابي إطلاقًا. حالة عملية مالية حقيقية تتحدد بنص كتبه العميل. ولهذا الهجوم ليس ذكيًا، الهجوم مجرد كتابة:
https://shop.example.com/payment/tabby/return?order=SO0042&status=success&amount=999
اطلب طلبًا عاديًا، خذ رقم المرجع من شاشة التأكيد، اترك صفحة الدفع، ثم افتح هذا الرابط. المعاملة تنتقل إلى حالة مدفوع، وأمر البيع يتأكد، والفاتورة تُرحّل، ورسالة التأكيد تُرسل. وفي متجر فيه تسليم تلقائي، المستودع يستلم أمر تجهيز لبضاعة لم يدفع ثمنها أحد.
والنسخ الأسوأ من هذا السيناريو معروفة: تغيير قيمة amount لمعرفة هل الوحدة تسجّل الرقم من الرابط بدل الرقم من البوابة، أو تجربة المراجع بالتسلسل SO0043 وSO0044 لإقفال طلبات آخرين، أو تنفيذ دفعة صغيرة حقيقية ثم إعادة إرسال إشعار نجاحها على معاملة أكبر.
توقيع الرابط يساعد لكنه ليس الحل
بعض البوابات توقّع باراميترات إعادة التوجيه، والتحقق من هذا التوقيع أفضل من عدمه بكثير، وهو يوقف الرابط المكتوب باليد أعلاه.
لكنه لا يخبرك بالحالة الحالية. التوقيع يثبت أن المزوّد أصدر هذه البيانات في لحظة ما، ولا يثبت أن الدفعة مصرّح بها الآن، ولا أنها لم تُلغَ بعدها بدقيقتين، ولا أنها حُصّلت فعلًا، ولا أن هذه الرسالة لم تُستهلك سابقًا على معاملة أخرى. التوقيع يجيب على سؤال «من قال هذا»، والسؤال الذي تحتاجه هو «ما الصحيح الآن».
ولهذا النمط الوحيد المتين هو أن تتوقف عن تحليل ما يُقال لك، وتذهب تسأل بنفسك.
كيف تتحقق Tabby & Tamara for Odoo من الدفعة
رابط الرجوع لا يعطي إلا المرجع
القيمة الوحيدة المأخوذة من المتصفح العائد هي المعرّف اللازم للعثور على المعاملة. لا حالة، ولا مبلغ، ولا عملة، ولا أي قرار للمزوّد يُقرأ من الباراميترات.
وهذه النقطة أهم مما تبدو. معناها أنه لا يوجد في ذلك الرابط شيء يستطيع المهاجم ضبطه ليستفيد منه. إضافة &status=success&amount=999 لا تغيّر شيئًا لأنه لا يوجد أصلًا مسار في الكود يقرأ هذه المفاتيح. الباراميترات المزوّرة ببساطة ليست جزءًا من القرار.
الحالة تُقرأ من واجهة المزوّد نفسه
بعد تحديد المعاملة، ترسل الوحدة نداءً من الخادم إلى الخادم وتقرأ كائن الدفعة من المصدر:
GET /api/v2/payments/{id}
Authorization: Bearer <مفتاحك السري>
هذا نداء تابي. ومع تمارا تتم القراءة نفسها عبر GET /orders/{id}، موثّقة برمز الواجهة البرمجية الخاص بك.
الرد هو السجل المعتمد: الحالة الحالية، والمبلغ، والعملة كما هي عند المزوّد. وأودو يحرّك المعاملة بناءً على هذا الرد ولا شيء غيره. الدفعة المصرّح بها تُحصّل ثم تُغلق كمدفوعة، والدفعة المغلقة أو المرفوضة أو المنتهية الصلاحية تُلغى أو تُسجّل كخطأ، والدفعة التي ما زالت جارية تبقى معلّقة حتى يحسمها إشعار أو استعلام لاحق.
الخلاصة التي تستحق الحفظ: أفضل نتيجة ممكنة لرابط رجوع مزوّر هي أنه يشغّل استعلامًا يرجع بالحقيقة. لا توجد بيانات يستطيع المهاجم تلفيقها تجعل واجهة المزوّد تقول «مصرّح بها» والمزوّد لم يصرّح بشيء.
الويب هوك يمر من نفس الباب
الويب هوك في النهاية مجرد طلب HTTP قادم من الإنترنت. نقطة النهاية لازم تكون متاحة للعموم حتى يستخدمها المزوّد، وهذا يعني أنها متاحة لغيره أيضًا. وكتابة جسم JSON يدّعي نجاح دفعة ليست أصعب من تعديل رابط.
لذلك يُعامَل الويب هوك كمُشغّل لا كدليل. يُستخدم محتواه لمعرفة أي معاملة يتحدث عنها، ثم يتولى نفس النداء الموثّق GET /api/v2/payments/{id} تحديد ما يحدث فعلًا. الإشعار الملفّق أو المعاد إرساله يمر على نفس خطوة التحقق التي يمر عليها الإشعار الحقيقي، والإشعار الحقيقي لا يكسب شيئًا لكونه حقيقيًا.
المعاملة المنتهية لا يُعاد معالجتها
القطعة الأخيرة هي عدم تكرار المعالجة. المعاملة التي وصلت إلى حالة مدفوعة أو ملغاة أو خطأ لا تُعالج مرة ثانية، والإشعارات اللاحقة عليها تُستقبل وتُتجاهل.
وهذه ليست تفصيلة نظرية، فهي تغطي حالات يومية جدًا:
- المزوّدون يعيدون إرسال الويب هوك عند فشل التسليم، فوصول نسخة مكررة سلوك طبيعي لا استثنائي.
- رجوع العميل والويب هوك يصلان كثيرًا في نفس الثانية ويشيران لنفس السجل. بدون حارس الحالة النهائية قد تُسجَّل الدفعة مرتين على فاتورة واحدة.
- إشعار تحصيل قديم يُعاد إرساله بعد أن تكون قد استرجعت المبلغ للعميل، فيقلب معاملة مسترجعة إلى مدفوعة.
- إشعار إلغاء يصل متأخرًا، فيلغي دفعة سبق تحصيلها وتسويتها محاسبيًا.
وباجتماع هذا مع القراءة من الواجهة، يُغلق باب هجمات إعادة الإرسال كاملًا. أي إشعار مسجّل يمكن إرساله ألف مرة، وفي كل مرة إما يصطدم بمعاملة منتهية فلا يفعل شيئًا، أو يشغّل استعلامًا جديدًا يرجع بالحالة الحقيقية.
نفس السؤال عند الكاشير
في نقاط البيع السؤال نفسه لكن بشكل مختلف: ليس رابطًا مزوّرًا بل شاشة جوال. عميل يرفع جواله وفيه صفحة نجاح، والكاشير في طابور مزدحم ولا يملك طريقة يفرّق فيها بين موافقة الآن ولقطة شاشة من الأسبوع الماضي.
الحل بنفس المنطق. الكاشير يختار المزوّد، تفتح نافذة برمز QR، العميل يمسح ويوافق من جواله، والخادم يتابع البوابة ويحصّل عند التصريح. وزر الترحيل يبقى مقفلًا حتى ينجح التحصيل فعليًا، بدون تجاوز يدوي. الشاشة التي يثق بها الكاشير تُحرّكها استجابة البوابة، لا ما يعرضه العميل. والمسار كاملًا عند الكاشير، وما يجب تدريبه عليه، في تابي وتمارا في نقاط البيع في أودو.
مين في فريقك يشوف المفاتيح، ومين يقدر يرجّع فلوس
التحقق من جهة الخادم يحسم وش يقدر يسوي شخص غريب برابط. يبقى النص الثاني: وش يقدر يسوي موظفينك أنت. والموضوع كله يرجع لثلاثة أسئلة: مين يقرأ المفاتيح، ومين يقرأ سجل الـ API، ومين يقدر يرسل استرداد.
المفاتيح
من أودو 15 وطالع، المفتاح السري لتابي (Secret Key) ورمز تمارا (API Token) ورمز إشعارات تمارا (Notification Token) مقفولة على مستوى الحقل نفسه، وما يقراها إلا مدير الإعدادات، يعني من عنده صلاحية Settings في قسم Administration. وتطبيق الدفع في أودو ما يفتح سجلات مزودي الدفع إلا لهذي المجموعة، فالبائع والمحاسب ما يوصلون لنموذج المزوّد من الأساس. ولو تطبيق ثاني من أودو أعطى دورًا معيّنًا صلاحية قراءة النموذج، تبقى حقول المفاتيح مخفية عنه. وعلى الشاشة تطلع المفاتيح نجومًا، وهذا يمنع اللي يطالع من ورا كتفك، لكنه ما يمنع مدير الإعدادات إذا بغى القيمة.
ومفاتيح نقاط البيع تنكتب في الإعدادات وتنحفظ كمعاملات نظام (System Parameters)، وهذي بعد ما يقراها إلا مدير الإعدادات.
يعني عمليًا: قائمة مدراء الإعدادات عندك هي نفسها قائمة اللي ماسكين مفاتيحك، فخلّها قصيرة. والاستثناء أودو 14. فيه تمشي الوحدة على عُرف ذاك الإصدار في مفاتيح المزودين، يخفيها عن مستخدمي البوابة وزوار الموقع لكن مو عن الموظفين، فعلى 14 اعتبر إن أي مستخدم داخلي يقدر يقراها.
سجل الـ API
من أودو 15، سجل الـ API يحفظ كل نداء يطلع من الموقع ومن بوابة العميل إلى تابي وتمارا. نداءات الكاشير ما تدخله. وقيمته إنه يحفظ وش انرسل ووش رجع بالحرف.
مفاتيحك مو فيه. ترويسة التفويض اللي تحملها ما تنحفظ أبدًا، ومن كل عنوان ينحفظ المسار بس. لكن عملاءك فيه. كل طلب دفع يحمل اسم العميل وإيميله وجواله وعنوان الشحن مع محتوى السلة، وكل رد ينحفظ مثل ما أرسله المزوّد، والاثنين يوقفون عند 6,000 حرف.
قواعد الوصول في الوحدة تسمح لمدير الإعدادات يقرأ هذي السطور ويحذفها، ولمدير المحاسبة يقراها بس. وما في شي يمسح السطور القديمة من نفسه، فالسجل يكبر طول ما المتجر شغّال. ولو سياسة الخصوصية عندك تقول إنك تحتفظ ببيانات العملاء لمدة محددة، فهذا السجل داخل في هالالتزام بعد، ومدير الإعدادات يقدر يحدد السطور القديمة من القائمة ويحذفها.
الاسترداد
فيه قفلين منفصلين، واللي ينطبق منهم يعتمد على مكان البيعة.
بيعة الموقع أو البوابة تسترجعها من زر Refund الأصلي في أودو على سجل الدفعة. أودو يُظهر هذا الزر لمن عنده صلاحية الفوترة، في كل الإصدارات من 15 إلى 19، وهو اللي يرسل النداء للمزوّد بصلاحيات النظام، فاللي يسوي الاسترداد ما يحتاج يشوف أي مفتاح. وصلاحية Tabby Refund اللي تضيفها الوحدة ما لها دخل هنا. فإذا تبي تحدد مين يقدر يرجّع بيعة أونلاين، حدد مين عنده صلاحية الفوترة.
بيعة الفرع تسترجعها من زر Refund on Tabby على سجل الدفعة أو على الفاتورة، وهذا الزر من الوحدة نفسها. محمي بصلاحية Tabby Refund، وما أحد يملكها لين تمنحها أنت، والفحص يصير داخل الدالة نفسها مو بس بإخفاء الزر. أما استرجاع الكاشير العادي على دفعة تابي فيوصل لتابي بدون هذي الصلاحية، لأن الكاشير أصلًا مسموح له يرجّع بيعة عند الكاونتر.
وكل مسار بشاشاته خطوة بخطوة تلقاه في دليل استرداد تابي وتمارا في أودو.
رمز إشعارات تمارا
مزوّد تمارا فيه حقل اسمه Notification Token، ولا شي من اللي في هذي الصفحة يعتمد عليه. الويب هوك اللي يحمل الرمز الصحيح، أو رمز غلط، أو بدون رمز أصلًا، كلهم يوصلون لنفس القراءة من واجهة تمارا. فتعبئة الحقل أو تركه فاضي ما يغيّر شي في قدرة إشعار مزوّر إنه يخلّي طلب مدفوع.
مراجعة في عشرين دقيقة تقدر تسويها على أي وحدة
لا داعي لتصديق كلام أي بائع، ولا كلامنا نحن. وإن لم تكن جهّزت بيئة اختبار بعد، ففي شرح تجربة تابي وتمارا في بيئة الاختبار قبل الإطلاق ما الذي يحدد الاختبار أو الإنتاج لكل مزوّد، وما الذي يثبته طلب التجربة وما لا يثبته. بعدها، في وضع الاختبار وبطلب تجريبي، نفّذ التالي:
- أكمل دفعة اختبارية حقيقية، والتقط رابط الرجوع كاملًا من تبويب الشبكة في المتصفح.
- ابدأ طلبًا ثانيًا، ألغِه من صفحة المزوّد، ثم الصق رابط الرجوع الأول بعد تغيير المرجع إلى مرجع الطلب الثاني. يجب ألا يصبح الطلب مدفوعًا.
- أضف
&status=success&amount=1إلى رابط رجوع حقيقي وأعد التحميل. يجب ألا يتغير شيء، وألا يتغير المبلغ المسجّل. - أعد إرسال إشعار ناجح مرة ثانية. النتيجة الصحيحة دفعة واحدة وفاتورة واحدة، لا اثنتان.
- أرسل بنفسك طلب POST بجسم JSON مكتوب يدويًا إلى نقطة الويب هوك، بمرجع صحيح وحالة نجاح. يجب ألا يتغير شيء.
- افتح سجل الـ API. لكل حدث من الأحداث السابقة يجب أن ترى نداءً صادرًا إلى المزوّد. وإذا انقلب طلب إلى مدفوع بدون أي نداء صادر مسجّل، فالوحدة صدّقت المدخلات. وفي دليل حل مشكلة اختفاء تابي من صفحة الدفع فقرة عن قراءة هذا السجل حسب رمز الاستجابة.
- اقرأ كود المتحكم وابحث عن باراميترات الطلب وهي تصل إلى
_set_doneأو_set_authorizedأو ما يقابلها في إصدارك. دوال تغيير الحالة يجب أن تتغذى من رد الواجهة بعد تحليله، لا منkwargs.
النقطة السابعة مسألة ترخيص بقدر ما هي مسألة تقنية. Tabby & Tamara for Odoo تصدر برخصة LGPL-3 وبمصدر مقروء، فهذه المراجعة شيء تقدر تنفّذه فعليًا. أما الوحدة المغلقة، أو المرخّصة لنطاق واحد مع منع مشاركة المصدر، فلا يمكن قبولها إلا بالثقة المجردة.
ماذا تقول صفحات المنافسين عن هذا الموضوع
هذه ملاحظة منصفة لا اتهام. في صفحات وحدات تابي وتمارا التي فُحصت في متجر تطبيقات أودو، لا توجد صفحة واحدة توضّح كيف تتحقق من حالة الدفعة أبعد من ذكر «تسجيل ويب هوك». وأغلبها مزوّد واحد لكل وحدة بسعر يقارب 270 دولارًا، فمن يريد المزوّدين يشتري مرتين. وواحدة تغطي الاثنين لكن للمتجر الإلكتروني فقط، وأخرى تغطي الاثنين لكن لنقاط البيع فقط وتشترط نسخة Enterprise، وأرخص خيار مرخّص لنطاق واحد ويمنع مشاركة المصدر. والمقارنة الكاملة بين هذه الإضافات، بأسعارها وما تغطيه كل واحدة، في الفرق بين إضافات تابي وتمارا في متجر أودو.
وهذا كلام عن الأوصاف المنشورة، لا عن الكود خلفها. قد تكون تلك الوحدات تتحقق من جهة الخادم ولم تذكر ذلك. لكنك مطالب بالشراء بناءً على الوصف، فاسأل البائع ثلاثة أسئلة قبل الدفع:
- هل يؤثر أي جزء من رابط الرجوع على حالة المعاملة؟
- هل تُقرأ الحالة النهائية من واجهة المزوّد بنداء موثّق منفصل؟
- ماذا يحدث حين يصل إشعار جديد لمعاملة وصلت حالة نهائية؟
أي بائع فكّر في الموضوع سيجيب في فقرة واحدة.
ما الذي لا يحميك منه التحقق من جهة الخادم
الوضوح في حدود المسؤولية جزء من المصداقية.
هو لا يفتح لك حساب تاجر. تحتاج حسابك الخاص لدى تابي وحسابك لدى تمارا بمستنداتهما وإجراءات الموافقة عندهما. الوحدة توصّل مفاتيحك فقط، وهي ربط مستقل من كرنلتكس بدون أي ارتباط أو اعتماد من الشركتين. أما أين تُدخل هذه المفاتيح في أودو، وكيف تتأكد منها قبل أن يظهر الزر لأي عميل، فتجده في شرح إعداد تابي في أودو من المفاتيح حتى أول طلب حقيقي.
وهو لا يحمل عنك مخاطر الائتمان. التزام العميل بسداد أقساطه شأن بينه وبين المزوّد حسب اتفاقيتك، وعدد الدفعات ونسب العمولة تحددها تلك الشركات لا أي وحدة في أودو.
وهو لا يغني عن انضباطك أنت. احفظ المفاتيح السرية خارج مستودع الكود، وشغّل مسارات الرجوع والويب هوك على HTTPS فقط، وخلّ صلاحيات مدير الإعدادات والفوترة وTabby Refund عند القلة اللي تحتاجها فعلًا، مثل ما هو مشروح فوق. وسجل الـ API ما يحفظ مفاتيحك، لكنه يحفظ بيانات عملائك، فتعامل معه على هالأساس.
الخلاصة
أي ربط للدفع الآجل هو في جوهره نظام يسلّم بضاعة بناءً على رسالة. والسؤال الوحيد المهم: أي رسالة يصدّقها؟ إذا صدّق متصفح العميل فأنت بنيت متجرًا مجانيًا. وإذا صدّق ردًا موثّقًا من المزوّد، ورفض إعادة معالجة ما انتهى، تحوّل رابط الرجوع المزوّر إلى مجرد صفحة تُفتح بلا أثر.
وحدة تابي وتمارا لأودو تُشترى مرة واحدة بـ 200 دولار، وتغطي المزوّدين معًا في المتجر الإلكتروني وفواتير البوابة وعروض الأسعار ونقاط البيع، على أودو من 14.0 إلى 19.0، على النسخة المجتمعية والمؤسسية، وبرخصة LGPL-3 حتى يقرأ مطوّرك كل سطر في مسار التحقق قبل الإطلاق.
أسئلة متكررة
هل يمكن لرابط رجوع مزوّر أن يجعل طلب أودو مدفوعًا؟
لا، ليس مع ربط يتحقق من جهة الخادم. في Tabby & Tamara for Odoo لا يؤخذ من رابط الرجوع إلا المرجع، أما الحالة فتُقرأ بنداء موثّق إلى واجهة المزوّد عبر GET /api/v2/payments/{id}. إضافة باراميترات مثل status=success أو amount لا تؤثر على شيء لأن الكود لا يقرأها أصلًا. لكن الوحدة التي تصدّق الرابط تستطيع فعلًا تحويل الطلب إلى مدفوع، ولهذا يستحق السؤال أن يُطرح قبل الشراء.
كيف يتم التحقق من الويب هوك، وهل يكفي التوقيع؟
الويب هوك يُعامل كمُشغّل لا كدليل. يُستخدم لتحديد المعاملة المقصودة فقط، ثم تُقرأ الحالة الحقيقية من واجهة المزوّد بنفس النداء الموثّق. التوقيع مفيد ويمنع الرسائل المكتوبة يدويًا، لكنه يثبت من أرسل الرسالة ولا يثبت الحالة الحالية: رسالة موقّعة قديمة قد تكون لدفعة أُلغيت أو استُرجعت بعدها. القراءة من المصدر هي ما يحسم.
ماذا يحدث لو وصل نفس الإشعار مرتين؟
لا شيء في المرة الثانية. المعاملة التي وصلت حالة نهائية، مدفوعة أو ملغاة أو خطأ، لا يُعاد معالجتها، والإشعار اللاحق يُستقبل ويُتجاهل. هذا يغطي إعادة المحاولة الطبيعية من المزوّد، ووصول رجوع العميل والويب هوك في نفس الثانية، وإعادة إرسال إشعار قديم بعد الاسترداد. النتيجة دفعة واحدة على الفاتورة، لا دفعتان.
كيف أتأكد بنفسي أن الوحدة تتحقق فعلًا من جهة الخادم؟
افتح سجل الـ API بعد كل حدث دفع. يجب أن ترى نداءً صادرًا إلى المزوّد مقابل كل رجوع أو ويب هوك. إذا انقلب طلب إلى مدفوع بدون أي نداء صادر، فالوحدة صدّقت المدخلات. وبما أن الوحدة برخصة LGPL-3 ومصدرها مقروء، تقدر أيضًا تفتح كود المتحكم وتتأكد أن دوال مثل _set_done تتغذى من رد الواجهة بعد تحليله لا من باراميترات الطلب.
وفي نقاط البيع، ما الذي يمنع الكاشير من إقفال بيع غير مدفوع؟
زر الترحيل يبقى مقفلًا حتى ينجح التحصيل فعليًا عند المزوّد، بدون تجاوز يدوي. الكاشير يختار المزوّد، وتفتح نافذة برمز QR، والعميل يوافق من جواله، والخادم يتابع البوابة ويحصّل عند التصريح. لقطة شاشة لموافقة قديمة لا تفتح الزر، لأن الشاشة تُحرّكها استجابة البوابة لا جوال العميل.
مين في فريقي يقدر يشوف المفتاح السري لتابي؟
من أودو 15 وطالع، مدير الإعدادات بس. المفتاح السري لتابي ورمزا تمارا مقفولة على هذي الصلاحية على مستوى الحقل، وأودو ما يفتح سجلات مزودي الدفع إلا لها، ومفاتيح نقاط البيع محفوظة في معاملات نظام ما يقراها غيرها. فالموظف اللي يستلم دفعات تابي أو يرجّعها ما يحتاج يشوف أي مفتاح. والاستثناء أودو 14، وفيه أي مستخدم داخلي يقدر يقراها.