مجله ایرانیکاسرورآموزش سرور، هاست، وردپرس و شبکه
آموزشی

چطور CRM را به ووکامرس وصل کنیم؟ ثبت خودکار مشتری و سفارش

اگر فروشگاه ووکامرسی دارید، اطلاعات مهم مشتری فقط نام و شماره تلفن او نیست. سفارش‌های قبلی، مبلغ خرید، محصول موردعلاقه، آخرین خرید، وضعیت سفارش و دفعات بازگشت مشتری همگی اطلاعاتی هستند که می‌توانند به…

چطور CRM را به ووکامرس وصل کنیم؟ ثبت خودکار مشتری و سفارش
خلاصه سریع این آموزش

اگر فروشگاه ووکامرسی دارید، اطلاعات مهم مشتری فقط نام و شماره تلفن او نیست. سفارش‌های قبلی، مبلغ خرید، محصول موردعلاقه، آخرین خرید، وضعیت سفارش و دفعات بازگشت مشتری همگی اطلاعاتی…

۱۴ دقیقه مطالعه ۰ دیدگاه ۱۹ مهر ۱۴۰۵ آخرین به‌روزرسانی

اگر فروشگاه ووکامرسی دارید، اطلاعات مهم مشتری فقط نام و شماره تلفن او نیست. سفارش‌های قبلی، مبلغ خرید، محصول موردعلاقه، آخرین خرید، وضعیت سفارش و دفعات بازگشت مشتری همگی اطلاعاتی هستند که می‌توانند به تیم فروش و پشتیبانی کمک کنند. CRM یا «سیستم مدیریت ارتباط با مشتری» جایی است که این اطلاعات را کنار هم قرار می‌دهد تا هر مشتری فقط یک سفارش ناشناس در WooCommerce نباشد.

در این آموزش یک اتصال عمومی و قابل توسعه بین WooCommerce و CRM می‌سازیم. WooCommerce هنگام ثبت یا تغییر سفارش، اطلاعات لازم را برای سرویس اتصال می‌فرستد؛ سرویس، مشتری را در CRM پیدا یا ایجاد می‌کند، سفارش را به فرصت فروش یا فعالیت مشتری متصل می‌کند و شناسه CRM را برای جلوگیری از ثبت تکراری نگه می‌دارد.

📌 نتیجه نهایی این آموزش: مشتری جدید یا قدیمی WooCommerce به Contact موجود در CRM متصل می‌شود، سفارش‌ها به همان مشتری اضافه می‌شوند، سفارش مهم یا پرداخت‌شده می‌تواند Deal/Opportunity بسازد و Webhook تکراری نیز رکورد دوم ایجاد نمی‌کند.

فهرست مطالب

CRM دقیقاً چه چیزی به WooCommerce اضافه می‌کند؟

WooCommerce برای مدیریت فروشگاه بسیار مناسب است، اما CRM هدف دیگری دارد. WooCommerce می‌گوید چه چیزی فروخته شده است؛ CRM کمک می‌کند بفهمیم به چه کسی فروخته‌ایم، ارتباط بعدی با او چه زمانی است و تیم فروش یا پشتیبانی چه سابقه‌ای از آن مشتری دارد.

نگاشت معمول WooCommerce به CRM
WooCommerce CRM هدف
Customer Contact پروفایل یکپارچه مشتری
Order Deal / Opportunity / Purchase ثبت ارزش و وضعیت خرید
Order Note Activity / Note تاریخچه ارتباط
Product / Category Interest / Tag شناخت علاقه مشتری
Order Status Pipeline Stage پیگیری مرحله فروش

معماری درست اتصال CRM و WooCommerce

برای اتصال حرفه‌ای بهتر است CRM را مستقیم به دیتابیس WordPress وصل نکنیم. ساختار داخلی ذخیره سفارش ممکن است تغییر کند و HPOS نیز دقیقاً نشان داده که وابستگی به جدول‌های قدیمی انتخاب خوبی نیست.

معماری پیشنهادی سه بخش دارد:

🔹 WooCommerce: منبع مشتری، سفارش، محصول و وضعیت پرداخت.

🔹 Connector یا سرویس واسط: اطلاعات را دریافت، پاک‌سازی، تطبیق و وارد صف می‌کند.

🔹 CRM: Contact، Deal، Activity و اطلاعات تیم فروش را نگه می‌دارد.

WooCommerce → Webhook → Queue → تطبیق مشتری → CRM → ذخیره CRM ID → WooCommerce

چرا Webhook و REST API را با هم استفاده می‌کنیم؟

Webhook برای خبرکردن CRM مناسب است. مثلاً وقتی سفارش ایجاد یا ویرایش می‌شود، WooCommerce خودش یک درخواست HTTP می‌فرستد. در نتیجه لازم نیست هر دقیقه هزاران سفارش را بررسی کنیم.

REST API برای دو کار دیگر مناسب است: Import اولیه مشتری‌ها و سفارش‌های قدیمی، و دریافت نسخه تازه یک سفارش وقتی Webhook رسیده است. Endpointهای جدید باید از مسیر /wp-json/wc/v3/ استفاده کنند.

⚠️ پیشنهاد معماری: Webhook را فقط «اعلان تغییر» در نظر بگیرید. برای عملیات مالی یا تصمیم مهم، Worker می‌تواند Order ID را دریافت و نسخه تازه سفارش را با REST API بخواند.

مرحله ۱: REST API Key بسازید

در پیشخوان وردپرس وارد مسیر زیر شوید:

WooCommerce → Settings → Advanced → REST API

یک Key با کاربر اختصاصی Integration بسازید. اگر Connector فقط داده WooCommerce را می‌خواند، دسترسی Read کافی است. اگر می‌خواهید CRM ID را به Order یا Customer برگردانید، به Write نیز نیاز خواهید داشت.

کلیدها شامل Consumer Key و Consumer Secret هستند و باید فقط سمت سرور ذخیره شوند.

curl -u "ck_REPLACE_ME:cs_REPLACE_ME" \
"https://shop.example.com/wp-json/wc/v3/orders?per_page=1"

اگر JSON سفارش را دریافت کردید، اتصال REST API درست است. خطای 401 معمولاً به Credential یا دسترسی کاربر API مربوط است.

مرحله ۲: Webhook سفارش را فعال کنید

از مسیر زیر وارد بخش Webhook شوید:

WooCommerce → Settings → Advanced → Webhooks

برای شروع دو Webhook کافی است:

🔹 Order created برای سفارش جدید.

🔹 Order updated برای تغییر وضعیت یا اطلاعات سفارش.

اگر ثبت‌نام کاربر بدون سفارش نیز برای CRM مهم است، Customer Created/Updated را هم اضافه کنید.

Delivery URL می‌تواند مثلاً این باشد:

https://crm-bridge.example.com/webhooks/woocommerce

برای Webhook یک Secret قوی تعیین کنید. WooCommerce بدنه درخواست را با HMAC-SHA256 امضا می‌کند و Signature را در Header می‌فرستد.

مرحله ۳: امضای Webhook را قبل از هر کاری بررسی کنید

هر کسی می‌تواند به URL عمومی Webhook درخواست POST بزند. بنابراین قبل از اعتماد به Order ID یا ایمیل مشتری باید Signature را بررسی کنیم.

<?php

$payload = file_get_contents(
    'php://input'
);

$signature =
    $_SERVER[
        'HTTP_X_WC_WEBHOOK_SIGNATURE'
    ] ?? '';

$secret = getenv(
    'WC_WEBHOOK_SECRET'
);

if ( ! $secret ) {
    http_response_code( 500 );
    exit( 'Secret not configured' );
}

$expected = base64_encode(
    hash_hmac(
        'sha256',
        $payload,
        $secret,
        true
    )
);

if (
    ! hash_equals(
        $expected,
        $signature
    )
) {
    http_response_code( 401 );
    exit( 'Invalid signature' );
}

$data = json_decode(
    $payload,
    true
);

if (
    ! is_array( $data ) ||
    empty( $data['id'] )
) {
    http_response_code( 400 );
    exit( 'Invalid payload' );
}

http_response_code( 200 );
echo 'accepted';

Endpoint باید سریع پاسخ بدهد. پردازش CRM را داخل همان Request طولانی نکنید؛ Payload را ذخیره یا وارد Queue کنید و پاسخ 2xx را سریع برگردانید.

مرحله ۴: جلوی ثبت دوباره Webhook را بگیرید

Webhook ممکن است دوباره ارسال شود. اگر هر بار یک Contact و Deal جدید بسازیم، CRM در مدت کوتاهی پر از رکورد تکراری می‌شود.

WooCommerce در Header شناسه Delivery را نیز ارسال می‌کند. آن را Unique ذخیره کنید:

CREATE TABLE woo_crm_events (
    id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    delivery_id VARCHAR(100) NOT NULL,
    topic VARCHAR(100) NOT NULL,
    woo_object_id BIGINT UNSIGNED NOT NULL,
    payload JSON NOT NULL,
    status VARCHAR(30) NOT NULL DEFAULT 'pending',
    attempts INT UNSIGNED NOT NULL DEFAULT 0,
    last_error TEXT NULL,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    processed_at TIMESTAMP NULL,
    UNIQUE KEY uniq_delivery (delivery_id),
    KEY idx_status (status),
    KEY idx_object (woo_object_id)
);

اگر همان Delivery ID دوباره رسید، سرور باید پاسخ موفق بدهد اما Event دوم نسازد.

مشتری را در CRM با چه کلیدی پیدا کنیم؟

این بخش مهم‌تر از خود API است. اگر معیار تطبیق اشتباه باشد، یک مشتری با چند Contact مختلف وارد CRM می‌شود.

اولویت پیشنهادی برای Match مشتری
اولویت شناسه توضیح
۱ CRM ID ذخیره‌شده مطمئن‌ترین اتصال برای مشتری قبلی
۲ Woo Customer ID برای مشتری عضو سایت
۳ ایمیل Normalizeشده مناسب برای حساب‌های مختلف با ایمیل ثابت
۴ شماره تلفن Normalizeشده مفید برای Guest Checkout

نام مشتری معیار مناسبی برای Match نیست. دو نفر ممکن است نام یکسان داشته باشند و یک مشتری نیز ممکن است نام خود را با املای متفاوت وارد کند.

شماره تلفن را قبل از CRM یکسان‌سازی کنید

مثلاً این سه مقدار ممکن است برای یک مشتری باشند:

09121234567
+989121234567
00989121234567

Connector باید قبل از جست‌وجوی CRM فرمت تلفن را استاندارد کند. برای مثال اگر بازار شما ایران است، همه شماره‌های موبایل را می‌توانید در قالب بین‌المللی +98… نگهداری کنید.

مرحله ۵: Order را به مدل عمومی CRM تبدیل کنید

هر CRM نام فیلدهای خودش را دارد. بهتر است Connector ابتدا WooCommerce را به یک مدل میانی تبدیل کند و بعد Adapter مخصوص هر CRM آن مدل را ارسال کند.

{
  "contact": {
    "woo_customer_id": 83,
    "email": "customer@example.com",
    "phone": "+989121234567",
    "first_name": "Ali",
    "last_name": "Ahmadi"
  },
  "deal": {
    "woo_order_id": 18425,
    "order_number": "18425",
    "status": "processing",
    "currency": "IRT",
    "total": "2450000",
    "payment_method": "bank-card"
  },
  "items": [
    {
      "product_id": 145,
      "variation_id": 0,
      "sku": "SKU-1001",
      "name": "Product A",
      "quantity": 2
    }
  ]
}

با این معماری، اگر امروز CRM اول و یک سال بعد CRM دیگری انتخاب کردید، بخش WooCommerce Connector تغییر زیادی نمی‌کند؛ فقط Adapter مقصد عوض می‌شود.

نمونه Upsert مشتری در CRM

Upsert یعنی «اگر مشتری وجود دارد به‌روزرسانی کن و اگر وجود ندارد بساز». API واقعی CRM شما ممکن است Endpoint و ساختار دیگری داشته باشد؛ کد زیر الگوی معماری است.

<?php

function crm_request(
    string $method,
    string $path,
    array $body = array()
): array {
    $base_url = rtrim(
        getenv( 'CRM_BASE_URL' ),
        '/'
    );

    $token = getenv(
        'CRM_API_TOKEN'
    );

    if ( ! $base_url || ! $token ) {
        throw new RuntimeException(
            'CRM configuration is missing.'
        );
    }

    $ch = curl_init(
        $base_url . $path
    );

    curl_setopt_array(
        $ch,
        array(
            CURLOPT_CUSTOMREQUEST =>
                $method,
            CURLOPT_RETURNTRANSFER =>
                true,
            CURLOPT_HTTPHEADER =>
                array(
                    'Authorization: Bearer ' .
                        $token,
                    'Content-Type: application/json',
                ),
            CURLOPT_TIMEOUT => 20,
            CURLOPT_CONNECTTIMEOUT => 5,
        )
    );

    if ( ! empty( $body ) ) {
        curl_setopt(
            $ch,
            CURLOPT_POSTFIELDS,
            json_encode(
                $body,
                JSON_UNESCAPED_UNICODE
            )
        );
    }

    $response = curl_exec( $ch );

    if ( false === $response ) {
        throw new RuntimeException(
            curl_error( $ch )
        );
    }

    $status = curl_getinfo(
        $ch,
        CURLINFO_HTTP_CODE
    );

    curl_close( $ch );

    if (
        $status < 200 ||
        $status >= 300
    ) {
        throw new RuntimeException(
            'CRM returned HTTP ' .
            $status
        );
    }

    $data = json_decode(
        $response,
        true
    );

    return is_array( $data )
        ? $data
        : array();
}

Token CRM نیز مانند WooCommerce Secret باید فقط سمت سرور نگهداری شود؛ نه داخل JavaScript، مخزن عمومی Git یا Log قابل مشاهده کاربران.

سفارش Guest Checkout را فراموش نکنید

همه خریداران WooCommerce الزاماً Customer ID ندارند. در Guest Checkout مقدار Customer ID ممکن است صفر باشد، اما Billing Email و Billing Phone وجود داشته باشد.

پس Connector نباید شرط بگذارد که «اگر Customer ID صفر بود مشتری را Sync نکن». Guest نیز باید با ایمیل یا تلفن به Contact موجود وصل شود.

Deal را برای کدام سفارش‌ها بسازیم؟

لازم نیست هر Order Draft یا Failed وارد Pipeline فروش شود. سیاست CRM را براساس نیاز تیم فروش تعریف کنید.

نمونه سیاست وضعیت سفارش
وضعیت WooCommerce رفتار CRM
pending Lead یا Deal باز؛ در صورت نیاز به پیگیری پرداخت
processing Deal موفق یا در حال تحویل طبق فرایند شما
completed Closed Won / خرید تکمیل‌شده
cancelled Closed Lost یا Cancelled
refunded Refund Activity و اصلاح ارزش Deal

این جدول یک نمونه است. CRM شما ممکن است Pipeline فروش، خدمات پس از فروش یا Customer Success جدا داشته باشد.

CRM ID را به WooCommerce برگردانید

بعد از ایجاد Contact در CRM، شناسه آن را نگه دارید. برای مشتری عضو می‌توانید CRM ID را روی Customer Metadata و برای Guest روی Order Metadata ذخیره کنید.

مزیت این کار این است که Event بعدی مجبور نیست دوباره CRM را با ایمیل جست‌وجو کند.

{
  "meta_data": [
    {
      "key": "_crm_contact_id",
      "value": "CRM-84712"
    }
  ]
}

اگر CRM ID را فقط در دیتابیس Connector نگه می‌دارید نیز مشکلی نیست؛ مهم این است که یک Mapping پایدار داشته باشید.

Import مشتری‌ها و سفارش‌های قدیمی

Webhook فقط اتفاق‌های آینده را می‌بیند. اگر فروشگاه سه سال سابقه دارد، قبل از فعال‌سازی Realtime Sync باید اطلاعات تاریخی را Import کنید.

REST API را صفحه‌بندی کنید:

GET /wp-json/wc/v3/customers?per_page=100&page=1
GET /wp-json/wc/v3/customers?per_page=100&page=2

GET /wp-json/wc/v3/orders?per_page=100&page=1
GET /wp-json/wc/v3/orders?per_page=100&page=2

در Import ابتدا Contactها را Upsert کنید و سپس Orderها را به Contact مربوط وصل کنید. Import تاریخی و Webhook زنده نیز باید از همان قواعد Idempotency استفاده کنند.

Queue و Retry؛ اتصال CRM بدون این دو شکننده است

ممکن است CRM پنج دقیقه از دسترس خارج شود یا Rate Limit داشته باشد. در این حالت نباید Event مشتری از بین برود.

رویداد را در Queue نگه دارید و در صورت خطا با فاصله افزایشی دوباره امتحان کنید؛ برای مثال ۱ دقیقه، ۵ دقیقه، ۱۵ دقیقه و یک ساعت. بعد از تعداد مشخصی شکست، Event را به Failed Queue بفرستید تا اپراتور بررسی کند.

Connector CRM را روی خود هاست فروشگاه اجرا کنیم؟

برای فروشگاه کم‌ترافیک، یک افزونه ساده ممکن است کافی باشد. اما اگر Queue، Retry، چند CRM، Import تاریخی یا پردازش سنگین دارید، جداکردن Connector روی VPS باعث می‌شود اختلال CRM مستقیماً PHP Workerهای فروشگاه و Checkout را اشغال نکند.

تماس با پشتیبانی ایرانیکاسرور: 021-91302467

مانیتورینگ Webhook را فراموش نکنید

WooCommerce برای Webhook لاگ تحویل دارد، اما بهتر است Endpoint Connector را نیز مانیتور کنید. اگر DNS، SSL یا Backend دچار مشکل شود، باید قبل از پرشدن Queue متوجه شوید.

WooCommerce بعد از چند Delivery ناموفق پیاپی می‌تواند Webhook را غیرفعال کند؛ بنابراین فقط Queue سمت CRM را نگاه نکنید و وضعیت خود Webhook را نیز کنترل کنید.

اطلاعات بازاریابی را با اطلاعات سفارش قاطی نکنید

وجود ایمیل مشتری در یک سفارش به این معنی نیست که می‌توانید بدون توجه به سیاست حریم خصوصی او را وارد هر کمپین تبلیغاتی کنید. اطلاعات لازم برای سفارش، پشتیبانی و CRM عملیاتی با رضایت بازاریابی یک مفهوم نیست.

اگر در Checkout گزینه عضویت خبرنامه یا رضایت بازاریابی دارید، آن مقدار را به‌عنوان فیلد جدا در CRM Sync کنید. خودتان از وجود Order نتیجه نگیرید که Marketing Consent فعال است.

چه اطلاعاتی را واقعاً به CRM بفرستیم؟

هر چیزی که WooCommerce دارد لازم نیست وارد CRM شود. انتقال بی‌دلیل همه Metaها هم هزینه API را بالا می‌برد و هم اطلاعات حساس بیشتری پخش می‌کند.

حداقل داده کاربردی برای بیشتر CRMها
بخش فیلدها
مشتری نام، ایمیل، تلفن، Customer ID
سفارش Order ID، شماره سفارش، وضعیت، مبلغ و ارز
محصول نام، SKU، Category، Quantity
رفتار خرید آخرین خرید، تعداد سفارش و مجموع خرید در صورت نیاز
Consent رضایت بازاریابی در صورت وجود و ثبت واقعی

خطاهای رایج اتصال CRM به WooCommerce

برای هر سفارش Contact جدید می‌سازیم

قبل از Create باید CRM ID، Customer ID، ایمیل و تلفن بررسی شوند. هدف یک Contact با چند Purchase است، نه چند Contact برای یک نفر.

Webhook را داخل همان Request کامل پردازش می‌کنیم

اگر API CRM کند باشد، WooCommerce پاسخ دیر دریافت می‌کند. Event را Queue کنید و سریع 2xx برگردانید.

Signature را بررسی نمی‌کنیم

در این حالت هر درخواست جعلی می‌تواند مشتری یا Deal داخل CRM بسازد.

Guest Checkout را حذف می‌کنیم

Customer ID صفر به معنی نبود مشتری نیست. Billing Email و Phone را نیز برای Match در نظر بگیرید.

CRM API Token را داخل افزونه عمومی یا JavaScript می‌گذاریم

Secretها باید سمت سرور و ترجیحاً خارج از Source Code نگهداری شوند.

Marketing Consent را از وجود سفارش حدس می‌زنیم

اطلاعات تراکنشی و رضایت تبلیغاتی را جدا نگه دارید و فقط Consent واقعی را Sync کنید.

آزمایش اتصال قبل از انتشار

سناریوهای ضروری
سناریو نتیجه مورد انتظار
مشتری جدید یک Contact جدید ساخته شود.
مشتری قدیمی Contact موجود Update شود، نه Create.
Guest Checkout با ایمیل یا تلفن Match شود.
Webhook تکراری Event دوم رکورد تکراری نسازد.
CRM Down Event در Queue باقی بماند و Retry شود.
Refund Activity و مبلغ Deal طبق سیاست CRM اصلاح شود.
Signature جعلی درخواست با 401 رد شود.

پرسش‌های متداول

برای اتصال CRM به WooCommerce حتماً افزونه لازم است؟

خیر. WooCommerce REST API و Webhook داخلی دارد و می‌توان یک Connector مستقل ساخت. افزونه آماده زمانی مناسب است که CRM شما Integration رسمی و کافی داشته باشد.

Webhook بهتر است یا REST API؟

این دو مکمل‌اند. Webhook تغییر را اعلام می‌کند و REST API برای Import قدیمی، بازیابی جزئیات و Sync اصلاحی مناسب است.

چطور مشتری تکراری در CRM نسازیم؟

CRM ID قبلی، Woo Customer ID، ایمیل و تلفن استانداردشده را به‌ترتیب بررسی و عملیات را به شکل Upsert اجرا کنید.

آیا سفارش Guest هم وارد CRM شود؟

در بیشتر فروشگاه‌ها بله. Guest نیز مشتری واقعی است و می‌توان او را با ایمیل یا تلفن Match کرد.

اگر CRM موقتاً قطع شود چه می‌شود؟

Webhook نباید از بین برود. Event را در Queue نگه دارید و با Retry دوباره ارسال کنید.

آیا اطلاعات همه Metaهای WooCommerce را به CRM بفرستیم؟

خیر. فقط داده‌ای را Sync کنید که برای فروش، پشتیبانی یا تحلیل مشتری لازم است. انتقال بی‌هدف داده حساس ریسک و پیچیدگی اتصال را بالا می‌برد.

منابع رسمی این آموزش

🔹 WooCommerce REST API — مرجع رسمی API برای Orders، Customers و سایر داده‌های فروشگاه.

🔹 WooCommerce REST API v3 — نسخه فعلی و توصیه‌شده برای Integrationهای جدید.

🔹 WooCommerce API Authentication — روش ساخت و استفاده امن از Consumer Key و Consumer Secret.

🔹 WooCommerce Webhooks — مرجع ایجاد Webhook، Topicها، Delivery URL و لاگ تحویل.

🔹 WooCommerce Webhook API — مرجع HMAC-SHA256، Signature و مدیریت Webhook.

🔹 WooCommerce 11.2.1 Release Notes — نسخه پایدار بررسی‌شده هنگام نگارش مقاله.

جمع‌بندی

اتصال CRM به WooCommerce فقط ارسال نام و ایمیل مشتری نیست. اتصال قابل اعتماد باید مشتری را بدون ساخت رکورد تکراری Match کند، سفارش و Refund را به همان Contact وصل کند، Webhook را با Signature تأیید کند، Eventها را در Queue نگه دارد و برای خطاهای CRM Retry داشته باشد. Webhook برای تغییرات لحظه‌ای و REST API v3 برای Import و بازیابی جزئیات بهترین ترکیب عمومی است. اگر Connector را از خود فروشگاه جدا می‌کنید، Credentialها را فقط سمت سرور نگه دارید و رضایت بازاریابی را نیز از اطلاعات تراکنشی جدا کنید.

برای اجرای Connector CRM روی سرور جدا کمک می‌خواهید؟

اگر اتصال شما Queue، Webhook، Import قدیمی یا API چند سرویس دارد، اجرای Connector روی VPS می‌تواند فشار پردازش و خطای سرویس خارجی را از خود WooCommerce جدا کند. برای بررسی Nginx، PHP، Queue Worker یا SSL نیز می‌توانید درخواست کانفیگ ثبت کنید.

تماس با پشتیبانی ایرانیکاسرور: 021-91302467

اشتراک‌گذاری مقاله
گفت‌وگو درباره آموزش

دیدگاه‌ها (۰)

هنوز دیدگاهی ثبت نشده است.

دیدگاه یا سؤال خود را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *