تابع wp_remote_post ابزار استاندارد وردپرس برای ارسال درخواست‌های HTTP POST به APIهای خارجی و منابع راه دور است. این تابع یک لایه انتزاعی روی cURL و سایر کتابخانه‌های HTTP ایجاد می‌کند و امکان ارسال داده، هدرهای احراز هویت و تنظیمات امنیتی را فراهم می‌سازد. استفاده درست از آن، از نبود داده در سمت سرور، خطاهای احراز هویت و رفتار غیرمنتظره در اتصال API جلوگیری می‌کند. اشتباهات رایجی مانند نبود بررسی is_wp_error، نبود timeout و نبود nonce می‌تواند به شکست درخواست و افت پایداری منجر شود. تسلط بر این تابع برای اتصال API ضروری است و در افزونه‌نویسی حرفه‌ای کاربرد گسترده دارد.

چرا ارسال POST به API حیاتی است؟

در بسیاری از سناریوهای توسعه وردپرس، تنها دریافت داده کافی نیست. باید داده‌ای را به سرویس خارجی ارسال کنید: ثبت سفارش در سیستم انبارداری، ارسال پیامک، ارسال داده به CRM، ثبت لید در سیستم فروش، ارسال فاکتور به سیستم حسابداری و بسیاری موارد دیگر. برای این ارتباطات، تابع wp_remote_post ابزار استاندارد وردپرس است. این تابع امکان ارسال داده با ساختار مشخص، هدرهای احراز هویت و تنظیمات دقیق امنیتی را فراهم می‌کند.

تابع wp_remote_post چیست؟

تابع wp_remote_post() یک تابع هسته وردپرس است که در فایل wp-includes/http.php تعریف شده است. این تابع یک درخواست HTTP POST به URL مشخص ارسال می‌کند و پاسخ را به‌شکل آرایه یا WP_Error برمی‌گرداند. در پشت صحنه، این تابع از WP_Http استفاده می‌کند که خودش از cURL یا Streams استفاده می‌کند. این لایه انتزاعی، امکان نوشتن کد مستقل از محیط سرور را فراهم می‌کند. نکته مهم این است که این تابع داده را در بدنه درخواست (Body) ارسال می‌کند و نه در URL. این رویکرد از افشای اطلاعات حساس در لاگ‌های سرور جلوگیری می‌کند.

امضای تابع و پارامترها

امضای این تابع به‌شکل زیر است:
function wp_remote_post( $url, $args = array() ) {
    $http = _wp_http_get_object();
    return $http->request( $url, $args );
}
پارامتر اول (url) آدرس کامل درخواست است. پارامتر دوم (args) آرایه‌ای از تنظیمات است. خروجی این تابع یا یک آرایه است (در حالت موفق)، یا یک شیء WP_Error در حالت خطا.

آرگومان‌های کلیدی args

پارامتر args می‌تواند شامل تنظیمات زیر باشد: - method: روش درخواست (پیش‌فرض POST است) - timeout: حداکثر زمان انتظار (پیش‌فرض ۵ ثانیه) - redirection: تعداد ریدایرکت‌های مجاز - headers: هدرهای HTTP به‌شکل آرایه - body: داده‌های ارسالی (آرایه یا رشته) - sslverify: بررسی گواهی SSL - user-agent: رشته User-Agent - blocking: اگر false باشد، منتظر پاسخ نمی‌ماند - cookies: کوکی‌ها به‌شکل آرایه - data_format: فرمت داده (پیش‌فرض query است) نمونه استفاده:
$response = wp_remote_post(
    'https://api.example.com/v1/orders',
    array(
        'timeout'     => 20,
        'headers'     => array(
            'Authorization' => 'Bearer ' . $api_token,
            'Content-Type'  => 'application/json',
            'Accept'        => 'application/json',
        ),
        'body'        => wp_json_encode( array(
            'customer_id' => $customer_id,
            'total'       => $order_total,
            'items'       => $order_items,
        ) ),
        'data_format' => 'body',
        'sslverify'   => true,
    )
);
نکته مهم: تنظیم data_format روی body باعث می‌شود وردپرس داده را به‌صورت خام ارسال کند. برای ارسال JSON، این تنظیم ضروری است.

ساختار body و انواع محتوا

پارامتر body می‌تواند در چند فرمت مختلف پاس داده شود: **آرایه برای فرم URL-Encoded**:
$response = wp_remote_post( $url, array(
    'body' => array(
        'name'  => 'علی',
        'email' => 'ali@example.com',
    ),
) );
در این حالت، وردپرس داده را به فرمت application/x-www-form-urlencoded ارسال می‌کند. **رشته JSON برای Content-Type: application/json**:
$response = wp_remote_post( $url, array(
    'headers'     => array( 'Content-Type' => 'application/json' ),
    'body'        => wp_json_encode( $payload ),
    'data_format' => 'body',
) );
**فایل برای Multipart**:
$response = wp_remote_post( $url, array(
    'body' => array(
        'file' => file_get_contents( $file_path ),
        'name' => 'document.pdf',
    ),
) );
نکته مهم: انتخاب ساختار درست بسیار مهم است. اگر API انتظار JSON دارد و شما فرم ارسال کنید، خطای ۴۰۰ می‌گیرید.

هدرهای احراز هویت

بسیاری از APIها نیاز به احراز هویت دارند. سه رویکرد رایج: **Bearer Token**:
'headers' => array(
    'Authorization' => 'Bearer ' . $token,
),
**Basic Auth**:
'headers' => array(
    'Authorization' => 'Basic ' . base64_encode( $username . ':' . $password ),
),
**API Key در هدر سفارشی**:
'headers' => array(
    'X-API-Key' => $api_key,
),
نکته امنیتی: همیشه از هدر برای ارسال اطلاعات حساس استفاده کنید، نه از URL یا پارامترهای body که در لاگ ذخیره می‌شوند.

بررسی is_wp_error

همانند wp_remote_get، بررسی is_wp_error در wp_remote_post ضروری است:
$response = wp_remote_post( $url, $args );

if ( is_wp_error( $response ) ) {
    error_log( 'API request failed: ' . $response->get_error_message() );
    return false;
}

$status = wp_remote_retrieve_response_code( $response );
if ( $status >= 400 ) {
    $body = wp_remote_retrieve_body( $response );
    $error_data = json_decode( $body, true );

    error_log( sprintf(
        'API returned error %d: %s',
        $status,
        isset( $error_data['message'] ) ? $error_data['message'] : 'Unknown error'
    ) );

    return false;
}

$body = wp_remote_retrieve_body( $response );
$data = json_decode( $body, true );

return $data;
نکته مهم: ثبت لاگ از خطاهای API در محیط تولید، امکان ردیابی مشکلات را فراهم می‌کند.

کاربردهای عملی در افزونه

ارسال سفارش به سیستم انبارداری:
function myplugin_sync_order_to_warehouse( $order_id ) {
    $order = wc_get_order( $order_id );
    if ( ! $order ) {
        return false;
    }

    $payload = array(
        'order_id'     => $order_id,
        'customer'     => array(
            'name'  => $order->get_billing_first_name() . ' ' . $order->get_billing_last_name(),
            'email' => $order->get_billing_email(),
        ),
        'items'        => array(),
        'total'        => $order->get_total(),
        'created_at'   => $order->get_date_created()->format( 'c' ),
    );

    foreach ( $order->get_items() as $item ) {
        $payload['items'][] = array(
            'sku'      => $item->get_product()->get_sku(),
            'quantity' => $item->get_quantity(),
            'price'    => $item->get_total(),
        );
    }

    $response = wp_remote_post(
        'https://warehouse.example.com/api/orders',
        array(
            'timeout'     => 30,
            'headers'     => array(
                'Authorization' => 'Bearer ' . get_option( 'myplugin_warehouse_token' ),
                'Content-Type'  => 'application/json',
            ),
            'body'        => wp_json_encode( $payload ),
            'data_format' => 'body',
        )
    );

    if ( is_wp_error( $response ) ) {
        update_post_meta( $order_id, '_warehouse_sync_status', 'failed' );
        return false;
    }

    $status = wp_remote_retrieve_response_code( $response );
    if ( 200 !== $status && 201 !== $status ) {
        update_post_meta( $order_id, '_warehouse_sync_status', 'failed' );
        return false;
    }

    update_post_meta( $order_id, '_warehouse_sync_status', 'success' );
    return true;
}
ارسال پیامک به مشتری:
function myplugin_send_sms( $phone, $message ) {
    $response = wp_remote_post(
        'https://api.sms-provider.com/v1/send',
        array(
            'timeout' => 10,
            'headers' => array(
                'Authorization' => 'Bearer ' . get_option( 'myplugin_sms_token' ),
            ),
            'body'    => array(
                'to'      => $phone,
                'message' => $message,
            ),
        )
    );

    if ( is_wp_error( $response ) ) {
        return false;
    }

    return 200 === wp_remote_retrieve_response_code( $response );
}
نکته مهم: عملیات ارسال به APIهای خارجی معمولاً طولانی است. برای جلوگیری از کند شدن سایت، بهتر است این عملیات را به پس‌زمینه منتقل کنید.

استراتژی Retry و پایداری

درخواست‌های API ممکن است به دلایل موقت شکست بخورند. استراتژی Retry با Backoff نمایی، پایداری را افزایش می‌دهد:
function myplugin_api_post_with_retry( $url, $args, $max_retries = 3 ) {
    $attempt = 0;

    while ( $attempt < $max_retries ) {
        $response = wp_remote_post( $url, $args );

        if ( ! is_wp_error( $response ) ) {
            $status = wp_remote_retrieve_response_code( $response );
            if ( $status < 500 ) {
                return $response;
            }
        }

        $attempt++;

        if ( $attempt < $max_retries ) {
            $delay = pow( 2, $attempt );
            sleep( $delay );
        }
    }

    return new WP_Error( 'api_max_retries', 'API request failed after retries' );
}
نکته مهم: Retry باید تنها برای خطاهای گذرا (خطاهای ۵xx) استفاده شود، نه برای خطاهای ۴xx که نشان‌دهنده مشکل در درخواست است.

نکات امنیتی و اشتباهات رایج

اشتباه اول، نبود بررسی is_wp_error است. بدون این بررسی، خطاهای شبکه به خطاهای Fatal تبدیل می‌شوند. اشتباه دوم، نبود timeout مناسب است. برای عملیات POST که داده سنگین دارند، timeout پیش‌فرض ۵ ثانیه ممکن است کافی نباشد. اشتباه سوم، استفاده از sslverify => false است. این تنظیم، امنیت را از بین می‌برد و سایت را در معرض MITM قرار می‌دهد. اشتباه چهارم، ارسال اطلاعات حساس در URL است. از هدر یا body استفاده کنید. اشتباه پنجم، نبود escape در خروجی پاسخ است. اگر پاسخ API در HTML چاپ می‌شود، باید با توابع escape عبور کند. اشتباه ششم، ذخیره توکن‌ها در فایل‌های عمومی است. توکن‌ها باید در options یا متغیرهای محیطی ذخیره شوند. اشتباه هفتم، نبود Rate Limiting است. درخواست‌های مکرر به API می‌تواند به بلاک شدن IP منجر شود. اشتباه هشتم، نبود لاگ‌گیری است. خطاهای API باید در لاگ سرور ثبت شوند.

تحلیل فنی پیشرفته

در نگاه مهندسی، تابع wp_remote_post() یک نقطه معماری در لایه HTTP Client است که بر چند جنبه از سیستم اثر می‌گذارد. لایه اول لایه Data Serialization است. این تابع امکان ارسال داده در فرمت‌های مختلف (query، body، JSON، multipart) را فراهم می‌کند. لایه دوم لایه Authentication است. ارسال هدرهای احراز هویت، امکان ارتباط امن با APIهای محافظت‌شده را فراهم می‌کند. لایه سوم لایه Idempotency است. درخواست‌های POST معمولاً غیر Idempotent هستند، بنابراین Retry باید با احتیاط انجام شود. برای عملیات حساس، باید Idempotency Key در هدر ارسال شود. لایه چهارم لایه Performance است. تنظیم blocking => false برای ارسال آتش و فراموش (Fire and Forget) مفید است. لایه پنجم لایه Error Handling است. تابع WP_Error امکان انتقال دقیق خطاها را فراهم می‌کند. لایه ششم لایه SSL Security است. بررسی گواهی SSL از افشای اطلاعات جلوگیری می‌کند. لایه هفتم لایه Observability است. لاگ‌گیری از درخواست‌ها و پاسخ‌ها امکان دیباگ را فراهم می‌کند. لایه هشتم لایه Testing است. Mock کردن pre_http_request امکان تست بدون درخواست واقعی را فراهم می‌کند. مفاهیم پایه‌ای HTTP POST در POST در ویکی‌پدیا توضیح داده شده است. برای مطالعه بیشتر روی توابع مرتبط، می‌توانید به راهنمای wp_remote_get، راهنمای wp_remote_request، راهنمای wp_send_json، راهنمای wp_send_json_success، راهنمای wp_send_json_error، راهنمای set_transient و راهنمای esc_html مراجعه کنید.

پرسش‌های پرتکرار

تفاوت wp_remote_post و wp_remote_get چیست؟ اولی داده را در body ارسال می‌کند و دومی در URL. چطور داده JSON ارسال کنیم؟ با Content-Type: application/json و data_format => 'body'. آیا می‌توان Retry را خودکار کرد؟ بله، با حلقه و backoff نمایی. چطور توکن را امن نگهداری کنیم؟ در options یا متغیرهای محیطی، نه در فایل‌های عمومی. آیا این تابع از HTTP/2 پشتیبانی می‌کند؟ در صورتی که cURL سرور پشتیبانی کند.

نتیجه و مسیر ادامه

تابع wp_remote_post() ابزار استاندارد وردپرس برای ارسال درخواست‌های HTTP POST است. استفاده درست از آن یعنی تنظیم timeout مناسب، ارسال هدرهای احراز هویت، بررسی is_wp_error، بررسی کد وضعیت، Retry هوشمند و لاگ‌گیری. اشتباه‌های کوچک در این تابع اغلب به شکست درخواست یا افشای اطلاعات منجر می‌شوند. اگر این تابع را در پروژه‌ای واقعی به کار برده‌اید و رفتار غیرمنتظره‌ای دیده‌اید — به‌خصوص در اتصال به APIهای خارجی یا در سناریوهای پرترافیک — تجربه‌تان می‌تواند راهگشای دیگران باشد. کدام بخش بیشترین زمان را از شما گرفت؟ دیدگاه خود را بنویسید.