التسويق بالأفلييتانشاء افلييت سيستم

هندسة نظام أفلييت متعدد التجار عملياً: دمج Vibe Coding وWhatsApp API وأتمتة العمولات

خطوات بناء نظام أفلييت متعدد التجار وربطه بواتساب API

كيفية بناء نظام أفلييت متعدد التجار باستخدام Vibe Coding وWhatsApp API: الدليل الهندسي الشامل من التخطيط إلى التشغيل

⚡ الإجابة المباشرة وخلاصة الدليل (AEO Quick Snippet)

نظام الأفلييت متعدد التجار (Multi-Vendor Affiliate Platform) هو منظومة برمجية تُمكّن عدّة متاجر وتجار مستقلين (Tenants) من عرض منتجاتهم وحملاتهم التسويقية داخل سوق مركزي موحد، مع تمكين شبكة مسوقين بالعمولة (Affiliates) من توليد روابط تتبع مخصصة، واحتساب العمولات آلياً عبر محرك إسناد مالي دقيق (Attribution Engine) يفصل حسابات كل تاجر بصورة معزولة تماماً. يُبنى هذا النظام هندسياً عبر معمارية متعددة المستأجرين (Multi-Tenant Architecture) تستند إلى قواعد بيانات علائقية مثل PostgreSQL مدعومة بسياسات أمان على مستوى الصف (Row-Level Security – RLS). أما منهجية البرمجة بالذكاء الاصطناعي التفاعلي الموجه (Vibe Coding)، فهي استراتيجية هندسية تعتمد على تحويل المواصفات الوظيفية الدقيقة ومخططات المعمارية (System Architecture) إلى كود برمجي عالي الجودة ومكتوب بلغات مثل Node.js/TypeScript أو PHP عبر التوجيه المنطقي لنماذج الذكاء الاصطناعي التوليدية. يتكامل هذا النظام مباشرة مع قنوات الاتصال الفوري عبر WhatsApp API من خلال واجهات برمجية وخطافات ويب (Webhooks) لإرسال تنبيهات لحظية ومؤتمتة للتجار والمسوقين تخص مبيعاتهم وعمولاتهم، مما يحقق معدلات تفاعل تتجاوز 95% متفوقة على البريد التقليدي.

🚀 هل تريد إطلاق شبكة الأفلييت الخاصة بك بدون تعقيدات برمجية؟

وفر شهوراً من العمل البرمجي الشاق والتكاليف الباهظة مع منظومة متكاملة تجمع بين هندسة الوكلاء الأذكياء وأتمتة محادثات واتساب اللحظية.

  • تطوير وتخصيص معماريات الأنظمة المعقدة عبر وكلاء Beincode الأذكياء.
  • أتمتة تنبيهات الطلبات والعمولات فورياً دون حظر عبر Whats360.
  • تكامل تلقائي مع المحافظ والمدفوعات الإلكترونية عبر EGCash.

تحدث مع مهندس النظام عبر واتساب الآن

       ┌────────────────────────────────────────────────────────┐
       │             منظومة الأفلييت متعددة التجار            │
       └──────────────────────────┬─────────────────────────────┘
                                  │
         ┌────────────────────────┴────────────────────────┐
         ▼                                                 ▼
┌──────────────────┐                             ┌──────────────────┐
│ محرك الإسناد     │                             │ طبقة التكامل     │
│ والتتبع المالي   │                             │ والاتصال اللحظي  │
└────────┬─────────┘                             └────────┬─────────┘
         │                                                │
         ├─ تتبع النقرات والـ Cookies                     ├─ خطافات الويب (Webhooks)
         ├─ تجزئة السلة بين التجار                        ├─ واجهات برمجة (REST APIs)
         └─ دفتر الأستاذ (Financial Ledger)               └─ تنبيهات WhatsApp الفورية

تاريخياً، كان تشييد شبكة تسويق بالعمولة تدعم تجاراً متعددين يتطلب أشهراً من التطوير المضني ومئات الآلاف من الدولارات لبرمجة محركات الإسناد، والتعامل مع تضارب الكوكيز (Attribution Clashes)، ومعالجة المدفوعات والعمولات المعلقة. لكن مع نضوج تقنيات التطوير الموجه بالذكاء الاصطناعي، بات بإمكان المطورين ورواد الأعمال تشييد وتدقيق هذه المنظومات المعقدة بسرعة غير مسبوقة، شريطة فهم القواعد الهندسية الدقيقة التي تمنع اختراق البيانات أو انهيار العمليات المالية المتزامنة.

🌐 مفهوم النظام ودورة العمل الحيوية

تقوم شبكة الأفلييت متعددة التجار على تفاعل معقد ومترابط بين أربعة أطراف رئيسية داخل بيئة برمجية سحابية موحدة تضمن حفظ الحقوق واحتساب الحركات اللحظية:

sequenceDiagram
    autonumber
    actor C as العميل (Customer)
    actor A as المسوق (Affiliate)
    participant S as متجر التاجر (Merchant Store)
    participant P as منصة الأفلييت (Affiliate Platform)
    participant W as خدمة WhatsApp API

    A->>P: 1. توليد رابط إحالة مخصص (?ref=AFF1001)
    A->>C: 2. ترويج الرابط عبر القنوات الإعلانية
    C->>S: 3. النقر على الرابط وتخزين Click ID في Cookie
    C->>S: 4. إتمام عملية الشراء (Checkout)
    S->>P: 5. إرسال Webhook ببيانات الطلب والـ Ref ID
    P->>P: 6. التحقق من التوقيع واحتساب العمولة بدفتر الأستاذ
    P->>W: 7. استدعاء API لإرسال إشعار فوري
    W-->>A: 8. تنبيه المسوق بالعمولة المستحقة

الأطراف الأربعة لمنظومة الأفلييت

  • إدارة المنصة (Platform Super Admin): الجهة المسؤولة عن تشغيل النظام، مراقبة النزاهة المالية، فرض سياسات تتبع النقرات، وفصل النزاعات بين التجار والمسوقين.
  • التاجر (Merchant / Vendor): مستأجر مستقل (Tenant) يربط متجره (مثل WooCommerce أو Shopify) بالنظام، يحدد نسب العمولات لمنتجاته، ويتحكم في فترات استحقاق الأرباح (Locking Period).
  • المسوق بالعمولة (Affiliate / Publisher): الشريك الترويجي الذي يحصل على معرّف تتبع فريد، يروج للمنتجات، ويتابع نقراته وأرباحه وسحوباته عبر لوحة تحكم مخصصة.
  • المشتري النهائي (End Customer): المستهلك الذي ينقر على روابط التتبع ويتم تسجيل الـ Attribution Context الخاص به لإسناد البيع للمسوق المستحق.

التمييز الجوهري بين النماذج البرمجية

  • نظام الأفلييت أحادي التاجر (Single-Store Affiliate): يُبنى كإضافة (Plugin) ترتبط بمتجر واحد وقاعدة بيانات مفردة؛ حيث تكون جميع المنتجات تابعة لجهة تجارية واحدة، وحساب العمولة يسير في خط مستقيم.
  • نظام الماركت بليس التقليدي (Multi-Vendor Marketplace): يركز على تجميع بائعين متعددين داخل سلة شراء موحدة لإدارة المخزون والتوصيل المباشر، دون التركيز على آليات التتبع الخارجي والإسناد بالعمولة، مثل المنصات الاستعراضية كمنصة Toggaar.
  • منصة الأفلييت متعددة التجار (Multi-Vendor Affiliate Platform): شبكة SaaS سحابية معقدة ومستقلة تماماً عن مواقع المتاجر؛ تستقبل البيانات عبر واجهات برمجة التطبيقات (APIs) والـ Webhooks من متاجر مختلفة، وتدير حسابات الإسناد وتضارب الكوكيز (Attribution Clashes)، وتفصل المستحقات المالية لكل تاجر بصورة معزولة، وتوفر تتبعاً دقيقاً لآلاف المسوقين في وقت واحد.

📋 وثيقة متطلبات المنتج والهندسة البرمجية

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

⚠️ قاعدة هندسية صارمة:

التعامل مع العمولات دون دفتر أستاذ مالي مزدوج (Double-Entry Ledger) يؤدي حتماً إلى أخطاء مالية كارثية عند حدوث إلغاء جزئي أو استرجاع للطلبات في بيئة متعددة التجار.

قصص المستخدمين الأساسية (Core User Stories)

  • كتاجر (Merchant): “أريد ربط متجري بالمنصة وتحديد عمولة 10% على تصنيف الإلكترونيات، مع فترة تعليق 14 يوماً للعمولة لضمان عدم استرجاع المنتج قبل الدفع”.
  • كمسوق (Affiliate): “أريد توليد رابط تتبع لمنتج معين وتلقي إشعار فوري على حسابي في واتساب بمجرد إتمام بيع ناجح، ومعرفة رصيدي المعلق والمتاح”.
  • كمدير نظام (Admin): “أريد استعراض حركة القيود المالية لكافة التجار وعكس العمولات آلياً عند حدوث استرجاع كلي أو جزئي للطلب دون الإخلال باتزان الدفاتر المالية”.

المتطلبات الوظيفية وغير الوظيفية

  1. محرك الإسناد الديناميكي: دعم نماذج الإسناد الشائعة (Last-Click، First-Click)، والتعامل مع فترات صلاحية ملفات التتبع (Cookie Lifetime).
  2. محرك تجزئة السلة (Cart Splitting Engine): في حال احتوى طلب شراء واحد على منتجات تابعة لتاجرين مختلفين، يجب أن يولد النظام سجلين منفصلين للعمولات، يحاسب كل تاجر على منتجاته دون تداخل مالي.
  3. دفتر الأستاذ المالي (Financial Ledger): تسجيل كل عملية مالية (استحقاق، اعتماد، سحب، عكس) كقيد مزدوج غير قابل للتعديل التاريخي (Immutable).
  4. بوابة إشعارات متعددة القنوات: الربط الآمن مع واجهات برمجة التطبيقات لإرسال تنبيهات لحظية للأحداث الحيوية عبر WhatsApp وSMS Control والبريد من خلال UltraMail.
  5. المتانة والتحمل (Throughput & Latency): يجب ألا يتجاوز زمن استجابة مسار إعادة التوجيه وتتبع النقرات (Click Redirect) أكثر من 50ms.
  6. القدرة على معالجة العمليات المتزامنة (Concurrency): منع تكرار صرف العمولات عن طريق تقنيات الأقفال التفاؤلية أو التشاؤمية (Optimistic/Pessimistic Locking) داخل المعاملات المصرفية.
  7. الأمان والعزل التام: تطبيق معايير OWASP API Security العشرة، وعزل بيانات كل تاجر برمجياً عبر RLS.

⚙️ المقارنة التقنية لاختيار مكدس البرمجيات

يتطلب بناء نظام أفلييت عالي الاعتمادية موازنة دقيقة بين سرعة التطوير، وتكلفة الاستضافة، وأداء معالجة البيانات اللحظية:

الطبقة البرمجية التقنية المختارة الخيارات البديلة مبرر الاختيار الهندسي
واجهة المستخدم (Frontend) Next.js (React / TypeScript) Vue.js / Nuxt, Blade تقديم أداء فائق في تقديم لوحات التحكم عبر Server-Side Rendering وAPI Routes مدمجة وتوافق مذهل مع TypeScript.
محرك الخلفية (Backend API) Node.js (Fastify / NestJS) Laravel (PHP), Django (Python) قدرة هائلة على معالجة آلاف اتصالات التتبع اللحظية (High I/O Concurrency) بزمن تأخير منخفض جداً واستهلاك رشيد لموارد الخادم.
قاعدة البيانات (Database) PostgreSQL (علائقية متقدمة) MySQL, MongoDB توفير محرك القيود المالية المعقدة (ACID Transactions)، ودعم RLS الأصيل لعزل المستأجرين، ودعم تخزين JSONB.
طوابير المعالجة (Queues & Cache) Redis + BullMQ RabbitMQ, SQS إدارة طوابير الـ Webhooks وإشعارات واتساب وإعادة المحاولة التلقائية (Exponential Backoff) وتخزين الـ Caches المؤقتة للنقرات.
بيئة الـ Vibe Coding Beincode AI Workflows Cursor, Windsurf أتمتة توليد الهياكل البرمجية والتحقق المنطقي من صحة خوارزميات الإسناد والربط التلقائي للوكلاء البرمجيين (AI Agents).

🏛️ المعمارية الهندسية متعددة المستأجرين

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

graph TD
    subgraph Client Layer
        A[المسوق] -->|طلب API / لوحة التحكم| G[API Gateway]
        M[التاجر] -->|طلب API / الإدارة| G
    end

    subgraph Security & Context
        G -->|التحقق من JWT & Tenant Context| C[Tenant Middleware]
        C -->|Set Local Context app.current_tenant_id| DB[(PostgreSQL Database)]
    end

    subgraph Data Isolation Layer
        DB -->|تطبيق Row-Level Security| T1[سجلات التاجر A]
        DB -->|تطبيق Row-Level Security| T2[سجلات التاجر B]
    end

استراتيجيات عزل البيانات للمنصات السحابية

  1. قاعدة بيانات منفصلة لكل مستأجر (Database-per-tenant): عزل تام ومطلق، لكنه عالي التكلفة وصعب الإدارة عند التوسع لآلاف التجار.
  2. مخطط منفصل لكل مستأجر (Schema-per-tenant): توازن جيد، لكنه يسبب تعقيدات هائلة في ترحيل التحديثات البرمجية (Migrations).
  3. قاعدة بيانات مشتركة مع عزل المعرفات (Shared Database, Shared Schema with Tenant ID): النموذج الأكثر كفاءة وقابلية للتوسع لمنصات SaaS، حيث تشترك جميع الكيانات في نفس الجداول وتُفصل السجلات عبر حقل merchant_id (Tenant Identifier)، وتُحمى بواسطة PostgreSQL Row-Level Security (RLS).

💾 تصميم قاعدة البيانات المتقدمة ونماذج أكواد SQL

تتوزع قاعدة البيانات عبر 17 جدولاً مترابطاً يضمن التكامل والاتزان المالي ومنع التكرار:

┌──────────────┐       ┌─────────────────┐       ┌──────────────────────┐
│  merchants   │◀──────│ merchant_members│       │ affiliate_campaigns  │
└──────┬───────┘       └─────────────────┘       └──────────┬───────────┘
       │                                                    │
       ├────────────────────────────────┐                   │
       ▼                                ▼                   ▼
┌──────────────┐       ┌─────────────────┐       ┌──────────────────────┐
│   products   │       │     orders      │◀──────│   affiliate_links    │
└──────┬───────┘       └────────┬────────┘       └──────────┬───────────┘
       │                        │                           │
       ▼                        ▼                           ▼
┌──────────────┐       ┌─────────────────┐       ┌──────────────────────┐
│ order_items  │       │   commissions   │       │        clicks        │
└──────────────┘       └────────┬────────┘       └──────────────────────┘
                                │
                                ▼
                       ┌─────────────────┐
                       │commission_ledger│
                       └─────────────────┘
الملف: database/migrations/001_core_schema.sql (PostgreSQL DDL)

CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS "pgcrypto";

CREATE TABLE users (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    email VARCHAR(255) UNIQUE NOT NULL,
    password_hash VARCHAR(255) NOT NULL,
    phone_number VARCHAR(50) UNIQUE,
    full_name VARCHAR(255) NOT NULL,
    role VARCHAR(50) NOT NULL CHECK (role IN ('super_admin', 'merchant_admin', 'merchant_staff', 'affiliate')),
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE merchants (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    business_name VARCHAR(255) NOT NULL,
    slug VARCHAR(100) UNIQUE NOT NULL,
    webhook_secret VARCHAR(255) NOT NULL,
    api_key_hash VARCHAR(255) NOT NULL,
    default_commission_rate NUMERIC(5, 2) DEFAULT 10.00 CHECK (default_commission_rate >= 0),
    cookie_duration_days INT DEFAULT 30 CHECK (cookie_duration_days > 0),
    currency VARCHAR(10) DEFAULT 'EGP',
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE merchant_members (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    merchant_id UUID NOT NULL REFERENCES merchants(id) ON DELETE CASCADE,
    user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    permissions JSONB DEFAULT '{"can_manage_orders": true, "can_view_reports": true}',
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    UNIQUE(merchant_id, user_id)
);

CREATE TABLE affiliates (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    referral_code VARCHAR(50) UNIQUE NOT NULL,
    payout_details JSONB NOT NULL DEFAULT '{}',
    total_earned NUMERIC(12, 2) DEFAULT 0.00,
    balance_available NUMERIC(12, 2) DEFAULT 0.00,
    balance_pending NUMERIC(12, 2) DEFAULT 0.00,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE affiliate_campaigns (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    merchant_id UUID NOT NULL REFERENCES merchants(id) ON DELETE CASCADE,
    name VARCHAR(255) NOT NULL,
    commission_type VARCHAR(20) DEFAULT 'percentage' CHECK (commission_type IN ('percentage', 'fixed')),
    commission_value NUMERIC(10, 2) NOT NULL CHECK (commission_value >= 0),
    is_active BOOLEAN DEFAULT TRUE,
    start_date TIMESTAMP WITH TIME ZONE,
    end_date TIMESTAMP WITH TIME ZONE,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE affiliate_links (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    affiliate_id UUID NOT NULL REFERENCES affiliates(id) ON DELETE CASCADE,
    merchant_id UUID NOT NULL REFERENCES merchants(id) ON DELETE CASCADE,
    campaign_id UUID REFERENCES affiliate_campaigns(id) ON DELETE SET NULL,
    custom_slug VARCHAR(100) NOT NULL,
    target_url TEXT NOT NULL,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    UNIQUE(affiliate_id, merchant_id, custom_slug)
);

CREATE TABLE visitors (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    ip_hash VARCHAR(64) NOT NULL,
    user_agent TEXT,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE clicks (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    link_id UUID NOT NULL REFERENCES affiliate_links(id) ON DELETE CASCADE,
    affiliate_id UUID NOT NULL REFERENCES affiliates(id) ON DELETE CASCADE,
    merchant_id UUID NOT NULL REFERENCES merchants(id) ON DELETE CASCADE,
    visitor_id UUID REFERENCES visitors(id) ON DELETE SET NULL,
    click_id VARCHAR(100) UNIQUE NOT NULL,
    ip_hash VARCHAR(64) NOT NULL,
    is_fraudulent BOOLEAN DEFAULT FALSE,
    fraud_reason VARCHAR(255),
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE products (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    merchant_id UUID NOT NULL REFERENCES merchants(id) ON DELETE CASCADE,
    external_store_product_id VARCHAR(100) NOT NULL,
    title VARCHAR(255) NOT NULL,
    price NUMERIC(10, 2) NOT NULL,
    sku VARCHAR(100),
    is_available BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    UNIQUE(merchant_id, external_store_product_id)
);

CREATE TABLE orders (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    merchant_id UUID NOT NULL REFERENCES merchants(id) ON DELETE CASCADE,
    affiliate_id UUID REFERENCES affiliates(id) ON DELETE SET NULL,
    click_id VARCHAR(100) REFERENCES clicks(click_id) ON DELETE SET NULL,
    external_order_id VARCHAR(100) NOT NULL,
    order_status VARCHAR(50) NOT NULL CHECK (order_status IN ('pending', 'processing', 'completed', 'cancelled', 'refunded')),
    subtotal_amount NUMERIC(12, 2) NOT NULL,
    tax_amount NUMERIC(10, 2) DEFAULT 0.00,
    shipping_amount NUMERIC(10, 2) DEFAULT 0.00,
    total_amount NUMERIC(12, 2) NOT NULL,
    commission_eligible_amount NUMERIC(12, 2) NOT NULL,
    currency VARCHAR(10) NOT NULL,
    customer_phone VARCHAR(50),
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    UNIQUE(merchant_id, external_order_id)
);

CREATE TABLE order_items (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    order_id UUID NOT NULL REFERENCES orders(id) ON DELETE CASCADE,
    product_id UUID REFERENCES products(id) ON DELETE SET NULL,
    merchant_id UUID NOT NULL REFERENCES merchants(id) ON DELETE CASCADE,
    title VARCHAR(255) NOT NULL,
    quantity INT NOT NULL CHECK (quantity > 0),
    unit_price NUMERIC(10, 2) NOT NULL,
    total_price NUMERIC(10, 2) NOT NULL,
    is_commissionable BOOLEAN DEFAULT TRUE
);

CREATE TABLE commissions (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    order_id UUID NOT NULL REFERENCES orders(id) ON DELETE CASCADE,
    merchant_id UUID NOT NULL REFERENCES merchants(id) ON DELETE CASCADE,
    affiliate_id UUID NOT NULL REFERENCES affiliates(id) ON DELETE CASCADE,
    rate_applied NUMERIC(5, 2) NOT NULL,
    amount NUMERIC(10, 2) NOT NULL,
    status VARCHAR(50) DEFAULT 'pending' CHECK (status IN ('pending', 'approved', 'reversed', 'paid')),
    hold_until TIMESTAMP WITH TIME ZONE,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE commission_ledger (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    commission_id UUID NOT NULL REFERENCES commissions(id) ON DELETE CASCADE,
    affiliate_id UUID NOT NULL REFERENCES affiliates(id) ON DELETE CASCADE,
    merchant_id UUID NOT NULL REFERENCES merchants(id) ON DELETE CASCADE,
    entry_type VARCHAR(20) NOT NULL CHECK (entry_type IN ('credit_pending', 'credit_available', 'debit_payout', 'debit_reversal')),
    amount NUMERIC(10, 2) NOT NULL,
    notes TEXT,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE payouts (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    affiliate_id UUID NOT NULL REFERENCES affiliates(id) ON DELETE CASCADE,
    amount NUMERIC(10, 2) NOT NULL CHECK (amount > 0),
    status VARCHAR(50) DEFAULT 'requested' CHECK (status IN ('requested', 'processing', 'completed', 'rejected')),
    payout_method VARCHAR(50) NOT NULL,
    transaction_reference VARCHAR(255),
    processed_at TIMESTAMP WITH TIME ZONE,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE webhook_events (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    merchant_id UUID REFERENCES merchants(id) ON DELETE CASCADE,
    event_id VARCHAR(255) NOT NULL,
    event_type VARCHAR(100) NOT NULL,
    idempotency_key VARCHAR(255) UNIQUE NOT NULL,
    payload JSONB NOT NULL,
    status VARCHAR(50) DEFAULT 'received' CHECK (status IN ('received', 'processed', 'failed')),
    error_message TEXT,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE notifications (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    recipient_user_id UUID REFERENCES users(id) ON DELETE CASCADE,
    channel VARCHAR(20) NOT NULL CHECK (channel IN ('whatsapp', 'sms', 'email', 'in_app')),
    destination VARCHAR(100) NOT NULL,
    message_content TEXT NOT NULL,
    external_message_id VARCHAR(255),
    delivery_status VARCHAR(50) DEFAULT 'queued' CHECK (delivery_status IN ('queued', 'sent', 'delivered', 'failed')),
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE audit_logs (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID REFERENCES users(id) ON DELETE SET NULL,
    merchant_id UUID REFERENCES merchants(id) ON DELETE SET NULL,
    action VARCHAR(100) NOT NULL,
    entity_name VARCHAR(100) NOT NULL,
    entity_id VARCHAR(100) NOT NULL,
    ip_address VARCHAR(50),
    details JSONB,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX idx_clicks_click_id ON clicks(click_id);
CREATE INDEX idx_clicks_merchant_affiliate ON clicks(merchant_id, affiliate_id);
CREATE INDEX idx_orders_merchant_external ON orders(merchant_id, external_order_id);
CREATE INDEX idx_orders_click_id ON orders(click_id);
CREATE INDEX idx_commissions_order ON commissions(order_id);
CREATE INDEX idx_commissions_status ON commissions(status);
CREATE INDEX idx_ledger_affiliate ON commission_ledger(affiliate_id);
CREATE INDEX idx_webhook_events_idempotency ON webhook_events(idempotency_key);

تطبيق سياسات الأمان على مستوى الصف (RLS)

ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
ALTER TABLE commissions ENABLE ROW LEVEL SECURITY;
ALTER TABLE products ENABLE ROW LEVEL SECURITY;

CREATE POLICY merchant_orders_isolation_policy ON orders
    FOR ALL
    USING (
        merchant_id = NULLIF(current_setting('app.current_merchant_id', true), '')::UUID
        OR current_setting('app.is_super_admin', true) = 'true'
    )
    WITH CHECK (
        merchant_id = NULLIF(current_setting('app.current_merchant_id', true), '')::UUID
        OR current_setting('app.is_super_admin', true) = 'true'
    );

CREATE POLICY merchant_products_isolation_policy ON products
    FOR ALL
    USING (
        merchant_id = NULLIF(current_setting('app.current_merchant_id', true), '')::UUID
        OR current_setting('app.is_super_admin', true) = 'true'
    );

🎯 محرك تتبع المسوقين والإسناد

عندما ينقر العميل على رابط الإحالة: https://store.example.com/product/123?ref=AFF1001 يقوم خادم التوجيه الخاص بمنصة الأفلييت بإنشاء معرف نقرة فريد مشفر وموقّع بطريقة HMAC-SHA256 يمنع التلاعب.

الملف: src/tracking/click-tracker.ts (TypeScript / Node.js)

import crypto from 'crypto';
import Redis from 'ioredis';

const redis = new Redis(process.env.REDIS_URL || 'redis://localhost:6379');
const SIGNING_SECRET = process.env.ATTRIBUTION_SECRET || 'secret-system-key-360';

interface ClickContext {
  affiliateId: string;
  merchantId: string;
  campaignId?: string;
  ipAddress: string;
  userAgent: string;
}

export class ClickTrackerService {
  public static generateSecureClickId(affiliateId: string, merchantId: string): string {
    const rawData = `${affiliateId}:${merchantId}:${Date.now()}:${crypto.randomBytes(8).toString('hex')}`;
    const signature = crypto.createHmac('sha256', SIGNING_SECRET).update(rawData).digest('hex').substring(0, 16);
    return Buffer.from(`${rawData}:${signature}`).toString('base64url');
  }

  public async registerClick(context: ClickContext, targetUrl: string): Promise<{ redirectUrl: string; clickId: string }> {
    const clickId = ClickTrackerService.generateSecureClickId(context.affiliateId, context.merchantId);

    const ipThrottleKey = `throttle:click:${context.ipAddress}:${context.affiliateId}`;
    const isSpam = await redis.set(ipThrottleKey, '1', 'EX', 5, 'NX');

    if (!isSpam) {
      await redis.lpush('queue:suspicious_clicks', JSON.stringify({ ...context, clickId, reason: 'High-frequency IP burst' }));
    }

    const clickDataKey = `attribution:click:${clickId}`;
    await redis.set(
      clickDataKey,
      JSON.stringify({
        affiliateId: context.affiliateId,
        merchantId: context.merchantId,
        campaignId: context.campaignId,
        timestamp: Date.now(),
      }),
      'EX',
      60 * 60 * 24 * 30
    );

    const redirectUrlObj = new URL(targetUrl);
    redirectUrlObj.searchParams.set('aff_click_id', clickId);
    redirectUrlObj.searchParams.set('aff_id', context.affiliateId);

    return { redirectUrl: redirectUrlObj.toString(), clickId };
  }
}

كود تتبع المتصفح وحفظ الكوكيز في متجر التاجر (affiliate-tag.js)

(function () {
  const urlParams = new URLSearchParams(window.location.search);
  const clickId = urlParams.get('aff_click_id');
  const affId = urlParams.get('aff_id');

  if (clickId && affId) {
    const cookiePayload = JSON.stringify({ clickId, affId, t: Date.now() });
    const expiryDays = 30;
    const date = new Date();
    date.setTime(date.getTime() + expiryDays * 24 * 60 * 60 * 1000);
    
    document.cookie = `aff_attribution=${encodeURIComponent(cookiePayload)}; expires=${date.toUTCString()}; path=/; SameSite=Lax; Secure`;
  }
})();

💰 محرك احتساب العمولات ودفتر الأستاذ المالي

تعتمد الحسابات الدقيقة على تفكيك بنود الطلب واستبعاد الضرائب والشحن لضمان اتزان الدفاتر المحاسبية:

graph LR
    subgraph Calculation Flow
        A[إجمالي السلة: 1200 ج.م] --> B[خصم الشحن: 100 ج.م]
        B --> C[خصم الضريبة: 100 ج.م]
        C --> D[المبلغ المؤهل: 1000 ج.م]
        D -->|ضرب نسبة 10%| E[العمولة المكتسبة: 100 ج.م]
    end

    subgraph Ledger Accounting
        E --> F[(قيد مدين للتاجر: 100 ج.م)]
        E --> G[(قيد دائن معلق للمسوق: 100 ج.م)]
    end
الملف: src/finance/commission-engine.ts (TypeScript)

import { Pool, PoolClient } from 'pg';

export interface OrderFinancialData {
  orderId: string;
  merchantId: string;
  affiliateId: string;
  clickId: string;
  subtotal: number;
  shipping: number;
  tax: number;
  total: number;
  commissionRate: number;
  holdPeriodDays: number;
}

export class CommissionEngine {
  constructor(private pool: Pool) {}

  public async calculateAndRecordPendingCommission(data: OrderFinancialData): Promise {
    const client: PoolClient = await this.pool.connect();

    try {
      await client.query('BEGIN');

      const commissionAmount = Number(((data.subtotal * data.commissionRate) / 100).toFixed(2));
      const holdUntilDate = new Date();
      holdUntilDate.setDate(holdUntilDate.getDate() + data.holdPeriodDays);

      const checkExisting = await client.query(
        'SELECT id FROM commissions WHERE order_id = $1 AND merchant_id = $2 FOR UPDATE',
        [data.orderId, data.merchantId]
      );

      if (checkExisting.rows.length > 0) {
        throw new Error(`Commission already exists for Order ${data.orderId}`);
      }

      const insertCommissionQuery = `
        INSERT INTO commissions (
          order_id, merchant_id, affiliate_id, rate_applied, amount, status, hold_until
        ) VALUES ($1, $2, $3, $4, $5, 'pending', $6)
        RETURNING id;
      `;
      const commissionRes = await client.query(insertCommissionQuery, [
        data.orderId,
        data.merchantId,
        data.affiliateId,
        data.commissionRate,
        commissionAmount,
        holdUntilDate,
      ]);
      const commissionId = commissionRes.rows[0].id;

      const insertLedgerQuery = `
        INSERT INTO commission_ledger (
          commission_id, affiliate_id, merchant_id, entry_type, amount, notes
        ) VALUES ($1, $2, $3, 'credit_pending', $4, $5);
      `;
      await client.query(insertLedgerQuery, [
        commissionId,
        data.affiliateId,
        data.merchantId,
        commissionAmount,
        `Pending commission from Order ${data.orderId}. Eligible base: ${data.subtotal}`,
      ]);

      await client.query(
        'UPDATE affiliates SET balance_pending = balance_pending + $1, updated_at = CURRENT_TIMESTAMP WHERE id = $2',
        [commissionAmount, data.affiliateId]
      );

      await client.query('COMMIT');
      return commissionId;
    } catch (error) {
      await client.query('ROLLBACK');
      throw error;
    } finally {
      client.release();
    }
  }

  public async reverseCommission(commissionId: string, reason: string): Promise {
    const client = await this.pool.connect();

    try {
      await client.query('BEGIN');

      const commRes = await client.query(
        'SELECT id, affiliate_id, merchant_id, amount, status FROM commissions WHERE id = $1 FOR UPDATE',
        [commissionId]
      );

      if (commRes.rows.length === 0) {
        throw new Error('Commission record not found');
      }

      const commission = commRes.rows[0];

      if (commission.status === 'reversed') {
        throw new Error('Commission is already reversed');
      }

      await client.query(
        `INSERT INTO commission_ledger (commission_id, affiliate_id, merchant_id, entry_type, amount, notes)
         VALUES ($1, $2, $3, 'debit_reversal', $4, $5)`,
        [commission.id, commission.affiliate_id, commission.merchant_id, commission.amount, `Reversal Reason: ${reason}`]
      );

      await client.query(
        "UPDATE commissions SET status = 'reversed', updated_at = CURRENT_TIMESTAMP WHERE id = $1",
        [commission.id]
      );

      if (commission.status === 'pending') {
        await client.query(
          'UPDATE affiliates SET balance_pending = GREATEST(balance_pending - $1, 0) WHERE id = $2',
          [commission.amount, commission.affiliate_id]
        );
      } else if (commission.status === 'approved') {
        await client.query(
          'UPDATE affiliates SET balance_available = balance_available - $1 WHERE id = $2',
          [commission.amount, commission.affiliate_id]
        );
      }

      await client.query('COMMIT');
    } catch (error) {
      await client.query('ROLLBACK');
      throw error;
    } finally {
      client.release();
    }
  }
}

🤖 بناء النظام بمنهجية فايب كودنج

تعتمد منهجية فايب كودنج (Vibe Coding) على تفكيك النظام إلى وحدات فرعية موجهة بدقة بنماذج الذكاء الاصطناعي، مع مراجعة الكود واختباره فورياً لضمان النزاهة الهندسية.

graph TD
    P[1. موجه معماري عالي الدقة Prompt] --> G[2. توليد الكود Module-by-Module]
    G --> T[3. اختبار فوري عبر Unit Tests]
    T -->|نجح| S[4. تدقيق أمني ومراجعة SQL Injection]
    T -->|فشل| R[5. تعديل الموجه وإعادة التوليد]
    R --> G
    S --> D[6. الدمج في المستودع الرئيسي]
💡 نموذج موجه Vibe Coding عملي للإنتاج:

Role: Senior Distributed Systems & Fintech Engineer.
Task: Write a production-ready Fastify (Node.js/TypeScript) route handler for:
POST /api/v1/merchants/:merchantId/webhooks/orders

Requirements:
1. Validate HMAC-SHA256 signature from 'X-Merchant-Signature' header using merchant's stored secret.
2. Implement strict idempotency check using 'X-Idempotency-Key' with Redis.
3. If valid, parse order payload, extract 'aff_click_id' from metadata, and calculate commission.
4. Use PostgreSQL transaction for all balance updates.
5. Log event in 'webhook_events' table.
6. Return HTTP 200 within 200ms. Handle queueing for heavy jobs.
7. Avoid any pseudo-code; write full error handling and type-safety.

🔌 بناء واجهات برمجة التطبيقات

تسجيل نقرة إحالة واستخراج معرف التتبع

المسار: POST /api/v1/tracking/clicks

// Request Body
{
  "affiliate_code": "AFF1001",
  "merchant_slug": "tech-store-eg",
  "target_url": "https://store.example.com/product/laptop-pro"
}

// Response (200 OK)
{
  "success": true,
  "data": {
    "click_id": "YWZmMTAwMTpjMTJiYTM3YToxNzM2MTI0NDAwOmFiY2RlZjEyMzQ1Njc4OTA6YjM0ZjJhN2U",
    "redirect_url": "https://store.example.com/product/laptop-pro?aff_click_id=YWZmMTAwMTpjMTJiYTM3YToxNzM2MTI0NDAwOmFiY2RlZjEyMzQ1Njc4OTA6YjM0ZjJhN2U&aff_id=c12ba37a-514d-49d7-84ec-86bbd79b884d"
  }
}

استعلام رصيد المسوق اللحظي

المسار: GET /api/v1/affiliates/me/balance (المصادقة: Bearer JWT)

// Response (200 OK)
{
  "success": true,
  "data": {
    "currency": "EGP",
    "balance_available": 4500.00,
    "balance_pending": 1250.00,
    "total_withdrawn": 18200.00,
    "active_referral_links": 14,
    "last_payout_at": "2026-02-28T14:30:00Z"
  }
}

🔒 هندسة وتأمين خطافات الويب

تتطلب حماية الـ Webhooks ثلاث طبقات تحقق: فحص توقيع HMAC، والتأكد من حداثة الختم الزمني لمنع هجمات الإعادة، وفحص الـ Idempotency لمنع التكرار:

graph TD
    A[طلب Webhook وارد] --> B{فحص الختم الزمني < 300 ثانية؟}
    B -->|لا| E[رفض الطلب: 400 Bad Request]
    B -->|نعم| C{التحقق من توقيع HMAC}
    C -->|غير متطابق| F[رفض الطلب: 401 Unauthorized]
    C -->|متطابق| D{فحص مفتاح Idempotency في Redis}
    D -->|موجود مسبقاً| G[تجاهل المعالجة: 200 OK]
    D -->|جديد| H[حفظ المفتاح وتمرير الحدث للطابور]
الملف: src/webhooks/webhook-receiver.ts (TypeScript / Fastify)

import { FastifyRequest, FastifyReply } from 'fastify';
import crypto from 'crypto';
import Redis from 'ioredis';
import { Pool } from 'pg';

const redis = new Redis(process.env.REDIS_URL || 'redis://localhost:6379');
const pool = new Pool({ connectionString: process.env.DATABASE_URL });

export async function handleStoreWebhook(request: FastifyRequest, reply: FastifyReply) {
  const signature = request.headers['x-platform-signature'] as string;
  const timestamp = request.headers['x-platform-timestamp'] as string;
  const idempotencyKey = request.headers['x-idempotency-key'] as string;
  const merchantId = (request.params as { merchantId: string }).merchantId;

  if (!signature || !timestamp || !idempotencyKey) {
    return reply.status(400).send({ error: 'Missing security headers' });
  }

  const currentTime = Math.floor(Date.now() / 1000);
  if (Math.abs(currentTime - parseInt(timestamp, 10)) > 300) {
    return reply.status(400).send({ error: 'Request timestamp expired' });
  }

  const merchantRes = await pool.query('SELECT webhook_secret FROM merchants WHERE id = $1', [merchantId]);
  if (merchantRes.rows.length === 0) {
    return reply.status(404).send({ error: 'Merchant not found' });
  }
  const secret = merchantRes.rows[0].webhook_secret;

  const rawBody = JSON.stringify(request.body);
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(`${timestamp}.${rawBody}`)
    .digest('hex');

  const isValid = crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expectedSignature));
  if (!isValid) {
    return reply.status(401).send({ error: 'Invalid HMAC signature' });
  }

  const hasSeen = await redis.set(`idempotency:${idempotencyKey}`, 'processed', 'EX', 86400, 'NX');
  if (!hasSeen) {
    return reply.status(200).send({ success: true, message: 'Event already processed' });
  }

  await pool.query(
    `INSERT INTO webhook_events (merchant_id, event_id, event_type, idempotency_key, payload, status)
     VALUES ($1, $2, $3, $4, $5, 'received')`,
    [merchantId, idempotencyKey, (request.body as any).event, idempotencyKey, request.body]
  );

  await redis.lpush('queue:order_processing', JSON.stringify({ merchantId, payload: request.body }));

  return reply.status(200).send({ success: true, message: 'Webhook received successfully' });
}

🛍️ دمج WooCommerce والمتاجر الخارجية

يُوضع الكود المخصص التالي داخل ملف functions.php بمتجر ووكومرس أو ضمن إضافة مخصصة لالتقاط الكوكيز ومزامنة الطلبات:

الملف: wp-content/plugins/affiegy-wc-tracker/affiegy-wc-tracker.php (PHP)

<?php
if (!defined('ABSPATH')) exit;

class Affiegy_WC_Sync {
    private static $api_endpoint = 'https://api.affiegy-platform.com/api/v1/merchants/MERCHANT_UUID_HERE/webhooks/orders';
    private static $webhook_secret = 'SECURE_MERCHANT_SECRET_KEY_HERE';

    public static function init() {
        add_action('woocommerce_order_status_completed', [__CLASS__, 'dispatch_order_completed']);
        add_action('woocommerce_order_status_refunded', [__CLASS__, 'dispatch_order_refunded']);
        add_action('woocommerce_checkout_order_processed', [__CLASS__, 'attach_cookie_to_order_meta'], 10, 1);
    }

    public static function attach_cookie_to_order_meta($order_id) {
        if (isset($_COOKIE['aff_attribution'])) {
            $attribution_data = json_decode(stripslashes($_COOKIE['aff_attribution']), true);
            if (!empty($attribution_data['clickId'])) {
                update_post_meta($order_id, '_aff_click_id', sanitize_text_field($attribution_data['clickId']));
                update_post_meta($order_id, '_aff_affiliate_id', sanitize_text_field($attribution_data['affId']));
            }
        }
    }

    public static function dispatch_order_completed($order_id) {
        $order = wc_get_order($order_id);
        if (!$order) return;

        $click_id = get_post_meta($order_id, '_aff_click_id', true);
        if (empty($click_id)) return;

        $payload = [
            'event' => 'order.completed',
            'order_id' => (string)$order->get_id(),
            'click_id' => $click_id,
            'affiliate_id' => get_post_meta($order_id, '_aff_affiliate_id', true),
            'currency' => $order->get_currency(),
            'subtotal' => (float)$order->get_subtotal(),
            'tax' => (float)$order->get_total_tax(),
            'shipping' => (float)$order->get_shipping_total(),
            'total' => (float)$order->get_total(),
            'customer_phone' => $order->get_billing_phone(),
            'timestamp' => time()
        ];

        self::send_signed_payload($payload);
    }

    public static function dispatch_order_refunded($order_id) {
        $payload = [
            'event' => 'order.refunded',
            'order_id' => (string)$order_id,
            'timestamp' => time()
        ];
        self::send_signed_payload($payload);
    }

    private static function send_signed_payload($payload) {
        $json_payload = wp_json_encode($payload);
        $timestamp = time();
        $signature = hash_hmac('sha256', $timestamp . '.' . $json_payload, self::$webhook_secret);
        $idempotency_key = 'wc_' . $payload['order_id'] . '_' . $payload['event'] . '_' . $timestamp;

        wp_remote_post(self::$api_endpoint, [
            'headers' => [
                'Content-Type' => 'application/json',
                'X-Platform-Signature' => $signature,
                'X-Platform-Timestamp' => (string)$timestamp,
                'X-Idempotency-Key' => $idempotency_key,
            ],
            'body' => $json_payload,
            'timeout' => 15,
            'blocking' => false
        ]);
    }
}

Affiegy_WC_Sync::init();

💬 دمج WhatsApp API وأتمتة الإشعارات

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

graph TD
    A[تغير حالة الطلب إلى مكتمل] --> B[محرك العمولات: اعتماد العمولة]
    B --> C[وضع مهمة الإشعار بطابور BullMQ]
    C --> D[خدمة WhatsApp Integration Service]
    D --> E{فحص الرقم وتجنب الحظر}
    E -->|رقم موثوق + تأخير آمن| F[إرسال عبر Whats360 API]
    F --> G[تحديث جدول notifications بحالة الإرسال]
الملف: src/notifications/whatsapp-service.ts (Node.js / TypeScript)

import axios, { AxiosInstance } from 'axios';
import { Pool } from 'pg';

export interface WhatsAppNotificationPayload {
  recipientPhone: string;
  templateMessage: string;
  metadata?: Record;
}

export class WhatsAppNotificationService {
  private httpClient: AxiosInstance;
  private apiToken: string;
  private instanceId: string;
  private baseUrl: string;

  constructor(private pool: Pool) {
    this.apiToken = process.env.WHATS360_API_TOKEN || '';
    this.instanceId = process.env.WHATS360_INSTANCE_ID || '';
    this.baseUrl = process.env.WHATS360_BASE_URL || 'https://whats360.live/api/v1';

    this.httpClient = axios.create({
      baseURL: this.baseUrl,
      timeout: 10000,
    });
  }

  public async sendTextMessage(phone: string, message: string): Promise<{ success: boolean; messageId?: string; error?: string }> {
    try {
      const cleanPhone = phone.replace(/[^0-9]/g, '');
      const jid = `${cleanPhone}@s.whatsapp.net`;

      const response = await this.httpClient.get('/send-text', {
        params: {
          token: this.apiToken,
          instance_id: this.instanceId,
          jid: jid,
          msg: message,
        },
      });

      if (response.data && response.data.success) {
        await this.logNotification(cleanPhone, message, 'sent', response.data.response?.key?.id);
        return { success: true, messageId: response.data.response?.key?.id };
      } else {
        await this.logNotification(cleanPhone, message, 'failed', null);
        return { success: false, error: response.data?.error || 'Unknown API failure' };
      }
    } catch (error: any) {
      const errorMessage = error.response?.data?.error || error.message;
      await this.logNotification(phone, message, 'failed', null);

      if (error.response?.status === 463) {
        console.warn(`[WhatsApp API 463] Number ${phone} is not opened for chat or requires prior interaction.`);
      }

      return { success: false, error: errorMessage };
    }
  }

  public async notifyMerchantNewOrder(merchantPhone: string, merchantName: string, orderId: string, total: number, currency: string) {
    const message = `مرحباً يا ${merchantName} 🌟\nتم تسجيل طلب شراء جديد برقم (#${orderId}) في متجرك.\nإجمالي الطلب: ${total} ${currency}.\nيرجى مراجعة وتجهيز الشحنة عبر لوحة التحكم الخاصة بك.`;
    return this.sendTextMessage(merchantPhone, message);
  }

  public async notifyAffiliateCommissionApproved(affiliatePhone: string, affiliateName: string, amount: number, currency: string, newBalance: number) {
    const message = `أهلاً ${affiliateName} 🎉\nبشرى سارة! تم اعتماد عمولة بيع جديدة لك بقيمة: ${amount} ${currency}.\nرصيدك القابل للسحب الآن هو: ${newBalance} ${currency}.\nواصل الترويج عبر روابطك المخصصة!`;
    return this.sendTextMessage(affiliatePhone, message);
  }

  private async logNotification(phone: string, content: string, status: string, externalId: string | null) {
    await this.pool.query(
      `INSERT INTO notifications (channel, destination, message_content, external_message_id, delivery_status)
       VALUES ('whatsapp', $1, $2, $3, $4)`,
      [phone, content, externalId, status]
    );
  }
}

🛡️ أمان المنظومة ومكافحة الاحتيال والحظر

تتعرض شبكات التسويق بالعمولة لصور احتيال منظمة تهدف لسرقة العمولات أو تزييف المبيعات. يجب بناء خطوط دفاع هندسية صارمة تشمل:

🛡️ مكافحة احتيال النقرات (Click Fraud)

فحص تكرار النقرات من نفس الـ Subnet IP أو User-Agent خلال فواصل زمنية ضيقة وتوقيع الـ Click IDs المشفرة لمنع هجمات Cookie Stuffing.

⚡ حماية حسابات واتساب من الحظر

تطبيق تأخير إرسال عشوائي (Jittering) بين 5 و 15 ثانية، وتنويع النصوص، وتعديل بصمة الوسائط SHA-256 لمنع كشف السبام عبر منصة Whats360.

⏱️ طوابير العمليات ومعالجة الإخفاق والتكرار

تُدار التنبيهات ومعالجة مدفوعات العمولات بصورة غير متزامنة تماماً (Asynchronous) باستخدام مكتبة BullMQ ومحرك Redis لضمان استقرار الخادم:

graph LR
    A[حدث جديد] --> B[(Redis Stream / Queue)]
    B --> C[Worker Process]
    C -->|فشل معالجة| D{محاولة <= 5؟}
    D -->|نعم| E[تأخير تكراري Exponential Backoff]
    E --> B
    D -->|لا| F[طابور الرسائل الميتة DLQ]
    C -->|نجاح| G[تسجيل اكتمال العملية]
الملف: src/queues/order-worker.ts (BullMQ Worker)

import { Worker, Job } from 'bullmq';
import { CommissionEngine } from '../finance/commission-engine';
import { WhatsAppNotificationService } from '../notifications/whatsapp-service';
import { Pool } from 'pg';

const pool = new Pool({ connectionString: process.env.DATABASE_URL });
const commissionEngine = new CommissionEngine(pool);
const whatsappService = new WhatsAppNotificationService(pool);

export const orderWorker = new Worker(
  'order-processing-queue',
  async (job: Job) => {
    const { merchantId, payload } = job.data;

    if (payload.event === 'order.completed') {
      const commissionId = await commissionEngine.calculateAndRecordPendingCommission({
        orderId: payload.order_id,
        merchantId: merchantId,
        affiliateId: payload.affiliate_id,
        clickId: payload.click_id,
        subtotal: payload.subtotal,
        shipping: payload.shipping,
        tax: payload.tax,
        total: payload.total,
        commissionRate: 10,
        holdPeriodDays: 14,
      });

      await whatsappService.notifyMerchantNewOrder(
        payload.merchant_phone || '201000000000',
        'التاجر',
        payload.order_id,
        payload.total,
        payload.currency
      );

      await whatsappService.sendTextMessage(
        payload.affiliate_phone || '201111111111',
        `أهلاً بك! تم إسناد بيع جديد لطلبك رقم #${payload.order_id}. عمولتك المعلقة: ${(payload.subtotal * 0.1).toFixed(2)} ${payload.currency}.`
      );

      return { status: 'completed', commissionId };
    }

    if (payload.event === 'order.refunded') {
      const commRes = await pool.query('SELECT id FROM commissions WHERE order_id = $1 AND merchant_id = $2', [
        payload.order_id,
        merchantId,
      ]);
      if (commRes.rows.length > 0) {
        await commissionEngine.reverseCommission(commRes.rows[0].id, 'Customer Refund via Store Webhook');
      }
      return { status: 'reversed' };
    }
  },
  {
    connection: { host: 'localhost', port: 6379 },
    concurrency: 5,
    limiter: { max: 10, duration: 1000 },
    attempts: 5,
    backoff: {
      type: 'exponential',
      delay: 3000,
    },
  }
);

orderWorker.on('failed', (job, err) => {
  console.error(`[Job ${job?.id}] Failed with error: ${err.message}.`);
});

🎥 بطاقات الشروح المرئية التوضيحية

لتعميق الفهم التطبيقي والتنفيذي، تم إدراج الشروح المرئية التالية في مواضعها الهندسية المخصصة:

🧪 استراتيجيات الفحص والاختبارات الآلية

لا يمكن إطلاق نظام مالي دون اختبارات آلية تغطي السيناريوهات الحافة (Edge Cases) ومنع تكرار الحسابات:

الملف: tests/integration/affiliate-lifecycle.test.ts (Jest / Supertest Suite)

import request from 'supertest';
import { app } from '../../src/app';
import { Pool } from 'pg';

const pool = new Pool({ connectionString: process.env.TEST_DATABASE_URL });

describe('End-to-End Affiliate Multi-Vendor Lifecycle', () => {
  let merchantId: string;
  let affiliateId: string;
  let clickId: string;

  beforeAll(async () => {
    const mRes = await pool.query(
      "INSERT INTO merchants (business_name, slug, webhook_secret, api_key_hash) VALUES ('Test Store', 'test-store', 'test_secret_123', 'hash') RETURNING id"
    );
    merchantId = mRes.rows[0].id;

    const uRes = await pool.query(
      "INSERT INTO users (email, password_hash, full_name, role) VALUES ('aff@test.com', 'hash', 'Test Affiliate', 'affiliate') RETURNING id"
    );
    const aRes = await pool.query(
      "INSERT INTO affiliates (user_id, referral_code) VALUES ($1, 'TESTCODE') RETURNING id",
      [uRes.rows[0].id]
    );
    affiliateId = aRes.rows[0].id;
  });

  afterAll(async () => {
    await pool.query('DELETE FROM merchants WHERE id = $1', [merchantId]);
    await pool.end();
  });

  it('1. يجب أن يسجل النقرة وينشئ معرّف Click ID مشفر بنجاح', async () => {
    const res = await request(app.server)
      .post('/api/v1/tracking/clicks')
      .send({
        affiliate_code: 'TESTCODE',
        merchant_slug: 'test-store',
        target_url: 'https://teststore.com/item/1',
      });

    expect(res.status).toBe(200);
    expect(res.body.data).toHaveProperty('clickId');
    clickId = res.body.data.clickId;
  });

  it('2. يجب معالجة الـ Webhook واحتساب العمولة بدقة بدفتر الأستاذ', async () => {
    const orderPayload = {
      event: 'order.completed',
      order_id: 'ORDER_9999',
      click_id: clickId,
      affiliate_id: affiliateId,
      subtotal: 1000.0,
      shipping: 50.0,
      tax: 50.0,
      total: 1100.0,
      currency: 'EGP',
    };

    const timestamp = Math.floor(Date.now() / 1000).toString();
    const signature = require('crypto')
      .createHmac('sha256', 'test_secret_123')
      .update(`${timestamp}.${JSON.stringify(orderPayload)}`)
      .digest('hex');

    const res = await request(app.server)
      .post(`/api/v1/merchants/${merchantId}/webhooks/orders`)
      .set('X-Platform-Signature', signature)
      .set('X-Platform-Timestamp', timestamp)
      .set('X-Idempotency-Key', 'unique_test_order_9999')
      .send(orderPayload);

    expect(res.status).toBe(200);

    const affCheck = await pool.query('SELECT balance_pending FROM affiliates WHERE id = $1', [affiliateId]);
    expect(Number(affCheck.rows[0].balance_pending)).toBe(100.0);
  });

  it('3. يجب منع تكرار معالجة نفس الـ Webhook بناءً على مفتاح Idempotency', async () => {
    const orderPayload = { event: 'order.completed', order_id: 'ORDER_9999' };
    const timestamp = Math.floor(Date.now() / 1000).toString();
    const signature = require('crypto')
      .createHmac('sha256', 'test_secret_123')
      .update(`${timestamp}.${JSON.stringify(orderPayload)}`)
      .digest('hex');

    const res = await request(app.server)
      .post(`/api/v1/merchants/${merchantId}/webhooks/orders`)
      .set('X-Platform-Signature', signature)
      .set('X-Platform-Timestamp', timestamp)
      .set('X-Idempotency-Key', 'unique_test_order_9999')
      .send(orderPayload);

    expect(res.status).toBe(200);
    expect(res.body.message).toContain('already processed');

    const affCheck = await pool.query('SELECT balance_pending FROM affiliates WHERE id = $1', [affiliateId]);
    expect(Number(affCheck.rows[0].balance_pending)).toBe(100.0);
  });
});

🚀 إطلاق النسخة التجريبية الأولى (MVP)

مصفوفة إطلاق الـ MVP في 14 يوماً:

  • الأيام (1 – 3): تجهيز بيئة PostgreSQL على سحابة آمنة، تشغيل ملفات الـ DDL، وضبط إعدادات الـ RLS.
  • الأيام (4 – 7): برمجة محرك التتبع باستخدام Vibe Coding، ونشر إضافة WooCommerce في متاجر التجار المستهدفين.
  • الأيام (8 – 10): دمج حساب واتساب عبر Whats360 لربط جلسات الرسائل واختبار استقبال خطافات الويب للأوردرات.
  • الأيام (11 – 12): تشغيل طوابير Redis واختبار فترات الإسناد وتعديلات العملة.
  • الأيام (13 – 14): بدء الاختبارات الحية مع 3 تجار و 20 مسوقاً للتحقق من وصول الإشعارات وتوازن الدفاتر المحاسبية.

🧭 خريطة اتخاذ القرار: التطوير الذاتي أم التطوير المخصص

graph TD
    Start[بدء فكرة شبكة الأفلييت] --> Q1{هل تمتلك خبرة تقنية في إدارة خوادم ومعاملات PostgreSQL المالية؟}
    Q1 -->|نعم| Q2{هل حجم العمليات المتوقع أقل من 10,000 طلب شهرياً؟}
    Q1 -->|لا| DevAgency[الاستعانة بتطوير مخصص عبر خبراء BeInCode]
    Q2 -->|نعم| InHouse[بناء المنصة ذاتياً بالـ Vibe Coding وWhats360 API]
    Q2 -->|لا| DevAgency
    InHouse --> Finish[إطلاق المنصة وتشغيل الأتمتة اللحظية]
    DevAgency --> Finish
  • متى تطور النظام بنفسك (DIY Vibe Coding): إذا كنت مبرمجاً مطلعاً على هندسة البيانات وتستهدف اختبار فكرة السوق بعدد تجار ومسوقين محدود، وتعتمد على واجهات برمجة جاهزة ومستقرة للمراسلات مثل Whats360 للتخلص من تعقيدات خوادم الـ WebSockets والاتصال بواتساب.
  • متى تنتقل إلى التطوير المؤسسي المخصص: عند التوسع للتعامل مع مئات الآلاف من الزيارات اللحظية، وتطلب وجود بنية معقدة متعددة السيرفرات (Distributed Microservices)، وحلول دفع وتكاملات معقدة للمحافظ الرقمية المحلية وتسويات بنكية تلقائية، حيث توفر شركة Beincode الخبرة المتخصصة في هندسة المنظومات البرمجية الكبرى وتصميم وكلاء الذكاء الاصطناعي المؤسسيين (Enterprise AI Workflows) المخصصين لمتطلبات أعمالك.

هل تحتاج إلى بنية مخصصة لشبكتك بالكامل؟

فريق المهندسين في Beincode جاهز لبناء المعمارية المتكاملة مع الربط اللحظي بأنظمة الدفع والواتساب.

اطلب عرض سعر لتطوير المنصة مخصصة

❓ قسم الأسئلة الشائعة التقنية

هل يمكن لشبكة الأفلييت استخدام رقم هاتف واحد لإرسال تنبيهات جميع التجار والمسوقين؟

نعم برمجياً، ولكن الأفضل معمارياً هو تخصيص قناة أو رقم لكل تاجر (إذا رغب التاجر في أن تظهر رسائل مبيعاته باسم متجره)، أو استخدام رقم منصة مركزي موثق للإشعارات المالية العامة للمسوقين عبر ميزة تعدد الأجهزة (Multi-Device Management) المدعومة في منصات مثل Whats360 لتوزيع ثقل الإرسال ومنع الإغراق.

كيف يتعامل النظام إذا نقر العميل على رابط مسوق، ثم نقر بعد أسبوع على رابط مسوق آخر واشترى؟

يعتمد ذلك على نموذج الإسناد (Attribution Model) المعتمد في جدول حملة التاجر (affiliate_campaigns): إذا كان النموذج Last-Click Attribution (وهو الأكثر شيوعاً)، فإن محرك التتبع يحدث بيانات الـ Cookie المسجلة في متصفح الزائر بالـ Click ID الجديد، فتذهب كامل العمولة للمسوق الأخير. أما إذا كان النموذج First-Click Attribution، يفحص كود المتصفح وجود كوكي قديم؛ فإن وجده لا يستبدله، وتُسند العمولة للمسوق الأول تقديراً لجلب الزائر لأول مرة.

ما هو الحل التقني لمشكلة ظهور الخطأ 463 في واتساب عند إرسال الإشعارات؟

يحدث الخطأ 463 (Number Not Opened For Chat) عندما تحاول الأنظمة البرمجية إرسال رسائل آلية لرقم جديد كلياً لم يسبق له إجراء أي محادثة مع رقم المنصة، وهو قيد أمان داخلي في بروتوكول واتساب لمكافحة السبام. يُحل هذا العائق هندسياً عبر تقنية العكس الآلي (Reverse OTP / Handshake)؛ حيث يُطلب من المسوق أو العميل إرسال كود تفعيل قصير إلى واتساب المنصة أولاً لفتح قناة المحادثة (Handshake)، أو استخدام أدوات فحص الأرقام المسبقة واستبعاد الأرقام غير المسجلة قبل إطلاق الإشعارات.

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

إن بناء نظام أفلييت متعدد التجار ليس مجرد جمع لبعض الأكواد الجاهزة، بل هو هندسة دقيقة تجمع بين:

  1. قواعد بيانات علائقية متينة (PostgreSQL + RLS) تفصل ذمم التجار وتحمي الخصوصية.
  2. محرك إسناد واحتساب عمولات مزدوج القيد (Financial Ledger) يضمن اتزان الأرقام واستحالة التلاعب أو الازدواج.
  3. قنوات اتصال لحظية عالية الفتح عبر واتساب API باستخدام منصة Whats360 التي توفر بنية الـ Webhooks وإدارة الجلسات الآمنة دون تعقيدات وبأعلى معايير الحظر الصارمة.
  4. تسريع دورة البناء والتدقيق البرمجي عبر فايب كودنج (Vibe Coding)، مع الاعتماد على الشركاء التقنيين المتخصصين مثل Beincode عندما يحين وقت التوسع الضخم وبناء الأنظمة المؤسسية المصممة حسب الطلب.
خارطة العمل التنفيذية:
[1. نمذجة الجداول SQL] ➔ [2. بناء محرك الإسناد] ➔ [3. ربط الـ Webhooks] ➔ [4. دمج WhatsApp API] ➔ [5. الاختبارات والإطلاق]

ابدأ اليوم بتطبيق الهياكل البرمجية المرفقة

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

ابدأ تشغيل نظامك الآن عبر واتساب

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

الكلمات المفتاحية المستهدفة (Keywords Index)

بناء نظام أفلييت متعدد التجار, نظام تسويق بالعمولة متعدد التجار, إنشاء منصة أفلييت, برمجة نظام تسويق بالعمولة, Vibe Coding, Multi-Tenant Architecture, Affiliate Tracking System, Affiliate Commission Management, WhatsApp API Integration, Webhook Integration, REST API Development, WooCommerce API Integration.

الأسئلة الشائعة التي يجيب عنها المقال (FAQ Schema Ready Section)

  1. ما هو نظام الأفلييت متعدد التجار وكيف يختلف عن المتجر الفردي والماركت بليس؟
  2. كيف تضمن معمارية Multi-Tenant عزل بيانات التجار والمسوقين عبر PostgreSQL RLS؟
  3. ما هو الدور الهندسي لأسلوب Vibe Coding في تسريع برمجة محرك التتبع والإسناد؟
  4. كيف يتم احتساب العمولات بدقة واستبعاد الضرائب وتكاليف الشحن بدفتر الأستاذ المالي المزدوج؟
  5. ما هي الآلية البرمجية لتأمين خطافات الويب (Webhooks) ومنع هجمات الإعادة وتكرار العمولات (Idempotency)؟
  6. كيف يتم دمج WooCommerce برمجياً لالتقاط معرّف الإحالة وإرسال الطلبات المكتملة والمسترجعة؟
  7. كيف يتم إرسال إشعارات فورية للتجار والمسوقين عبر WhatsApp API دون التعرض للحظر أو الخطأ 463؟
  8. متى يجب الاعتماد على التطوير الذاتي ومتى يجب التوجه نحو التطوير المخصص عبر Beincode؟

🛠️ ملحق التطبيق الهندسي المتقدم: مسارات API، تكاملات Webhooks، وأتمتة المراسلات

يقدم هذا الملحق الفني مواصفات برمجية تفصيلية مكملة لما ورد في الدليل الرئيسي؛ يركز على بنية واجهات برمجة التطبيقات (REST Endpoints)، وتنسيقات الأحداث المشفرة لخطافات الويب (Webhook Payloads)، وطرق ضبط مصادقة JWT، وتدفق الإشعارات الآمن عبر بوابات واتساب لحماية المنظومة من ثغرات الحقن، والتكرار المالي، والحظر التشغيلي.

📌 مواصفة مسار احتساب العمولات عبر واجهة برمجة التطبيقات

المسار البرمجي: POST /api/v1/commissions/calculate
المصادقة والتصريح: يتطلب توكن موثق للتاجر أو النظام عبر Authorization: Bearer YOUR_JWT_TOKEN مع التحقق من صلاحية merchant_admin أو system_worker.
رؤوس الطلب (Headers): Content-Type: application/json و X-Idempotency-Key: YOUR_IDEMPOTENCY_KEY.

نموذج طلب احتساب العمولة (Request Body)

{
  "merchant_id": "c12ba37a-514d-49d7-84ec-86bbd79b884d",
  "order_id": "ORD-2026-9988",
  "click_id": "YWZmMTAwMTpjMTJiYTM3YToxNzM2MTI0NDAwOmFiY2RlZjEyMzQ1Njc4OTA6YjM0ZjJhN2U",
  "subtotal_amount": 1000.00,
  "shipping_amount": 50.00,
  "tax_amount": 50.00,
  "total_amount": 1100.00,
  "currency": "EGP",
  "items": [
    {
      "product_id": "prd-101",
      "quantity": 1,
      "unit_price": 1000.00,
      "is_commissionable": true
    }
  ]
}

نموذج استجابة احتساب العمولة (Response Body – 201 Created)

{
  "success": true,
  "status_code": 201,
  "data": {
    "commission_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "order_id": "ORD-2026-9988",
    "affiliate_id": "a98cb21c-43bb-4211-b112-9f01a1b2c3d4",
    "commissionable_base": 1000.00,
    "applied_rate_percentage": 10.00,
    "earned_commission": 100.00,
    "currency": "EGP",
    "status": "pending",
    "hold_until": "2026-03-20T12:00:00Z",
    "ledger_entry_id": "e31ba20a-11aa-4222-c333-8b01c2d3e4f5"
  }
}

نموذج الاستجابة عند حدوث خطأ تحقق (422 Unprocessable Entity)

{
  "success": false,
  "status_code": 422,
  "error": "Validation failed",
  "details": [
    {
      "field": "subtotal_amount",
      "message": "subtotal_amount must be greater than zero and equal to the sum of commissionable items."
    }
  ]
}

📦 حمولة حدث خطاف الويب الموحد (Webhook Payload – order.completed)

تُرسل هذه الحمولة بصيغة JSON من المتجر الإلكتروني إلى مسار الاستقبال المركزي على المنصة:

{
  "event": "order.completed",
  "event_id": "evt_ord_9988_comp",
  "timestamp": 1772884800,
  "tenant_id": "c12ba37a-514d-49d7-84ec-86bbd79b884d",
  "data": {
    "order_id": "ORD-2026-9988",
    "external_order_id": "12345",
    "click_id": "YWZmMTAwMTpjMTJiYTM3YToxNzM2MTI0NDAwOmFiY2RlZjEyMzQ1Njc4OTA6YjM0ZjJhN2U",
    "affiliate_id": "a98cb21c-43bb-4211-b112-9f01a1b2c3d4",
    "customer": {
      "first_name": "أحمد",
      "phone": "+201234567890"
    },
    "totals": {
      "subtotal": 1000.00,
      "shipping": 50.00,
      "tax": 50.00,
      "total": 1100.00,
      "currency": "EGP"
    }
  }
}
⚠️ تنبيه أمني بشأن التحقق من التوقيع (Signature Verification):

تختلف خوارزميات توقيع الرؤوس باختلاف مزود الخدمة؛ فعلى سبيل المثال تستخدم شوبيفاي هيدر X-Shopify-Hmac-SHA256 مشفرًا بصيغة Base64، بينما تعتمد ووكومرس هيدر X-WC-Webhook-Signature، وتعتمد واجهات الربط الداخلي المخصصة صيغة Hex. لا تطبق خوارزمية واحدة بصورة عشوائية، وتأكد من استخدام الدالة crypto.timingSafeEqual لمنع ثغرات التوقيت (Timing Attacks).

كود توثيق JWT وعزل المستأجر البرمجي (Node.js Middleware)

import { FastifyRequest, FastifyReply } from 'fastify';
import jwt from 'jsonwebtoken';

interface DecodedToken {
  userId: string;
  merchantId?: string;
  role: 'super_admin' | 'merchant_admin' | 'merchant_staff' | 'affiliate';
}

export async function verifyAuthAndTenant(request: FastifyRequest, reply: FastifyReply) {
  const authHeader = request.headers.authorization;
  if (!authHeader || !authHeader.startsWith('Bearer ')) {
    return reply.status(401).send({ error: 'Missing or malformed Authorization header' });
  }

  const token = authHeader.split(' ')[1];
  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET || 'SYS_SECRET') as DecodedToken;
    (request as any).user = decoded;

    // تثبيت هوية التاجر لضمان عدم تمرير استعلامات عابرة للمستأجرين
    if (decoded.role === 'merchant_admin' || decoded.role === 'merchant_staff') {
      if (!decoded.merchantId) {
        return reply.status(403).send({ error: 'Merchant context required for this role' });
      }
      (request as any).merchantId = decoded.merchantId;
    }
  } catch (err) {
    return reply.status(401).send({ error: 'Invalid or expired token' });
  }
}
💡 نصيحة تشغيلية لحماية واتساب من الحظر:

تجنب تشغيل أكثر من حملة أو خط إرسال لنفس الرقم في الوقت ذاته، وفعل دوماً قاطع الدائرة (Circuit Breaker) لإيقاف الحملات تلقائياً عند تسجيل 3 إلى 5 إخفاقات متتالية. تقدم منصة Whats360 نظاماً مدمجاً لتغيير بصمة الوسائط (Media Hash) عبر إضافة بايتات غير مرئية للملفات بحيث لا يتكرر توقيع SHA-256 بين المستقبلين.

مصفوفة مقارنة بوابات الإرسال (WhatsApp Channels Comparison)

الخاصية Meta Cloud API الرسمية جلسات الاتصال المباشر عبر Whats360
آلية التوصيل خوادم Meta Graph API السحابية اتصال مباشر للجلسة عبر رمز الاستجابة السريعة (QR)
متطلبات التوثيق سجل تجاري موثق وحساب مدير أعمال Meta بدون تعقيدات توثيق ورقية؛ ربط فوري خلال دقائق
هيكل التسعير رسوم متغيرة لكل نافذة محادثة (24 ساعة) اشتراك سحابي دوري بدون رسوم محادثة خفية
أتمتة المتاجر والـ Webhooks تتطلب خادم وسيط وموافقة مسبقة على القوالب قوالب حرة، خطافات ويب موجهة، وإشعارات للمتاجر

أسئلة بحث تقنية إضافية (Extended Technical FAQ)

السؤال: كيف يتصرف النظام عند تعطل بوابة واتساب أثناء تسجيل حركة بيع ناجحة؟

الإجابة: لا يتم إيقاف أو تعطيل تسجيل الطلب المالي؛ حيث يفصل النظام بين العمليات المحاسبية وعمليات التنبيه من خلال طابور مهام وسيط (Redis BullMQ). تُسجل العمولة في دفتر الأستاذ فوراً داخل معاملة PostgreSQL، ثم توضع مهمة إرسال التنبيه في الطابور مع سياسة إعادة محاولة تلقائية وتأخير تصاعدي (Exponential Backoff). في حال فشل الإرسال بعد 5 محاولات، تنقل المهمة إلى طابور الرسائل المتعثرة (Dead Letter Queue) لتسجيل سبب الإخفاق دون المساس ببيانات الطلب.

السؤال: كيف يُمنع احتساب العمولة مرتين إذا أعاد متجر التاجر إرسال حدث Webhook لنفس الطلب؟

الإجابة: يتم ذلك عبر تطبيق معيار فحص عدم التكرار (Idempotency Handling)؛ حيث يُنشئ متجر التاجر مفتاحاً فريداً لكل حدث (مثال: wc_ORD9988_completed_TIMESTAMP) ويُمرر في ترويسة الطلب X-Idempotency-Key. يفحص خادم الاستقبال وجود المفتاح في ذاكرة Redis المؤقتة؛ فإن وُجد، يرد الخادم بحالة 200 OK دون تنفيذ كود الاحتساب المالي. كما يضع جدول orders قيد تفرد علائقي UNIQUE(merchant_id, external_order_id) يمنع تكرار الإدخال على مستوى قاعدة البيانات.

السؤال: كيف يمكن معالجة تتبع الأفلييت إذا اشترى العميل من متصفح يمنع كوكيز الطرف الثالث؟

الإجابة: يتم الاعتماد على كوكيز الطرف الأول (First-Party Cookies) عبر تثبيت سكربت التتبع التابع للمنصة على نفس نطاق المتجر، مع تخزين معرف النقرة click_id محلياً داخل localStorage كطبقة احتياطية. عند الانتقال لصفحة إتمام الشراء، يُستخرج المعرف من التخزين المحلي ويُحقن مباشرة في بيانات الطلب التعريفية (Order Metadata) المرسلة عبر الـ Webhook من الخادم إلى الخادم (Server-to-Server Attribution)، مما يضمن استقرار التتبع حتى في متصفحات Safari وBrave ذات الحماية المرتفعة.

هل تريد استشارة متخصصة لضبط معمارية منصتك؟

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

تواصل مع الدعم الفني للاستشارات الهندسية

فهرس الكيانات والمصطلحات التقنية الإضافية

Fastify Route Handler, HMAC-SHA256, Idempotency Key, X-Platform-Signature, Timing Attacks, Dead Letter Queue, BullMQ Concurrency, Exponential Backoff, WhatsApp JID, Error 463 Handshake, Server-to-Server Tracking, First-Party Context, Redis Caching, Circuit Breaker Pattern.

استكشف المزيد في هذا التخصص عبر محرك البحث الداخلي

اترك تعليقاً

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