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ماژول را در زمان رویداد wooplus_hub_ready راهاندازی کنید تا هسته آماده باشد.
- 2برای صفحه تنظیمات از الگوی Umbrella Tab بالا استفاده کنید تا با ظاهر استاندارد افزونه یکدست شود.
- 3تاریخ را با wooplus_gregorian_to_jalali (شمسی) و پول را با wc_price و ارز ووکامرس نمایش دهید.
- 4هر Secret را با WooPlus_Crypto ذخیره کنید؛ هرگز کلید را سختکد یا در مرورگر قرار ندهید.
- 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 تازه نیاز دارید، در برد عمومی درخواست دهید تا در نسخه بعد اضافه شود.
ثبت درخواست قابلیت