Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 61

إنشاء نقطة نهاية لرسائل واتساب الواردة

أهلاً بك مجدداً!

في الدرس السابق، استكشفنا الجانب النظري من عملية "الاستماع" وتعرفنا على مفهوم الـ Webhooks. تعلمنا أنها آلية "دفع" تُعلم تطبيقنا بوقوع حدث ما (مثل وصول رسالة واتساب) عن طريق إرسال طلب HTTP POST إلى عنوان URL نحدده. لقد فهمنا لماذا نحتاج إليها وكيف تعمل من حيث المبدأ.

اليوم، سنحول هذه النظرية إلى واقع. سنقوم ببناء عنوان URL هذا بأنفسنا. هدفنا في هذا الدرس هو بناء نقطة نهاية (Endpoint) بسيطة باستخدام لغة بايثون لاستقبال الرسائل الواردة من واتساب. سنكتب الكود الذي سيسمح لوكيلنا بـ "الاستماع" حقًا، مما يكمل الحلقة الأساسية للمحادثة.


1. كيف يستمع تطبيقنا للإنترنت؟ مقدمة إلى خوادم الويب

تطبيق البايثون الذي نكتبه يعمل على جهاز الكمبيوتر الخاص بك. كيف يمكن لخدمة خارجية مثل Twilio، الموجودة على الإنترنت، أن تتواصل معه؟ الحل هو تحويل جزء من تطبيقنا إلى خادم ويب (Web Server).

  • خادم الويب: هو برنامج متخصص وظيفته الاستماع باستمرار للطلبات القادمة من الإنترنت عبر بروتوكول HTTP. عندما يستقبل طلبًا موجهًا إلى عنوان معين (URL)، فإنه يقوم بتنفيذ كود مرتبط بهذا العنوان ثم يرسل استجابة.

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

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



2. بناء أول خادم ويب باستخدام Flask

لنبنِ الآن خادمنا الصغير الذي سيستقبل إشعارات الـ Webhook.

الخطوة الأولى: تثبيت Flask

افتح الطرفية (Terminal) أو موجه الأوامر (Command Prompt) وقم بتثبيت مكتبة Flask باستخدام pip، تمامًا كما فعلنا مع المكتبات السابقة:

pip install Flask

الخطوة الثانية: كتابة كود الخادم

الآن، أنشئ ملف بايثون جديد (مثلاً app.py) واكتب فيه الكود التالي. سأشرح كل سطر بالتفصيل.

# 1. استيراد الأدوات اللازمة من مكتبة Flask
from flask import Flask, request

# 2. إنشاء نسخة من تطبيق الويب
app = Flask(__name__)

# 3. تحديد المسار (Route) ونوع الطلب للـ Webhook
@app.route('/webhook', methods=['POST'])
def receive_webhook():
    # 4. هذه الدالة ستعمل عند وصول طلب POST إلى عنوان /webhook
    print("تم استقبال Webhook!")

    # 5. قراءة البيانات الواردة من Twilio واستخراجها
    # Twilio ترسل البيانات بتنسيق form-data، وFlask يقرأها عبر request.form
    message_body = request.form.get('Body')
    sender_id = request.form.get('From')
    
    print(f"الرسالة من {sender_id}: {message_body}")
    
    # 6. إرسال استجابة لتأكيد الاستلام
    return 'OK', 200

# 7. تشغيل الخادم عند تنفيذ الملف مباشرة
if __name__ == '__main__':
    # debug=True يجعل الخادم يعيد التشغيل تلقائيًا عند تعديل الكود
    app.run(debug=True)

شرح الكود:

  1. from flask import Flask, request: نستورد Flask لإنشاء التطبيق، وrequest للوصول إلى بيانات الطلب الوارد.
  2. app = Flask(__name__): ننشئ كائن التطبيق الرئيسي.
  3. @app.route('/webhook', methods=['POST']): هذا هو الجزء الأهم. هذا السطر، المسمى "Decorator"، يخبر Flask بأن الدالة التالية (receive_webhook) يجب أن تُنفذ فقط عند وصول طلب من نوع POST إلى المسار /webhook. هذا المسار هو ما يُعرف بـ نقطة النهاية (Endpoint).
  4. def receive_webhook():: الدالة التي تحتوي على المنطق الذي نريد تنفيذه عند استقبال الـ Webhook.
  5. request.form.get('...'): في الدرس السابق، رأينا مثالاً لحمولة (Payload) الـ Webhook. كائن request يحتوي على كل معلومات الطلب. بما أن Twilio ترسل البيانات بتنسيق form-data، نستخدم request.form للوصول إليها. get('Body') تستخرج نص الرسالة، وget('From') تستخرج رقم المرسل.
  6. return 'OK', 200: من الضروري أن يرد خادمنا على Twilio لتأكيد أنه استلم الإشعار بنجاح. 200 هو رمز حالة HTTP ويعني "OK". إذا لم نرسل هذه الاستجابة، ستعتقد Twilio أن الإشعار فشل وستحاول إرساله مرة أخرى.
  7. app.run(debug=True): هذا السطر يقوم بتشغيل خادم الويب المحلي على جهازك.


3. مشكلة "localhost" والحل باستخدام ngrok

إذا قمت الآن بتشغيل الملف (python app.py)، سترى رسالة تفيد بأن الخادم يعمل على عنوان مثل http://127.0.0.1:5000. هذا العنوان يُعرف بـ localhost، وهو يعني "هذا الكمبيوتر". المشكلة هي أن هذا العنوان خاص بجهازك فقط. خوادم Twilio الموجودة على الإنترنت لا يمكنها الوصول إليه.

إذًا، كيف نجعل خادمنا المحلي متاحًا للإنترنت بشكل مؤقت وآمن لأغراض الاختبار؟

الحل هو أداة تسمى ngrok.

ngrok هو برنامج يقوم بإنشاء "نفق" آمن بين عنوان URL عام على الإنترنت وخادم الويب الذي يعمل على جهازك المحلي. عندما ترسل Twilio إشعارًا إلى عنوان ngrok العام، يقوم ngrok بتوجيهه عبر هذا النفق مباشرة إلى تطبيق Flask الخاص بك.

خطوات استخدام ngrok:

  1. قم بتنزيل ngrok من موقعه الرسمي واتبع تعليمات التثبيت البسيطة.

  2. في نافذة طرفية (Terminal)، قم بتشغيل خادم Flask الخاص بك: python app.py.

  3. في نافذة طرفية أخرى، اكتب الأمر التالي لتوجيه ngrok إلى المنفذ الذي يعمل عليه خادم Flask (المنفذ الافتراضي هو 5000):

    ngrok http 5000
    
  4. سيقوم ngrok بعرض شاشة تحتوي على معلومات، وأهمها هو عنوان URL العام تحت قسم "Forwarding". سيبدو شيئًا كهذا: https://<سلسلة-عشوائية>.ngrok-free.app.

كيفية البدء باستخدام WhatsApp Cloud API
توضح هذه الصورة خطوات إعداد واجهة واتساب. الخطوة الثالثة "Configure a Webhook" هي بالضبط ما سنفعله الآن باستخدام العنوان الذي يوفره ngrok.


4. ربط كل شيء معًا

الآن لدينا كل القطع اللازمة. لنجمعها:

  1. خادم Flask يعمل: تأكد من أن ملف app.py يعمل في نافذة طرفية.
  2. نفق ngrok مفتوح: تأكد من أن ngrok يعمل في نافذة طرفية أخرى.
  3. احصل على عنوان الـ Webhook الكامل: انسخ عنوان ngrok العام وأضف إليه نقطة النهاية التي حددناها في الكود (/webhook). العنوان النهائي سيكون: https://<سلسلة-عشوائية>.ngrok-free.app/webhook.
  4. تحديث إعدادات Twilio: اذهب إلى لوحة تحكم Twilio، ثم إلى إعدادات رقم واتساب الخاص بك. ابحث عن قسم "Messaging" أو "Webhook for incoming messages" والصق عنوان URL الكامل الذي أنشأته في الخطوة السابقة. تأكد من أن طريقة الطلب (Method) محددة إلى HTTP POST.
  5. أرسل رسالة اختبار: من هاتفك الشخصي، أرسل رسالة واتساب إلى رقمك في Twilio.

إذا سار كل شيء على ما يرام، يجب أن ترى في نافذة الطرفية التي يعمل بها خادم Flask مخرجات تبدو كالتالي:

تم استقبال Webhook!
الرسالة من whatsapp:+966501234567: مرحباً، هل المنتج متوفر؟

لقد نجحت! تطبيقك الآن "يستمع" إلى رسائل واتساب الواردة في الوقت الفعلي.

اختبر فهمك!

ماذا سيحدث لو قمت بتغيير السطر @app.route('/webhook', methods=['POST']) إلى @app.route('/whatsapp', methods=['POST']) في الكود، دون تغيير عنوان URL في إعدادات Twilio؟

Show answer

سيتوقف الـ Webhook عن العمل. سترسل Twilio طلبها إلى .../webhook، لكن خادم Flask الخاص بك لم يعد يستمع على هذا المسار. إنه الآن يستمع فقط على .../whatsapp. سيؤدي هذا إلى خطأ 404 Not Found، وستعتقد Twilio أن الإشعار فشل في الوصول. يجب أن يتطابق المسار في الكود تمامًا مع المسار المحدد في عنوان URL الذي تم إعداده في الخدمة الخارجية.



خلاصة الدرس

في هذا الدرس، قمنا بخطوة عملية هائلة. لنلخص ما أنجزناه:

  • بنينا خادم ويب: تعلمنا كيفية استخدام إطار عمل Flask لإنشاء خادم ويب بسيط في بايثون.
  • أنشأنا نقطة نهاية (Endpoint): حددنا مسارًا (/webhook) مخصصًا لاستقبال طلبات POST من Twilio.
  • حللنا مشكلة localhost: فهمنا لماذا لا يمكن الوصول إلى الخوادم المحلية من الإنترنت واستخدمنا أداة ngrok لإنشاء نفق عام آمن.
  • أكملنا دورة الاتصال: أصبح وكيلنا الآن قادرًا على "التحدث" (من خلال الأداة التي بنيناها سابقًا) و"الاستماع" (من خلال نقطة النهاية التي بنيناها اليوم).

لقد وضعت الأساس التقني لاستقبال البيانات من العالم الخارجي.


ماذا بعد؟

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