api connectأكواد WhatsApp API

الدليل العملي لربط Odoo بـ WhatsApp عبر Whats360: Webhooks وAPI ومعالجة الرسائل والميديا

ربط Odoo بـ WhatsApp عبر Whats360 باستخدام Webhooks وAPI ومعالجة الرسائل والمرفقات

الدليل الهندسي الشامل لربط Odoo بمنظومة Whats360: كود بايثون، استقبال الميديا، وحل أخطاء الويب هوك

ربط Odoo بمنظومة WhatsApp لا يتوقف عند إرسال رسالة من النظام أو استقبال رسالة من العميل. التكامل الحقيقي يحتاج إلى تصميم واضح لمسار البيانات، ومعالجة صحيحة للـ Webhooks، وربط الرسائل بجهات الاتصال داخل Odoo، والتعامل مع الصور والملفات، بالإضافة إلى فهم أخطاء المصادقة والاتصال التي قد تظهر أثناء التشغيل.

في هذا الدليل سنبني تصورًا هندسيًا عمليًا لربط Odoo بمنظومة Whats360، مع التركيز على Webhooks وPython وOdoo Controller واستقبال الرسائل والميديا، ثم نكمل دورة التكامل بإرسال الرسائل والمستندات من Odoo إلى WhatsApp.

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

الإجابة المباشرة

يمكن بناء التكامل من خلال توجيه Webhook من Whats360 إلى مسار Controller عام داخل Odoo، بحيث يستقبل النظام أحداث الرسائل ثم يعالجها داخل Python. بعد ذلك يمكن مطابقة رقم العميل مع res.partner، وتسجيل الرسالة داخل Odoo، وحفظ المرفقات في ir.attachment عند توفر بيانات الميديا اللازمة. أما الإرسال من Odoo إلى WhatsApp فيتم من خلال API الخاص بالتكامل وفق الـ Endpoint وطريقة المصادقة الفعلية المتاحة في إعدادات الحساب والتوثيق.

لماذا يحتاج ربط Odoo بـ WhatsApp إلى تصميم معماري واضح؟

الخطأ الشائع في مشاريع التكامل هو التعامل مع WhatsApp باعتباره مجرد قناة إرسال. في الواقع، عند استخدامه داخل شركة أو متجر أو نظام ERP، تظهر عدة مسارات للبيانات في الوقت نفسه.

هناك رسالة يرسلها العميل، ورسالة يرسلها الموظف من الهاتف، وربما صورة أو ملف أو فاتورة، بالإضافة إلى بيانات تعريف المحادثة والعميل ووقت الحدث ومعرف الرسالة.

لذلك فإن التكامل الجيد يجب أن يحدد منذ البداية:

  • كيف تصل الرسائل الواردة إلى Odoo.
  • كيف يتم التعرف على العميل.
  • كيف يتم منع تسجيل الرسالة نفسها أكثر من مرة.
  • كيف تتم معالجة الصور والملفات.
  • كيف يتم تسجيل الرسائل داخل Chatter أو نظام CRM المناسب.
  • كيف يميز النظام بين رسالة العميل ورسالة الموظف.
  • كيف يتم إرسال رسالة جديدة من Odoo إلى WhatsApp.
  • كيف يتم التعامل مع أخطاء Webhook وAPI.

هذه النقاط هي التي تحول التكامل من مجرد تجربة API إلى بنية قابلة للاستخدام داخل بيئة إنتاج.

معمارية تدفق البيانات بين WhatsApp وOdoo

أفضل طريقة لفهم التكامل هي النظر إليه باعتباره مسارين متكاملين: مسار وارد من WhatsApp إلى Odoo، ومسار صادر من Odoo إلى WhatsApp.

الرسائل الواردة من العملاء

عندما تصل رسالة جديدة إلى رقم WhatsApp المتصل بالمنظومة، يمكن للـ Webhook إرسال الحدث إلى عنوان Controller داخل Odoo.

يستقبل Controller البيانات، ثم يبدأ في تحليل الـ Payload، والتأكد من نوع الحدث، واستخراج بيانات الرسالة، ثم البحث عن العميل أو إنشاء سجل جديد عند الحاجة.

بعد ذلك يمكن تخزين نص الرسالة أو الحدث داخل نموذج مناسب في Odoo، وربطه بجهة الاتصال res.partner.

قاعدة مهمة في تصميم Webhook

لا تجعل استقبال Webhook مسؤولًا عن كل العمليات الثقيلة في نفس الطلب. الأفضل أن يكون Controller قادرًا على استقبال الحدث بسرعة، ثم معالجة العمليات التي تحتاج وقتًا أكبر بطريقة مناسبة لبنية النظام، خصوصًا عند وجود عدد كبير من الرسائل أو المرفقات.

معرّفات المحادثة والهوية

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

الأفضل أن يحتفظ النظام بالمعرفات التي تصل من الحدث كما هي، مع استخدام رقم الهاتف عندما يكون متاحًا، ثم بناء طبقة Mapping داخل Odoo تستطيع التعامل مع أكثر من معرف للمحادثة نفسها.

هذا التصميم أكثر أمانًا من الاعتماد على حقل واحد فقط كمفتاح دائم للعميل.

مزامنة الرسائل التي يرسلها الموظف من الهاتف

التكامل لا يكتمل إذا كان Odoo يسجل رسائل العملاء فقط بينما تظل ردود الموظفين التي يرسلونها من تطبيق WhatsApp على الهاتف خارج النظام.

عند توفر أحداث الرسائل الصادرة، يمكن استخدام بيانات مثل is_from_me للمساعدة في تحديد أن الحدث يمثل رسالة صادرة من الحساب نفسه.

الفكرة هنا ليست مجرد معرفة اتجاه الرسالة، بل الحفاظ على تسلسل المحادثة داخل Odoo، بحيث يرى فريق العمل سجلًا أقرب إلى الواقع الفعلي للمحادثة.

مكسب تشغيلي مهم

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

إعداد Webhook داخل Whats360

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

يمكن أن يكون عنوان Controller مثل:

https://your-odoo-domain.com/whatsapp/webhook

هذا العنوان مجرد مثال على Route داخل مشروع Odoo، ويجب استبداله بعنوان الخادم الحقيقي ومسار الـ Controller الذي أنشأته.

تحديد الأحداث التي تحتاجها

ليس من الضروري إرسال كل الأحداث الممكنة إلى Odoo. حدد الأحداث التي يحتاجها النظام فعلًا، مثل الرسائل الواردة، والرسائل الصادرة عندما تكون مطلوبة للحفاظ على سجل المحادثة.

كل حدث يجب أن يمر داخل Controller بعملية تحقق قبل تخزينه.

Master Payload

يمكن بناء Payload موحد يحتوي على البيانات التي يحتاجها Odoo لمعالجة الحدث:

{
  "event": "incoming_message",
  "instance_id": "{{instance_id}}",
  "message_id": "{{message_id}}",
  "phone": "{{phone}}",
  "sender_name": "{{sender_name}}",
  "chat_jid": "{{chat_jid}}",
  "message": "{{message}}",
  "media_url": "{{media_url}}",
  "timestamp": "{{timestamp}}"
}

هذا المثال يحتوي فعليًا على تسعة حقول رئيسية، وليس ثمانية، وهي نقطة مهمة عند بناء Parser داخل Odoo.

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

بناء Odoo Controller باستخدام Python

الـ Controller هو نقطة الدخول التي تستقبل طلب Webhook. وفي Odoo يمكن تعريف Route عام يسمح للمنظومة الخارجية بإرسال البيانات إليه دون الحاجة إلى جلسة مستخدم داخل Odoo.

مثال مبسط على الهيكل:

from odoo import http
from odoo.http import request
import json

class WhatsAppWebhookController(http.Controller):

    @http.route(
        '/whatsapp/webhook',
        type='http',
        auth='public',
        methods=['POST'],
        csrf=False
    )
    def whatsapp_webhook(self, **kwargs):

        raw_data = request.httprequest.data

        try:
            payload = json.loads(raw_data.decode('utf-8'))
        except Exception:
            return request.make_json_response(
                {'success': False, 'error': 'Invalid JSON'},
                status=400
            )

        event = payload.get('event')
        message_id = payload.get('message_id')
        phone = payload.get('phone')
        sender_name = payload.get('sender_name')
        message = payload.get('message')
        chat_jid = payload.get('chat_jid')

        return request.make_json_response({
            'success': True,
            'event': event,
            'message_id': message_id
        })

الكود السابق يوضح البنية الأساسية للـ Controller. أما الحقول الفعلية التي تستقبلها، وقواعد المصادقة، وأسماء الأحداث، فيجب أن تتوافق مع إعدادات التكامل الفعلية.

لماذا auth=’public’؟

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

لكن auth='public' لا يعني أن Route يجب أن يكون مفتوحًا بلا أي حماية في بيئة إنتاج. يجب تصميم طبقة تحقق مناسبة للطلبات حسب آلية المصادقة التي يدعمها التكامل.

لماذا csrf=False؟

طلبات Webhook القادمة من نظام خارجي لا تمر عادة من نموذج HTML تقليدي داخل جلسة متصفح Odoo، ولذلك يجب التعامل مع حماية CSRF بما يتوافق مع طبيعة الـ Route.

إعداد csrf=False قد يكون مطلوبًا في Controller مخصص لاستقبال Webhooks، لكن يجب تعويض ذلك بالتحقق من مصدر الطلب أو سر Webhook أو آلية المصادقة المتاحة.

مطابقة العميل مع res.partner

بعد استقبال الرسالة، تأتي واحدة من أهم مراحل التكامل: ربط الرسالة بالعميل الصحيح.

يمكن استخدام رقم الهاتف عندما يكون متاحًا، لكن من الأفضل عدم وضع منطق المطابقة داخل Controller بشكل عشوائي. أنشئ دالة مستقلة لتوحيد الرقم ثم البحث عنه.

def normalize_phone(phone):
    if not phone:
        return False

    phone = ''.join(
        char for char in str(phone)
        if char.isdigit() or char == '+'
    )

    return phone

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

phone = normalize_phone(payload.get('phone'))

partner = request.env['res.partner'].sudo().search(
    [('mobile', '=', phone)],
    limit=1
)

if not partner and phone:
    partner = request.env['res.partner'].sudo().create({
        'name': payload.get('sender_name') or phone,
        'mobile': phone,
    })

هذه مجرد بنية عملية قابلة للتعديل، لأن قواعد بيانات Odoo تختلف من مشروع إلى آخر. قد تكون لديك قاعدة مطابقة أكثر تعقيدًا تعتمد على الشركة أو رقم العميل أو معرف خارجي.

استخدام sudo()

الـ Webhook يصل إلى Odoo خارج جلسة الموظف. لذلك قد تظهر أخطاء صلاحيات عند محاولة إنشاء أو تعديل سجلات باستخدام مستخدم لا يمتلك الصلاحيات المطلوبة.

في هذا السياق يمكن استخدام sudo() في المواضع التي تحتاج إلى صلاحيات النظام، مع الانتباه إلى أن استخدامه يجب أن يكون محدودًا ومقصودًا، وليس حلًا عشوائيًا لكل مشكلة صلاحيات.

منع تكرار الرسائل

في أنظمة Webhook يجب دائمًا التفكير في احتمال إعادة إرسال الحدث. إذا قام Odoo بتسجيل كل طلب يصل إليه دون التحقق من message_id، فقد تظهر الرسالة نفسها أكثر من مرة.

لذلك من الأفضل الاحتفاظ بمعرف الرسالة واستخدامه كمفتاح لمنع التكرار.

message_id = payload.get('message_id')

if message_id:
    existing = request.env['whatsapp.message'].sudo().search(
        [('external_message_id', '=', message_id)],
        limit=1
    )

    if existing:
        return request.make_json_response({
            'success': True,
            'duplicate': True
        })

يمكن أن يكون whatsapp.message نموذجًا مخصصًا داخل الموديول، وهو أفضل في المشاريع الكبيرة من وضع كل البيانات مباشرة في mail.message.

قاعدة تصميم مهمة

الـ Webhook يجب أن يكون Idempotent قدر الإمكان؛ أي إن وصول الحدث نفسه أكثر من مرة لا يؤدي إلى إنشاء بيانات مكررة أو تنفيذ العملية التجارية مرتين.

تسجيل الرسائل داخل mail.message

إذا كان الهدف هو إظهار المحادثة داخل Odoo، يمكن استخدام mail.message أو نموذج محادثات مخصص حسب تصميم الـ CRM.

الفكرة الأساسية هي ربط الرسالة بالـ Partner والسجل التجاري المناسب بدل تخزينها كنص منفصل بلا سياق.

message_record = request.env['mail.message'].sudo().create({
    'model': 'res.partner',
    'res_id': partner.id,
    'message_type': 'comment',
    'body': message or '',
})

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

التعامل مع الصور والملفات والميديا

من أكثر الأجزاء حساسية في تكامل WhatsApp مع Odoo هو التعامل مع الميديا.

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

لذلك يجب الفصل بين مرحلتين:

  • استقبال حدث الرسالة.
  • الحصول على الميديا عند توفر المعرفات أو البيانات المطلوبة.

إذا كانت استجابة الحدث تحتوي على رابط أو بيانات تسمح بجلب الملف، يمكن تنفيذ عملية التحميل ثم إنشاء ir.attachment داخل Odoo.

import base64
import requests

media_response = requests.get(
    media_url,
    headers={
        'Authorization': 'Bearer YOUR_TOKEN'
    },
    timeout=30
)

media_response.raise_for_status()

attachment = request.env['ir.attachment'].sudo().create({
    'name': 'whatsapp_media',
    'type': 'binary',
    'datas': base64.b64encode(media_response.content),
    'res_model': 'res.partner',
    'res_id': partner.id,
})

يجب استبدال طريقة المصادقة وعنوان الميديا وفق API الفعلي المتاح في حسابك. لا تفترض أن كل Endpoint أو Header متاح لمجرد أن منصة أخرى تستخدمه.

لماذا قد تكون media_url فارغة؟

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

عند وجود قيمة فارغة، ابدأ بفحص نوع الرسالة والـ Payload الكامل، ثم تحقق من آلية جلب الميديا التي يوفرها التكامل.

هذه الطريقة أفضل من محاولة تحميل قيمة فارغة أو اعتبار المشكلة تلقائيًا خطأ في Odoo.

مشكلة فك تشفير الميديا بعد إعادة ربط الجهاز

إعادة ربط جهاز WhatsApp أو إنشاء جلسة جديدة قد تؤثر على إمكانية الوصول إلى بعض البيانات المشفرة المرتبطة بالجلسة السابقة.

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

اختبر أولًا رسالة جديدة بعد إعادة الربط.

اختبار الميديا الصحيح

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

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

حل خطأ 403 Forbidden في Odoo

خطأ 403 Forbidden يعني أن الطلب وصل إلى الخادم لكنه لم يُسمح له بالوصول إلى المورد المطلوب.

في حالة Webhook، ابدأ بفحص Route نفسه.

@http.route(
    '/whatsapp/webhook',
    type='http',
    auth='public',
    methods=['POST'],
    csrf=False
)

بعد ذلك افحص:

  • هل الرابط صحيح؟
  • هل المسار منشور فعلًا في الموديول؟
  • هل الموديول تم تحديثه وإعادة تشغيل Odoo؟
  • هل الطلب يستخدم POST كما هو متوقع؟
  • هل توجد طبقة Reverse Proxy تمنع الطلب؟
  • هل توجد قاعدة Firewall أو WAF تمنع مصدر الطلب؟
  • هل Odoo نفسه يعيد 403 قبل دخول الدالة؟

لا تفترض أن كل 403 سببه CSRF. يجب تحديد الطبقة التي أصدرت الاستجابة أولًا.

فهم خطأ 401 Unauthorized

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

login_required

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

لا تستخدم Header غير موثق لمجرد أنه شائع في API أخرى.

إذا كان التوثيق الفعلي يعتمد على:

Authorization: Bearer YOUR_TOKEN

فاستخدمه كما هو موثق. وإذا كانت المنظومة تدعم طريقة أخرى مثل Token في Query String، فطبقها فقط إذا كانت متاحة رسميًا في التكامل الذي تستخدمه.

session_invalid_or_expired

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

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

لا تخلط بين طبقات المصادقة

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

إرسال الرسائل من Odoo إلى WhatsApp

بعد نجاح المسار الوارد، يمكن بناء المسار العكسي: عندما ينفذ Odoo حدثًا تجاريًا، يتم إرسال رسالة إلى العميل عبر WhatsApp.

أمثلة ذلك تشمل:

  • تأكيد طلب بيع.
  • إشعار بتحديث حالة الطلب.
  • إرسال فاتورة.
  • إرسال مستند.
  • إرسال تنبيه تشغيلي.

يمكن بناء Client بسيط باستخدام Python:

import requests

url = "https://YOUR_API_ENDPOINT"

payload = {
    "phone": customer_phone,
    "message": message_text
}

headers = {
    "Authorization": "Bearer YOUR_TOKEN",
    "Content-Type": "application/json"
}

response = requests.post(
    url,
    json=payload,
    headers=headers,
    timeout=30
)

response.raise_for_status()

result = response.json()

الكود السابق يوضح طريقة بناء الطلب، بينما يجب وضع الـ Endpoint وأسماء الحقول الفعلية وفق API المستخدمة في حسابك، وليس اعتماد عنوان افتراضي على أنه Endpoint رسمي.

إرسال فاتورة PDF

يمكن تطبيق الفكرة نفسها على المستندات. يبدأ Odoo من سجل الفاتورة، ثم يحول الملف إلى صيغة مناسبة للإرسال، وبعدها ينفذ طلب API وفق آلية إرسال المستندات التي يدعمها التكامل.

في السيناريو التجاري يمكن أن يصبح التدفق:

  1. تأكيد الفاتورة في Odoo.
  2. استخراج رقم العميل.
  3. تجهيز ملف PDF.
  4. استدعاء API الخاص بإرسال المستند.
  5. تسجيل العملية داخل Odoo.
  6. التعامل مع أي فشل من خلال سجل واضح وإمكانية إعادة المحاولة.

حوّل Odoo من نظام تسجيل إلى نظام تشغيل

عندما يرتبط WhatsApp بأحداث Odoo، يمكن للرسائل أن تصبح جزءًا من Workflow فعلي: الطلب يتغير، فيخرج إشعار؛ الفاتورة تعتمد، فيتم تجهيز المستند؛ العميل يرد، فتعود الرسالة إلى نفس سجل العميل.

استكشف تكامل Whats360 مع الأنظمة

اختبار التكامل باستخدام HookURL

قبل ربط Webhook مباشرة بمنطق Odoo الكامل، من المفيد اختبار البيانات التي تصل من المنظومة.

يمكن استخدام خدمة HookURL المتاحة ضمن بيئة Whats360 لفحص Payloads أثناء مرحلة التطوير، بحسب المزايا المتاحة في حسابك وإعدادات المنصة.

الفكرة هي عزل المشكلة إلى طبقات:

  • هل الحدث يتم توليده أصلًا؟
  • هل الـ Webhook يرسل الطلب؟
  • هل الـ Payload يحتوي على البيانات المتوقعة؟
  • هل Odoo يستقبل الطلب؟
  • هل Controller يستطيع تحليل JSON؟
  • هل عملية حفظ البيانات تنجح؟
  • هل جلب الميديا يعمل؟

إذا فشل الاختبار قبل وصول البيانات إلى Odoo، فلا معنى لتعديل كود Odoo في هذه المرحلة.

وإذا نجح HookURL بينما يفشل Odoo، يصبح نطاق البحث محصورًا في Controller أو الشبكة أو المصادقة أو إعدادات Odoo.

اختبار Webhook من منظور المطور

قبل تشغيل التكامل في بيئة الإنتاج، يجب تنفيذ اختبار تدريجي بدل ربط كل العمليات مرة واحدة.

اختبار الرسالة النصية

ابدأ برسالة نصية بسيطة. تحقق من وصول message_id وبيانات العميل والنص ووقت الحدث.

اختبار الرسالة الصادرة

أرسل رسالة من الهاتف المرتبط بالحساب، ثم تحقق من وصول الحدث الصادر عند توفر هذا النوع من الأحداث، وفحص قيمة is_from_me والبيانات المرتبطة بالمحادثة.

اختبار الصورة

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

اختبار الملف

اختبر مستندًا مثل PDF، وتأكد من عدم الاعتماد على امتداد ثابت أو MIME Type واحد لكل الملفات.

اختبار التكرار

أعد إرسال نفس الحدث أو اختبر سيناريوالتكرار، ثم تأكد من أن النظام لا ينشئ سجلًا جديدًا لنفس message_id.

اعتبارات مهمة قبل الانتقال إلى الإنتاج

التكامل الذي يعمل في بيئة اختبار ليس بالضرورة جاهزًا للإنتاج. هناك مجموعة من النقاط التي يجب مراجعتها قبل الاعتماد عليه.

  • استخدام HTTPS.
  • حماية بيانات المصادقة وعدم وضعها مباشرة في الكود.
  • تسجيل الأخطاء بطريقة قابلة للبحث.
  • تسجيل معرف الرسالة الخارجي.
  • منع تكرار الأحداث.
  • إضافة Timeouts لطلبات HTTP.
  • التعامل مع فشل تحميل الميديا.
  • عدم جعل Webhook ينتظر عمليات ثقيلة بلا حاجة.
  • توفير آلية لإعادة المحاولة للعمليات الفاشلة.
  • تحديد صلاحيات sudo() بعناية.
  • اختبار الرسائل الواردة والصادرة.
  • اختبار الصور والملفات.
  • اختبار إعادة ربط الجهاز قبل الاعتماد على بيانات قديمة.

أخطاء تصميم يجب تجنبها

هناك فرق بين تكامل يعمل وتكامل يمكن الاعتماد عليه.

ربط كل شيء برقم الهاتف فقط

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

اعتبار media_url إلزاميًا

هذا يؤدي إلى أخطاء في الرسائل النصية أو الأحداث التي لا تحتوي على رابط ميديا مباشر.

عدم تخزين Message ID

غياب معرف خارجي للرسالة يجعل منع التكرار أصعب بكثير.

وضع كل منطق التكامل داخل Controller

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

تغيير API Endpoint دون التحقق من التوثيق

إذا حصلت على 401 أو 403، لا تبدأ بتجربة Headers أو Endpoints عشوائية. افحص التوثيق الفعلي للواجهة التي تستخدمها، ثم قارن الطلب بما هو مطلوب.

تصميم التكامل ليكون قابلًا للتوسع

عند عدد قليل من الرسائل، قد يعمل Controller بسيط بشكل جيد. لكن مع نمو النظام يجب التفكير في بنية البيانات والأداء.

من المفيد فصل:

  • Webhook Receiver.
  • Message Parser.
  • Partner Mapper.
  • Media Handler.
  • Outbound API Client.
  • Logging.
  • Retry Mechanism.

هذا الفصل يجعل تعديل جزء من النظام أقل تأثيرًا على باقي المكونات.

مثلًا، إذا تغيرت طريقة الحصول على الميديا، يجب أن تستطيع تعديل Media Handler دون إعادة كتابة منطق إنشاء العميل أو تسجيل الرسالة.

منطق قابل للتوسع

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

ربط WhatsApp بالـ CRM داخل Odoo

بعد نجاح الربط الأساسي، يمكن نقل التكامل من مستوى الرسائل إلى مستوى العمليات التجارية.

فعلى سبيل المثال، يمكن ربط الرسائل بجهة الاتصال ثم ربط العميل بفرصة بيع أو أمر بيع أو فاتورة، بحسب بنية الـ CRM المستخدمة.

هنا يصبح WhatsApp جزءًا من رحلة العميل داخل Odoo بدل أن يكون قناة منفصلة.

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

الأسئلة الشائعة حول ربط Odoo وWhatsApp

لماذا يصل media_url فارغًا في Webhook؟

لأن Payload الحدث لا يعني بالضرورة أن رابط الميديا المباشر سيكون موجودًا دائمًا. تعامل مع الميديا كمرحلة منفصلة، وافحص نوع الرسالة وآلية جلب الملف التي يوفرها التكامل.

هل ظهور @lid يعني أن الرسالة لن تصل إلى Odoo؟

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

كيف أسجل الرسائل التي يرسلها الموظف من الهاتف؟

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

ما أفضل طريقة لمنع تكرار الرسائل؟

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

ما سبب 403 عند استقبال Webhook؟

افحص Route داخل Odoo، وطريقة المصادقة، وإعداد CSRF، وطبقات Reverse Proxy وFirewall. لا تفترض أن السبب واحد في جميع البيئات.

ما الفرق بين 401 و403؟

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

ماذا يعني session_invalid_or_expired؟

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

هل إعادة ربط الجهاز قد تؤثر على الميديا القديمة؟

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

هل يمكن إرسال فاتورة PDF من Odoo إلى WhatsApp؟

يمكن بناء هذا السيناريو عندما تكون واجهة التكامل المستخدمة تدعم إرسال المستندات. يبدأ التدفق من سجل الفاتورة في Odoo، ثم تجهيز الملف، ثم استدعاء API المناسب، ثم تسجيل نتيجة العملية.

هل يمكن استخدام HookURL أثناء التطوير؟

نعم، يمكن استخدام ميزة HookURL المتاحة في Whats360 لفحص Payloads واختبار مسار Webhook بحسب إمكانيات حسابك، ثم نقل الاختبار إلى Controller الخاص بـ Odoo.

خطة تنفيذ عملية للمطور

إذا كنت تبدأ التكامل من الصفر، فالأفضل ألا تبدأ بإرسال الفواتير والميديا وكل الأحداث في وقت واحد.

ابدأ بمسار بسيط يمكن اختباره بسهولة:

Webhook → Controller → JSON Parsing → Message ID → Partner Mapping → Message Storage

بعد نجاح هذا المسار، أضف الميديا.

Media Event → Media Retrieval → Download → ir.attachment → Link to Odoo Record

ثم أضف المسار الصادر.

Odoo Event → API Client → WhatsApp → Result Logging → Retry on Failure

وأخيرًا أضف السيناريوهات التجارية مثل الفواتير وأوامر البيع والمتابعة.

مقالات ذات صلة

دليل WhatsApp API مع Odoo

شرح WhatsApp Webhooks وAPI

تكامل Odoo باستخدام Python

ربط WhatsApp مع أنظمة CRM

أتمتة WhatsApp باستخدام API

هل تريد تنفيذ التكامل بدل الاكتفاء بقراءة الدليل؟

إذا كان لديك نظام Odoo قائم وتحتاج إلى ربطه بـ WhatsApp لاستقبال الرسائل أو إرسال الإشعارات والمستندات، يمكن البدء بتحديد الـ Workflow المطلوب ثم بناء طبقة التكامل المناسبة.

استفسر عن تنفيذ ربط Odoo بـ WhatsApp

الخلاصة

ربط Odoo بمنظومة WhatsApp ليس مجرد إنشاء Webhook وإرسال JSON إلى Controller. التكامل الاحترافي يحتاج إلى التعامل مع دورة الرسالة كاملة، من لحظة وصول الحدث وحتى ربطه بالعميل وتسجيله داخل Odoo، ثم معالجة الميديا عند توفرها، مع إمكانية تسجيل الرسائل الصادرة وإرسال الإشعارات والمستندات من النظام.

أهم نقطة في التصميم هي فصل المشكلات عن بعضها: خطأ Webhook ليس بالضرورة مشكلة API، وخطأ 401 ليس بالضرورة مشكلة Odoo، ووجود media_url فارغًا لا يعني تلقائيًا أن الصورة فقدت، كما أن فشل الميديا القديمة بعد إعادة ربط الجهاز يجب اختباره باستخدام ميديا جديدة قبل تعديل الكود.

وعندما يتم بناء التكامل على أساس Message ID وPartner Mapping وMedia Handler وAPI Client واضح، يصبح النظام أكثر قابلية للصيانة والتوسع، ويمكن إضافة Workflows جديدة دون إعادة بناء المنظومة بالكامل.

للمطور الذي يريد البدء عمليًا، المسار الأنسب هو إنشاء Webhook بسيط، اختبار Payload، استقبال الرسالة داخل Odoo، مطابقة res.partner، ثم إضافة الميديا والرسائل الصادرة تدريجيًا.

ابدأ من التكامل الذي تحتاجه فعلًا

إذا كان مشروعك يحتاج إلى ربط Odoo بـ WhatsApp، ابدأ بتحديد الأحداث التي تريد مزامنتها، ثم اربط الـ Webhook بالـ Controller، واختبر الرسائل والميديا قبل الانتقال إلى Workflows التجارية.

ابدأ مع Whats360

الكلمات المفتاحية التي يغطيها المقال

ربط Odoo بواتساب، ربط Odoo بـ WhatsApp، WhatsApp API، Whats360، Odoo WhatsApp Integration، Odoo Webhook، WhatsApp Webhook، Odoo Controller، Python Odoo، Odoo API Integration، res.partner، mail.message، ir.attachment، WhatsApp CRM، WhatsApp Automation، WhatsApp Integration، Media Retrieval، WhatsApp Media API، Webhook Integration، API Integration، Odoo CRM، إرسال رسائل WhatsApp من Odoo، استقبال رسائل WhatsApp داخل Odoo، إرسال فاتورة PDF عبر WhatsApp، Odoo Python Webhook، HookURL، is_from_me، @lid، Message ID، 401 Unauthorized، 403 Forbidden، session_invalid_or_expired، معالجة ميديا WhatsApp، مزامنة رسائل WhatsApp، تكامل ERP مع WhatsApp.

الأسئلة الشائعة التي يجيب عنها المقال

  • كيف أربط Odoo بـ WhatsApp باستخدام Whats360؟
  • كيف أستقبل رسائل WhatsApp داخل Odoo؟
  • كيف أرسل رسائل WhatsApp من Odoo؟
  • كيف أستخدم Webhook لربط Odoo بـ WhatsApp؟
  • كيف أتعامل مع الصور والملفات القادمة من WhatsApp داخل Odoo؟
  • كيف أحفظ مرفقات WhatsApp في ir.attachment داخل Odoo؟
  • كيف أربط رسالة WhatsApp بالعميل في res.partner؟
  • ما دور mail.message في تكامل WhatsApp مع Odoo؟
  • كيف أتعامل مع media_url الفارغ في Webhook؟
  • كيف أمنع تكرار رسائل WhatsApp داخل Odoo؟
  • ما سبب خطأ 403 عند استقبال Webhook في Odoo؟
  • ما الفرق بين 401 و403 في تكامل Odoo مع WhatsApp؟
  • ماذا يعني session_invalid_or_expired؟
  • كيف أختبر WhatsApp Webhook قبل ربطه بـ Odoo؟
  • كيف أستخدم HookURL لفحص Payload؟
  • كيف أتعامل مع is_from_me في رسائل WhatsApp؟
  • ما الفرق بين @lid ورقم الهاتف في تكامل WhatsApp؟
  • كيف أرسل فاتورة PDF من Odoo إلى WhatsApp؟
  • كيف أبني Odoo Controller لاستقبال Webhook؟
  • كيف أجعل تكامل Odoo وWhatsApp قابلًا للتوسع؟

اترك تعليقاً

زر الذهاب إلى الأعلى