تخطَّ إلى المحتوى
أسامة جنينة
كل الأعمال
أنظمة الويبالذكاء الاصطناعي والأتمتةالبنية التحتية والتكاملاتتم تسليمه

منصة تجارة تعمل داخل واتساب

متجر متعدد الفروع، واجهته بالكامل محادثة واتساب

الدور
Full-stack — الخدمتان واللوحات ومحرّك الـ flow والنشر
الفترة
2025 — حتى الآن
التقنيات
Laravel 13 · Vue 3 + Inertia · Laravel Reverb (WebSockets) · Meta WhatsApp Cloud API · Fastify · Redis · MySQL · Thawani · Pest

أرقام أساسية

ملفات PHP في app/
176
موديلات Eloquent
23
Migrations
44
ملفات اختبار Pest
53
مسارات الدفع ومحرّك الـ flow هي الأكثر تغطية
مكوّنات Vue
74
ملفات بوابة Node
14
صغيرة بالقصد: ترجمة بروتوكول فقط، بدون أي منطق أعمال

المشكلة

كان عمل ملاحم وبقالة متعدد الفروع يستقبل كل طلب يدوياً على واتساب. الموظفون يكتبون الأسعار من الذاكرة، والطلبات تسكن في سجل المحادثة، ولا أحد يستطيع الإجابة على «ماذا باع الفرع الثالث أمس» دون قراءة المحادثات.

الحل البديهي — بناء تطبيق أو متجر ويب — كان الحل الخاطئ. عملاؤهم كانوا يطلبون بنجاح فعلاً؛ المشكلة أن الطلبات لم تكن تُسجَّل. ومطالبة هؤلاء العملاء بتثبيت أي شيء كانت ستبدّل قناةً ناجحة بمسار تحويل فيه تسرّب عند كل خطوة.

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

القيود الصارمة

  • العميل لا يثبّت شيئاً ولا يزور أي موقع. واتساب هنا ليس قناة إشعارات — بل هو سطح المنتج بالكامل.
  • نافذة خدمة العميل ٢٤ ساعة عند Meta قاعدة منصّة صارمة: خارجها لا يُسمح إلا بقوالب معتمدة مسبقاً. وخرقها يعرّض رقم العمل للخطر.
  • كل فرع له كتالوجه ومخزونه وساعات عمله، لكن الإدارة تحتاج رؤية موحّدة واحدة.
  • المحادثات ذات حالة وطويلة العمر. يمكن للعميل أن يترك الطلب في منتصفه ويعود بعد ساعات متوقعاً المتابعة.

المعمارية

خدمتان، غير متكافئتين بالقصد. بوابة Node/Fastify تقف على الحدّ ولا تفعل شيئاً إلا التحدث مع Meta: تتحقق من توقيع الـ webhook، وتفك تشفير حِزم WhatsApp Flow، وتوحّد شكل الرسالة، وتمرّرها للداخل. لا تحمل قاعدة بيانات ولا قواعد أعمال — ١٤ ملفاً فقط. وتطبيق Laravel يحمل كل ما هو فعلاً «العمل».

وُجد هذا الفصل لأن تغيّرات بروتوكول Meta ومنطق الأعمال تتغيّر لأسباب غير مترابطة إطلاقاً. عندما تُبدّل Meta مظروف webhook أو تُدوّر متطلبات تشفير Flow، تتحرك البوابة وحدها. وعندما تتغيّر قواعد التسعير أو سلوك الفروع، لا تُمَس البوابة. كلا اتجاهَي هذا الحدّ موثَّق بتواقيع HMAC، فلا تتصرف أي خدمة على طلب لم توقّعه الأخرى.

داخل Laravel، المحادثة آلة حالة. محرّك flow يتقدّم بالعميل عبر خطوات منفصلة، كل واحدة صنف مستقل، مع تخزين الموضع الحالي — وهذا ما يجعل استئناف الطلب بعد ساعات عملية بحث لا عملية إعادة بناء. وخدمة مخصّصة تتابع قاعدة الـ ٢٤ ساعة لكل محادثة وتقرر إن كانت الرسالة الحرة مسموحة أم أن إرسال قالب مطلوب، فيصبح الالتزام بقواعد المنصة خاصية في النظام لا شيئاً على الموظفين تذكّره.

خدمتان بحدّ موقّع بـ HMAC. البوابة تتحدث مع Meta ولا شيء غير ذلك؛ و Laravel يحمل الأعمال. تغيّرات بروتوكول Meta تتوقف عند البوابة، وتغيّرات التسعير لا تصل إليها أبداً.HMACWhatsAppالواجهة بالكاملFastify gatewayتحقّق · فكّ تشفيرFlow engineآلة حالةMySQLRedis + Queueحملات · مزامنةThawaniالمدفوعاتReverb (WS)لوحة طلبات حيةVue dashboardsالإدارة وكل فرع
خدمتان بحدّ موقّع بـ HMAC. البوابة تتحدث مع Meta ولا شيء غير ذلك؛ و Laravel يحمل الأعمال. تغيّرات بروتوكول Meta تتوقف عند البوابة، وتغيّرات التسعير لا تصل إليها أبداً.
  • Fastify gateway (Node)التحقق من توقيع Meta وفك تشفير Flow بـ RSA/AES وترجمة البروتوكول — بدون أي منطق أعمال
  • HMAC service boundaryالاتجاهان موقّعان؛ ولا خدمة تثق بطلب غير موقّع
  • Flow engine (state machine)أصناف خطوات بموضع مخزَّن، فيُستأنف الطلب المتروك من حيث توقف بالضبط
  • 24-hour window serviceتقرر بين الرسالة الحرة والقالب المعتمد لكل محادثة، مُلزِمةً سياسة Meta في الكود
  • Laravel Reverb (WebSockets)لوحات طلبات فورية للإدارة وكل فرع بدون polling
  • Thawani paymentsبوابة دفع محلية بتحقق من جهة السيرفر
  • Vue 3 + Inertia dashboardsواجهتا تشغيل مفصولتان بالأدوار فوق باكإند Laravel واحد

قرارات التصميم

خدمة بوابة منفصلة بدل controller webhook في Laravel

اخترتStandalone Node/Fastify gatewayبدلاً منHandling Meta webhooks directly inside Laravel

كان مسار Laravel واحد يعني بنية تحتية أقل وأجزاءً متحركة أقل، ولمتجر أحادي المستأجر ربما كان الصواب.

لكن ثلاثة أمور دفعت للاتجاه الآخر. Meta تطلب التحقق من التوقيع على الـ body الخام، وهذا يتعارض مع middleware الإطار الذي حلّل الطلب سابقاً. و WhatsApp Flow يحتاج التعامل مع مفاتيح RSA و AES، ولا شأن لهذا بأن يجاور منطق الفواتير. وتسليم الـ webhook يجب أن يُقَر بسرعة — وخدمة نحيفة تتحقق وتفك التشفير وتمرّر تستطيع الرد فوراً بغضّ النظر عن بطء العمل خلفها.

انتهت البوابة إلى ١٤ ملفاً باختبارات تشفير خاصة بها. هذه هي كامل تكلفة ألّا تلمس كود الأعمال أبداً عندما تُغيّر Meta شيئاً.

أصناف خطوات مخزَّنة بدل تحليل سجل المحادثة

اخترتExplicit state machine with a stored positionبدلاً منInferring intent from the message log each time

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

نمذجة الـ flow كأصناف خطوات منفصلة مع كتابة الموضع في قاعدة البيانات جعلت السلوك قابلاً للاختبار بمعزل — وهذا جزء كبير من سبب وصول مجموعة الاختبارات إلى ٥٣ ملفاً. كما جعلت حالة الطلب المتروك مجانية: الاستئناف قراءة سجل، لا إعادة تشغيل محادثة.

ترميز قاعدة الـ ٢٤ ساعة في خدمة، لا في تدريب الموظفين

اخترتA window service that gates every outbound messageبدلاً منDocumenting the rule and trusting operators

عقوبة خرق سياسة Meta ليست خطأ تحقّق — بل ضرر في تقييم جودة رقم هاتف العمل، وفقدانه في النهاية. وهذا خطر وجودي لمتجر قناته الوحيدة هي واتساب.

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

النتيجة

تعمل المنصة كخدمتين قابلتين للنشر بشكل مستقل: ١٧٦ ملف PHP على ٢٣ موديلاً و٤٤ migration في Laravel، و٧٤ مكوّن Vue للوحتين، وبوابة من ١٤ ملفاً. الجانب Laravel يحمل ٥٣ ملف اختبار Pest، مُرجَّحة نحو مسارات الدفع ومحرّك الـ flow حيث يكلّف الخلل مالاً حقيقياً.

وأبعد من الطلبات، يشحن النظام إرسال حملات جماعية، ومزامنة كتالوج وقوالب Meta، وإنشاء فواتير PDF، وساعات عمل لكل فرع، وحزمة تحليلات فيها تقارير إيرادات وأفضل المنتجات ومقارنة الفروع. وتطبيق الفروع على الموبايل تخدمه واجهة API موثَّقة بمرجع نقاط وصول مكتوب.

النتيجة التي طلبها العمل فعلاً: محادثة العميل لم تتغيّر، وكل ما يجري فيها الآن مُسجَّل ومُسعَّر وقابل للتقرير.

ما سآخذه معي

  • 01أفضل واجهة هي أحياناً تلك التي يستخدمها العميل أصلاً. بناء متجر «صحيح» كان سيعني عملاً أكثر وطلبات أقل.
  • 02عندما تتكامل مع منصة لا تتحكم بها، اعزلها خلف خدمة تتحكم بها. هذا الحدّ يسدّد ثمنه من أول مرة يغيّر المزوّد شيئاً.
  • 03سياسة المنصة تنتمي إلى الكود. أي قاعدة يمكن أن يُنهي خرقها العمل يجب أن يكون خرقها يدوياً مستحيلاً.
دراسة الحالة التاليةصِلةمراسلة بين الأجهزة بدون إنترنت ولا سيرفرات ولا شريحة