هُو الرَزاق
ووکامرس پلاس
خرید و قیمت‌ها

Developer Docs

ووکامرس پلاس را گسترش بده

یک سکوی توسعه‌پذیر بر پایه استانداردهای وردپرس. با Hookها (action/filter)، Eventها، REST و رابط Page Builder می‌توانید رفتار افزونه را تغییر دهید و قابلیت تازه بسازید — بدون دست‌زدن به هسته. همه مثال‌ها واقعی و آماده کپی‌اند.

۱) امنیت و دسترسی (Security & Access)

این بخش اول است چون مهم‌ترین است. هر افزونه‌ای که این Hookها را به کار می‌برد باید این قواعد را رعایت کند؛ در غیر این صورت یک حفره امنیتی در فروشگاه باز می‌شود.

Capability

هر اقدام مدیریتی را با current_user_can( 'manage_woocommerce' ) (یا قوی‌تر) گیت کنید. هرگز به نقش کاربر اعتماد نکنید و کم‌ترین سطح لازم را بخواهید (least privilege).

Nonce / CSRF

هر درخواست تغییر‌دهنده وضعیت را با check_ajax_referer یا wp_verify_nonce اعتبارسنجی کنید؛ سمت کلاینت با wp_create_nonce.

Sanitize + Escape

ورودی را پاک‌سازی (sanitize_text_field، absint، wp_kses_post) و خروجی را escape کنید (esc_html، esc_attr، esc_url). ورودی هیچ‌وقت امن نیست.

Secret

کلیدها و توکن‌ها را با WooPlus_Crypto رمزنگاری ذخیره کنید، سرویس بیرونی را سمت سرور proxy کنید تا Secret به مرورگر نرسد، و با transient نرخ را محدود کنید (rate-limit).

قالب امن یک اقدام مدیریتی:

add_action( 'wp_ajax_my_action', function () {
    check_ajax_referer( 'my_action' );                       // CSRF
    if ( ! current_user_can( 'manage_woocommerce' ) ) {      // capability
        wp_send_json_error( [ 'msg' => 'forbidden' ], 403 );
    }
    $value = sanitize_text_field( wp_unslash( $_POST['value'] ?? '' ) ); // sanitize
    // ... do the work ...
    wp_send_json_success( [ 'ok' => true ] );                // escaped/typed output
} );

۲) Hooks — Actions & Filters

قرارداد نام‌گذاری: wooplus_{module}_*. بیش از ۱۰۰ Hook در ماژول‌ها وجود دارد؛ نمونه‌های پرکاربرد در جدول زیر و مثال‌های کامل در ادامه.

هسته و رابط مدیریت
wooplus_hub_readyactionهاب آماده شد؛ نقطه راه‌اندازی ماژول وابسته.
wooplus_tools_umbrella_tabsfilterافزودن تب به «ابزارک‌ها» (slug => label).
wooplus_sales_tabs_extrafilterافزودن تب به آمبرلای فروش (حمل/پرداخت/بازارگاه).
wooplus_cf_settings_extraactionتزریق کارت تنظیمات به صفحه فیلدهای پرداخت.
wooplus_fp_settings_extraactionتزریق کارت تنظیمات به ماژول محافظت از فایل.
wooplus_orders_admin_enabledfilterروشن/خاموش بازطراحی صفحه سفارش‌ها.
سفارش، پرداخت و رویداد
wooplus_hub_eventactionگذرگاه رویداد مرکزی؛ موتور workflow هم به آن گوش می‌دهد.
wooplus_one_checkout_top / _bottomactionتزریق محتوا به تسویه‌حساب یک‌صفحه‌ای.
wooplus_subscription_created / _renewed / _cancelledactionچرخه عمر اشتراک.
wooplus_ticket_created / _replied / _sla_breachactionرویدادهای تیکتینگ.
wooplus_b2b_user_approved / _rejectedactionتایید/رد مشتری عمده.
wooplus_attribution_channelsfilterافزودن کانال منبع سفارش سفارشی.

مثال کامل: افزودن یک تب به «ابزارک‌ها» (Umbrella Tab)

دو گام: ۱) صفحه تنظیمات خود را به‌عنوان زیرمنوی (مخفی) منوی ووکامرس پلاس ثبت کنید؛ ۲) با filter همان slug را به‌عنوان تب معرفی کنید. آمبرلا، زیرمنوی مستقل را پنهان و به‌جایش تب نشان می‌دهد.

// 1) register your settings page under the WooPlus menu
add_action( 'admin_menu', function () {
    add_submenu_page(
        'wooplus-dashboard',          // WooPlus parent slug
        'My Tool', 'My Tool',
        'manage_woocommerce',          // capability (never weaker)
        'my-tool',                     // page slug
        'my_tool_render_page'          // render callback
    );
}, 99 );

// 2) surface that slug as a tab inside the «ابزارک‌ها» umbrella
add_filter( 'wooplus_tools_umbrella_tabs', function ( $tabs ) {
    $tabs['my-tool'] = 'ابزار من';     // slug => label
    return $tabs;
} );

مثال: تزریق کارت تنظیمات به یک ماژول موجود

add_action( 'wooplus_cf_settings_extra', function () {
    // یک <form> کاملا مستقل (action=admin-post) چاپ کنید — نه داخل فرم میزبان
    echo '<div class="card"><h2>تنظیمات من</h2> ... </div>';
} );

مثال: خاموش‌کردن بازطراحی صفحه سفارش‌ها

add_filter( 'wooplus_orders_admin_enabled', '__return_false' );

۳) Hub و Workflow — Events & Capabilities

ووکامرس پلاس یک «هاب» باز دارد: افزونه شما می‌تواند Event (رویداد) و Capability (قابلیت) ثبت کند تا کاربران آن‌ها را در موتور بصری «گردش‌کار» (بدون کد) به‌کار ببرند — یا با کد به Eventها گوش دهد.

یک Event ثبت و emit کنید

رویداد = اتفاقی که در افزونه شما می‌افتد و می‌تواند یک گردش‌کار را شروع کند. روی wooplus_hub_ready ثبت کنید:

add_action( 'wooplus_hub_ready', function () {
    if ( ! class_exists( 'WooPlus_Hub' ) ) { return; }

    WooPlus_Hub::register_event( [
        'id'     => 'myplugin.subscription_expired',
        'module' => 'myplugin',
        'label'  => __( 'اشتراک منقضی شد', 'myplugin' ),
        'schema' => [
            'user_id' => [ 'type' => 'int' ],
            'plan'    => [ 'type' => 'string' ],
        ],
    ] );
} );

// later, when it actually happens:
WooPlus_Hub::emit( 'myplugin.subscription_expired',
    [ 'user_id' => 42, 'plan' => 'gold' ], 'myplugin' );

// or just listen to any event (no registration needed):
add_action( 'wooplus_hub_event', function ( $id, $payload ) {
    if ( 'myplugin.subscription_expired' === $id ) { /* react */ }
}, 10, 2 );

یک Capability ثبت کنید (action گردش‌کار)

قابلیت = کاری که افزونه شما بلد است و کاربر می‌تواند در گردش‌کار صدایش بزند. ورودی/خروجی را اعلام و منطق را در callback بگذارید:

WooPlus_Hub::register_capability( [
    'id'           => 'myplugin.extend_subscription',
    'module'       => 'myplugin',
    'label'        => __( 'تمدید اشتراک', 'myplugin' ),
    'inputs'       => [
        'user_id' => [ 'type' => 'int',    'required' => true ],
        'days'    => [ 'type' => 'string', 'default'  => '30' ],
    ],
    'outputs'      => [ 'expires_at' => [ 'type' => 'string' ] ],
    'requires_cap' => 'manage_woocommerce',
    'callback'     => function ( $args ) {
        $uid  = (int) ( $args['user_id'] ?? 0 );
        $days = (int) ( $args['days'] ?? 30 );
        // ... your logic ...
        return [ 'expires_at' => '...' ];
    },
] );

امنیت: Capabilityهای حساس را قفل کنید

در زمینه صف/رویداد، requires_cap دور زده می‌شود. برای کارهایی که پول جابه‌جا می‌کنند یا وضعیت حساس را تغییر می‌دهند، فلگ sensitive را روشن و یک «گارد سخت» با ثابت wp-config.php بگذارید:

'sensitive' => true,
'callback'  => function ( $args ) {
    if ( ! ( defined( 'MYPLUGIN_ALLOW_AUTOPAY' ) && MYPLUGIN_ALLOW_AUTOPAY ) ) {
        return new WP_Error( 'locked', 'برای امنیت غیرفعال است؛ در wp-config.php فعال کنید.' );
    }
    // safe to proceed: validate amounts, no over-charge, idempotency ...
},
  • ورودی Capability را مثل ورودی کاربر بدانید: validate نوع/بازه، برای SQL از $wpdb->prepare.
  • برای HTTP خروجی، آدرس را با گارد SSRF اعتبارسنجی کنید (رد IP داخلی/متادیتا).
  • اسرار را با WooPlus_Crypto::encrypt() ذخیره کنید؛ برای عملیات پرخطر dry_run پیش‌فرض بگذارید.

یک نوع نود سفارشی بسازید (Custom Node)

اگر کار شما در قالب Capability نمی‌گنجد و یک منطق اجرایی کاملا تازه می‌خواهید، یک نوع نود جدید بسازید: موتور گردش‌کار برای هر گامی که نوعش را نشناسد این فیلتر را صدا می‌زند؛ کافی است یک «آرایه نتیجه» (دقیقا مثل گام‌های داخلی) برگردانید.

// node type "myplugin_score": runs whenever a step has type=myplugin_score
add_filter( 'wooplus_workflow_run_step_myplugin_score',
  function ( $result, $step, $results ) {
    if ( is_array( $result ) && isset( $result['status'] ) ) return $result;
    $inputs = $step['inputs'] ?? [];                  // resolve {{vars}} if needed
    $amount = (float) ( $inputs['amount'] ?? 0 );
    return [
      'status' => 'ok',                               // 'ok' | 'error' | 'wait'
      'output' => [ 'score' => (int) min( 100, floor( $amount / 100000 ) ) ],
    ];
  }, 10, 3
);

افزونه‌ی نمونه‌ی واقعی (قالب شروع)

یک افزونه‌ی کامل قابل‌نصب که هر سه راه را نشان می‌دهد: یک Event، دو Capability (با callback واقعی) و یک نوع نود سفارشی — همراه الگوی امنیتی nonce + capability. نصبش کنید، در «گردش‌کار» نودها و تریگر آن را ببینید، و از رویش شروع کنید.

دانلود افزونه‌ی نمونه

۴) فیلد سفارشی Checkout

نوع فیلد تازه را با filter استاندارد ووکامرس بسازید (همان روشی که فیلد «نقشه» map.ir ساخته شده). مقدار با name برابر key ذخیره می‌شود.

add_filter(
  'woocommerce_form_field_mytype',
  function ( $field, $key, $args, $value ) {
    ob_start(); ?>
    <p class="form-row">
      <label><?php echo esc_html( $args['label'] ); ?></label>
      <input name="<?php echo esc_attr( $key ); ?>"
             value="<?php echo esc_attr( $value ); ?>">
    </p>
    <?php return ob_get_clean();
  }, 10, 4
);

۵) Page Builder (Tools)

اگر WooPlus Builder فعال است، ابزار اختصاصی خود را در تب «ابزارها» ثبت کنید. اسکریپت را با hook سمت سرور wpb/editor/footer تزریق کنید.

// PHP: enqueue after the editor loads
add_action( 'wpb/editor/footer', function () { ?>
  <script>
  window.WPB.registerTool({
    id: 'my-tool', label: 'ابزار من', icon: 'bi-magic',
    onSelect() { /* build a widget or open a modal */ },
  });
  </script>
<?php } );

۶) REST API

ووکامرس پلاس namespaceهای wooplus/v1 و woocommerce-plus/v1 را دارد. route خود را با permission_callback ثبت کنید و سمت کلاینت header X-WP-Nonce را بفرستید.

add_action( 'rest_api_init', function () {
  register_rest_route( 'my-ns/v1', '/things', [
    'methods'  => 'POST',
    'permission_callback' =>
      fn() => current_user_can( 'manage_woocommerce' ),
    'callback' => 'my_things_handler',
  ] );
} );

۷) Secret و رمزنگاری

هر API key یا token را با WooPlus_Cryptoرمزنگاری‌شده ذخیره کنید. فقط سمت سرور decrypt کنید و هرگز در HTML/JS چاپ نکنید.

// store
$enc = WooPlus_Crypto::encrypt( $api_key );
update_option( 'my_key_enc', $enc );

// use (server-side only)
$key = WooPlus_Crypto::decrypt( get_option( 'my_key_enc' ) );
$res = wp_remote_post( $endpoint, [ 'headers' => [ 'x-api-key' => $key ] ] );

۸) افزودن ماژول سفارشی

  1. 1ماژول را در زمان رویداد wooplus_hub_ready راه‌اندازی کنید تا هسته آماده باشد.
  2. 2برای صفحه تنظیمات از الگوی Umbrella Tab بالا استفاده کنید تا با ظاهر استاندارد افزونه یکدست شود.
  3. 3تاریخ را با wooplus_gregorian_to_jalali (شمسی) و پول را با wc_price و ارز ووکامرس نمایش دهید.
  4. 4هر Secret را با WooPlus_Crypto ذخیره کنید؛ هرگز کلید را سخت‌کد یا در مرورگر قرار ندهید.
  5. 5برای هر اقدام: capability + nonce + sanitize/escape را رعایت کنید (بخش ۱).

۹) توسعه‌ی اپ موبایل (سرور-محور)

اپ مدیریت ووکامرس پلاس یک کلاینت عمومی و سرور-محور است: گرید ماژول‌ها از /app/modules پر می‌شود و صفحه‌ی تنظیمات به‌صورت خودکار از روی آپشن ماژول شما ساخته می‌شود. پس ماژول شما در اپ ظاهر و قابل‌تنظیم می‌شود بدون بازسازی یا انتشار مجدد اپ. (یک APK امضاشده و امن می‌ماند؛ افزونه نمی‌تواند کد نیتیو تزریق کند — فقط schema اعلام می‌کند.)

دو گام: ماژول را ثبت کنید (تا در گرید بیاید) و تنظیماتش را در آپشن wooplus_{key}_settings بگذارید (اپ آن‌ها را به فیلد ویرایش‌پذیر تبدیل می‌کند):

// 1) appear in the app's module grid (key MUST start with module_)
add_filter( 'wooplus_module_fields', function ( $f ) {
    $f['module_mycrm'] = 'اتصال CRM من';      // key => label
    return $f;
} );
add_filter( 'wooplus_module_descriptions', function ( $d ) {
    $d['module_mycrm'] = 'همگام‌سازی مشتریان با CRM.';
    return $d;
} );

// 2) the app AUTO-renders these as typed fields (toggle/number/text):
add_action( 'init', function () {
    if ( false === get_option( 'wooplus_mycrm_settings', false ) ) {
        add_option( 'wooplus_mycrm_settings', [
            'api_url'   => 'https://api.example.com',  // -> text
            'max_items' => 20,                          // -> number
            'auto_sync' => true,                        // -> toggle
        ] );
    }
} );
// The master on/off (module_mycrm) + these fields appear in the app's
// «ماژول‌ها» screen and POST back to /app/module-config. No app rebuild.

برای منطق اجرایی بیشتر (اکشن‌ها، اسکیمای گروه‌بندی‌شده) همان Capabilityها و رویدادهای بخش ۳ از اپ هم در دسترس‌اند. افزونه‌ی نمونه‌ی بالا این ماژول اپ را هم نشان می‌دهد.

Hookی که نیاز دارید نیست؟

سطح Hookها و Eventها مدام کامل‌تر می‌شود. اگر برای سناریوی خود به Hook، Event یا endpoint تازه نیاز دارید، در برد عمومی درخواست دهید تا در نسخه بعد اضافه شود.

ثبت درخواست قابلیت