文章目录[隐藏]
WordPress文创商品柔性库存共享插件开发指南
引言:文创商品库存管理的挑战与机遇
在文创产业蓬勃发展的今天,许多文创品牌面临着库存管理的双重挑战:一方面需要避免库存积压造成的资金压力,另一方面又担心缺货错失销售机会。传统的库存管理模式往往僵化,无法适应文创商品销售波动大、季节性强的特点。
柔性库存共享机制为解决这一难题提供了创新思路。通过建立多店铺、多渠道间的库存共享网络,文创商家可以实现库存的动态调配,提高库存周转率,降低运营成本。本文将详细介绍如何开发一个WordPress文创商品柔性库存共享插件,帮助文创品牌实现智能化的库存管理。
插件架构设计
核心功能模块
我们的插件将包含以下核心模块:
- 库存共享网络管理
- 实时库存同步系统
- 智能库存分配算法
- 订单与库存联动机制
- 数据统计与分析面板
数据库设计
首先,我们需要设计插件的数据表结构:
/**
* 创建插件所需的数据表
* 这段代码应该放在插件的激活钩子中执行
*/
function wc_flexible_inventory_create_tables() {
global $wpdb;
$charset_collate = $wpdb->get_charset_collate();
// 库存共享网络表
$network_table = $wpdb->prefix . 'wc_flex_inventory_network';
$network_sql = "CREATE TABLE IF NOT EXISTS $network_table (
network_id bigint(20) NOT NULL AUTO_INCREMENT,
store_name varchar(200) NOT NULL,
store_url varchar(500) NOT NULL,
api_key varchar(100) NOT NULL,
status enum('active','inactive','pending') DEFAULT 'pending',
inventory_share_percentage int(3) DEFAULT 100,
created_at datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (network_id),
UNIQUE KEY store_url (store_url(191))
) $charset_collate;";
// 共享库存记录表
$inventory_table = $wpdb->prefix . 'wc_flex_inventory_records';
$inventory_sql = "CREATE TABLE IF NOT EXISTS $inventory_table (
record_id bigint(20) NOT NULL AUTO_INCREMENT,
product_id bigint(20) NOT NULL,
variant_id bigint(20) DEFAULT 0,
network_store_id bigint(20) NOT NULL,
shared_quantity int(11) NOT NULL DEFAULT 0,
reserved_quantity int(11) NOT NULL DEFAULT 0,
last_synced datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (record_id),
KEY product_id (product_id),
KEY network_store_id (network_store_id)
) $charset_collate;";
// 库存分配日志表
$allocation_table = $wpdb->prefix . 'wc_flex_inventory_allocations';
$allocation_sql = "CREATE TABLE IF NOT EXISTS $allocation_table (
allocation_id bigint(20) NOT NULL AUTO_INCREMENT,
order_id bigint(20) NOT NULL,
product_id bigint(20) NOT NULL,
allocated_store_id bigint(20) NOT NULL,
allocated_quantity int(11) NOT NULL,
allocation_type enum('auto','manual','emergency') DEFAULT 'auto',
created_at datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (allocation_id),
KEY order_id (order_id)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($network_sql);
dbDelta($inventory_sql);
dbDelta($allocation_sql);
}
核心功能实现
1. 库存共享网络管理模块
/**
* 库存共享网络管理类
* 负责处理店铺的加入、审核和管理
*/
class WC_Flexible_Inventory_Network {
private $db;
public function __construct() {
global $wpdb;
$this->db = $wpdb;
}
/**
* 添加新店铺到共享网络
* @param array $store_data 店铺数据
* @return int|false 成功返回店铺ID,失败返回false
*/
public function add_store_to_network($store_data) {
$required_fields = ['store_name', 'store_url', 'contact_email'];
foreach ($required_fields as $field) {
if (empty($store_data[$field])) {
return false;
}
}
// 生成API密钥
$api_key = $this->generate_api_key();
$table_name = $this->db->prefix . 'wc_flex_inventory_network';
$result = $this->db->insert(
$table_name,
[
'store_name' => sanitize_text_field($store_data['store_name']),
'store_url' => esc_url_raw($store_data['store_url']),
'api_key' => $api_key,
'contact_email' => sanitize_email($store_data['contact_email']),
'inventory_share_percentage' => isset($store_data['share_percentage']) ?
intval($store_data['share_percentage']) : 100,
'status' => 'pending'
],
['%s', '%s', '%s', '%s', '%d', '%s']
);
if ($result) {
$store_id = $this->db->insert_id;
// 发送审核通知邮件
$this->send_approval_notification($store_data, $store_id);
return $store_id;
}
return false;
}
/**
* 生成唯一的API密钥
* @return string 生成的API密钥
*/
private function generate_api_key() {
return 'wc_flex_' . md5(uniqid() . microtime() . wp_rand());
}
/**
* 发送审核通知邮件
*/
private function send_approval_notification($store_data, $store_id) {
$admin_email = get_option('admin_email');
$subject = '新的库存共享网络加入申请';
$message = "有新的店铺申请加入库存共享网络:nn";
$message .= "店铺名称:" . $store_data['store_name'] . "n";
$message .= "店铺网址:" . $store_data['store_url'] . "n";
$message .= "联系邮箱:" . $store_data['contact_email'] . "n";
$message .= "申请时间:" . current_time('mysql') . "nn";
$message .= "请登录管理后台审核此申请。n";
$message .= "审核链接:" . admin_url('admin.php?page=wc-flex-inventory&action=review&id=' . $store_id);
wp_mail($admin_email, $subject, $message);
}
}
2. 实时库存同步系统
/**
* 实时库存同步管理器
* 负责处理不同店铺间的库存同步
*/
class WC_Flexible_Inventory_Sync {
private $db;
public function __construct() {
global $wpdb;
$this->db = $wpdb;
add_action('wc_flex_inventory_sync_cron', [$this, 'sync_inventory_across_network']);
}
/**
* 同步网络中的库存数据
*/
public function sync_inventory_across_network() {
// 获取所有活跃的网络店铺
$network_table = $this->db->prefix . 'wc_flex_inventory_network';
$active_stores = $this->db->get_results(
"SELECT * FROM $network_table WHERE status = 'active'"
);
foreach ($active_stores as $store) {
$this->sync_with_store($store);
}
}
/**
* 与特定店铺同步库存
* @param object $store 店铺对象
*/
private function sync_with_store($store) {
// 构建API请求
$api_url = trailingslashit($store->store_url) . 'wp-json/wc-flex-inventory/v1/inventory';
$response = wp_remote_get($api_url, [
'headers' => [
'Authorization' => 'Bearer ' . $store->api_key,
'Content-Type' => 'application/json'
],
'timeout' => 30
]);
if (is_wp_error($response)) {
error_log('库存同步失败: ' . $response->get_error_message());
return;
}
$inventory_data = json_decode(wp_remote_retrieve_body($response), true);
if ($inventory_data && isset($inventory_data['inventory'])) {
$this->update_local_inventory_records($store->network_id, $inventory_data['inventory']);
}
}
/**
* 更新本地库存记录
*/
private function update_local_inventory_records($store_id, $inventory_items) {
$table_name = $this->db->prefix . 'wc_flex_inventory_records';
foreach ($inventory_items as $item) {
$this->db->replace(
$table_name,
[
'product_id' => intval($item['product_id']),
'variant_id' => isset($item['variant_id']) ? intval($item['variant_id']) : 0,
'network_store_id' => $store_id,
'shared_quantity' => intval($item['quantity']),
'last_synced' => current_time('mysql')
],
['%d', '%d', '%d', '%d', '%s']
);
}
}
/**
* 获取可用于共享的库存总量
* @param int $product_id 产品ID
* @param int $variant_id 变体ID(可选)
* @return int 可用库存总量
*/
public function get_available_shared_inventory($product_id, $variant_id = 0) {
$table_name = $this->db->prefix . 'wc_flex_inventory_records';
$query = $this->db->prepare(
"SELECT SUM(shared_quantity - reserved_quantity) as total_available
FROM $table_name
WHERE product_id = %d AND variant_id = %d",
$product_id,
$variant_id
);
$result = $this->db->get_var($query);
return $result ? intval($result) : 0;
}
}
3. 智能库存分配算法
/**
* 智能库存分配器
* 根据预设策略自动分配库存
*/
class WC_Flexible_Inventory_Allocator {
private $db;
public function __construct() {
global $wpdb;
$this->db = $wpdb;
}
/**
* 为订单分配库存
* @param int $order_id 订单ID
* @param array $order_items 订单商品列表
* @return array 分配结果
*/
public function allocate_inventory_for_order($order_id, $order_items) {
$allocation_results = [];
foreach ($order_items as $item) {
$product_id = $item['product_id'];
$variant_id = isset($item['variation_id']) ? $item['variation_id'] : 0;
$quantity = $item['quantity'];
// 获取可用的共享库存
$available_stores = $this->get_available_stores_for_product($product_id, $variant_id);
// 根据分配策略选择店铺
$allocated_stores = $this->apply_allocation_strategy($available_stores, $quantity);
// 记录分配结果
foreach ($allocated_stores as $store_allocation) {
$this->record_allocation(
$order_id,
$product_id,
$store_allocation['store_id'],
$store_allocation['quantity']
);
// 预留库存
$this->reserve_inventory(
$product_id,
$variant_id,
$store_allocation['store_id'],
$store_allocation['quantity']
);
}
$allocation_results[$product_id] = $allocated_stores;
}
return $allocation_results;
}
/**
* 获取有可用库存的店铺
*/
private function get_available_stores_for_product($product_id, $variant_id) {
$table_name = $this->db->prefix . 'wc_flex_inventory_records';
$query = $this->db->prepare(
"SELECT r.*, n.store_name, n.store_url
FROM $table_name r
INNER JOIN {$this->db->prefix}wc_flex_inventory_network n
ON r.network_store_id = n.network_id
WHERE r.product_id = %d
AND r.variant_id = %d
AND (r.shared_quantity - r.reserved_quantity) > 0
AND n.status = 'active'
ORDER BY (r.shared_quantity - r.reserved_quantity) DESC",
$product_id,
$variant_id
);
return $this->db->get_results($query, ARRAY_A);
}
/**
* 应用分配策略(示例:就近优先策略)
*/
private function apply_allocation_strategy($available_stores, $required_quantity) {
$allocations = [];
$remaining_quantity = $required_quantity;
// 简单策略:按可用库存比例分配
$total_available = array_sum(array_column($available_stores, 'available'));
foreach ($available_stores as $store) {
if ($remaining_quantity <= 0) break;
$store_available = $store['shared_quantity'] - $store['reserved_quantity'];
$store_share = min(
floor(($store_available / $total_available) * $required_quantity),
$remaining_quantity
);
if ($store_share > 0) {
$allocations[] = [
'store_id' => $store['network_store_id'],
'quantity' => $store_share
];
$remaining_quantity -= $store_share;
}
}
return $allocations;
}
/**
* 记录库存分配
*/
private function record_allocation($order_id, $product_id, $store_id, $quantity) {
$table_name = $this->db->prefix . 'wc_flex_inventory_allocations';
$this->db->insert(
$table_name,
[
'order_id' => $order_id,
'product_id' => $product_id,
'allocated_store_id' => $store_id,
'allocated_quantity' => $quantity,
'allocation_type' => 'auto'
],
['%d', '%d', '%d', '%d', '%s']
);
}
}
插件集成与使用
WordPress集成
/**
* 主插件类
* 初始化所有组件并集成到WordPress
*/
class WC_Flexible_Inventory_Plugin {
private static $instance = null;
private $network_manager;
private $sync_manager;
private $allocator;
public static function get_instance() {
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
private function __construct() {
$this->init_components();
$this->setup_hooks();
}
private function init_components() {
$this->network_manager = new WC_Flexible_Inventory_Network();
$this->sync_manager = new WC_Flexible_Inventory_Sync();
$this->allocator = new WC_Flexible_Inventory_Allocator();
}
private function setup_hooks() {
// 插件激活时创建数据表
register_activation_hook(__FILE__, 'wc_flexible_inventory_create_tables');
// 添加管理菜单
add_action('admin_menu', [$this, 'add_admin_menu']);
// 集成WooCommerce
if (class_exists('WooCommerce')) {
add_filter('woocommerce_product_get_stock_quantity', [$this, 'adjust_stock_quantity'], 10, 2);
add_action('woocommerce_checkout_order_processed', [$this, 'handle_order_processed'], 10, 3);
}
// 注册REST API端点
add_action('rest_api_init', [$this, 'register_rest_endpoints']);
}
/**
* 调整显示的库存数量(包含共享库存)
*/
public function adjust_stock_quantity($quantity, $product) {
$shared_inventory = $this->sync_manager->get_available_shared_inventory(
$product->get_id(),
$product->get_type() === 'variation' ? $product->get_id() : 0
);
return $quantity + $shared_inventory;
}
/**
* 处理订单完成时的库存分配
*/
public function handle_order_processed($order_id, $posted_data, $order) {
$order_items = [];
foreach ($order->get_items() as $item) {
$order_items[] = [
'product_id' => $item->get_product_id(),
'variation_id' => $item->get_variation_id(),
'quantity' => $item->get_quantity()
];
}
$this->allocator->allocate_inventory_for_order($order_id, $order_items);
}
/**
* 注册REST API端点供其他店铺访问
*/
public function register_rest_endpoints() {
register_rest_route('wc-flex-inventory/v1', '/inventory', [
'methods' => 'GET',
'callback' => [$this, 'get_inventory_api'],
'permission_callback' => [$this, 'check_api_authentication']
]);
}
}
部署与优化建议
性能优化策略
- 缓存机制:对频繁查询的库存数据实施缓存
- 异步处理:使用队列处理库存同步和分配任务
- 数据库索引优化:确保关键
数据库索引优化
/**
* 数据库优化类
* 负责优化查询性能和数据管理
*/
class WC_Flexible_Inventory_Optimizer {
private $db;
public function __construct() {
global $wpdb;
$this->db = $wpdb;
}
/**
* 添加性能优化索引
*/
public function add_performance_indexes() {
$inventory_table = $this->db->prefix . 'wc_flex_inventory_records';
$allocations_table = $this->db->prefix . 'wc_flex_inventory_allocations';
// 添加复合索引以提高查询性能
$indexes = [
"ALTER TABLE $inventory_table ADD INDEX idx_product_variant (product_id, variant_id)",
"ALTER TABLE $inventory_table ADD INDEX idx_store_product (network_store_id, product_id)",
"ALTER TABLE $inventory_table ADD INDEX idx_available_stock (product_id, variant_id, shared_quantity, reserved_quantity)",
"ALTER TABLE $allocations_table ADD INDEX idx_order_product (order_id, product_id)",
"ALTER TABLE $allocations_table ADD INDEX idx_store_allocation (allocated_store_id, created_at)"
];
foreach ($indexes as $index_sql) {
$this->db->query($index_sql);
}
}
/**
* 清理历史数据
* @param int $days_ago 保留多少天前的数据
*/
public function cleanup_old_data($days_ago = 90) {
$allocations_table = $this->db->prefix . 'wc_flex_inventory_allocations';
$cutoff_date = date('Y-m-d H:i:s', strtotime("-$days_ago days"));
// 删除旧的分配记录
$this->db->query(
$this->db->prepare(
"DELETE FROM $allocations_table WHERE created_at < %s",
$cutoff_date
)
);
// 优化表
$this->db->query("OPTIMIZE TABLE $allocations_table");
}
/**
* 获取性能统计
*/
public function get_performance_stats() {
$stats = [];
$inventory_table = $this->db->prefix . 'wc_flex_inventory_records';
$allocations_table = $this->db->prefix . 'wc_flex_inventory_allocations';
// 查询表大小
$stats['inventory_table_size'] = $this->db->get_var(
"SELECT ROUND((data_length + index_length) / 1024 / 1024, 2)
FROM information_schema.TABLES
WHERE table_schema = DATABASE()
AND table_name = '$inventory_table'"
);
// 查询记录数量
$stats['inventory_records'] = $this->db->get_var(
"SELECT COUNT(*) FROM $inventory_table"
);
// 查询平均查询时间
$start_time = microtime(true);
$this->db->get_var("SELECT 1 FROM $inventory_table LIMIT 1");
$stats['avg_query_time'] = round((microtime(true) - $start_time) * 1000, 2);
return $stats;
}
}
前端界面开发
管理后台界面
/**
* 管理界面类
* 提供用户友好的管理界面
*/
class WC_Flexible_Inventory_Admin_UI {
public function __construct() {
add_action('admin_enqueue_scripts', [$this, 'enqueue_admin_assets']);
}
/**
* 加载管理界面资源
*/
public function enqueue_admin_assets($hook) {
if (strpos($hook, 'wc-flex-inventory') === false) {
return;
}
// 加载CSS样式
wp_enqueue_style(
'wc-flex-inventory-admin',
plugin_dir_url(__FILE__) . 'assets/css/admin.css',
[],
'1.0.0'
);
// 加载JavaScript
wp_enqueue_script(
'wc-flex-inventory-admin',
plugin_dir_url(__FILE__) . 'assets/js/admin.js',
['jquery', 'wp-api', 'chartjs'],
'1.0.0',
true
);
// 本地化脚本
wp_localize_script('wc-flex-inventory-admin', 'wcFlexInventory', [
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('wc_flex_inventory_nonce'),
'api_nonce' => wp_create_nonce('wp_rest')
]);
}
/**
* 渲染网络管理页面
*/
public function render_network_page() {
?>
<div class="wrap wc-flex-inventory">
<h1><?php esc_html_e('文创商品柔性库存共享网络', 'wc-flex-inventory'); ?></h1>
<div class="tablenav top">
<div class="alignleft actions">
<button type="button" class="button button-primary" id="add-store-btn">
<?php esc_html_e('添加新店铺', 'wc-flex-inventory'); ?>
</button>
</div>
</div>
<div id="store-network-container">
<!-- 店铺列表将通过AJAX加载 -->
<div class="spinner is-active"></div>
</div>
<!-- 添加店铺模态框 -->
<div id="add-store-modal" class="modal" style="display:none;">
<div class="modal-content">
<h2><?php esc_html_e('添加新店铺到共享网络', 'wc-flex-inventory'); ?></h2>
<form id="add-store-form">
<table class="form-table">
<tr>
<th scope="row">
<label for="store_name"><?php esc_html_e('店铺名称', 'wc-flex-inventory'); ?></label>
</th>
<td>
<input type="text" id="store_name" name="store_name" class="regular-text" required>
</td>
</tr>
<tr>
<th scope="row">
<label for="store_url"><?php esc_html_e('店铺网址', 'wc-flex-inventory'); ?></label>
</th>
<td>
<input type="url" id="store_url" name="store_url" class="regular-text" required>
</td>
</tr>
<tr>
<th scope="row">
<label for="contact_email"><?php esc_html_e('联系邮箱', 'wc-flex-inventory'); ?></label>
</th>
<td>
<input type="email" id="contact_email" name="contact_email" class="regular-text" required>
</td>
</tr>
<tr>
<th scope="row">
<label for="share_percentage"><?php esc_html_e('库存共享比例', 'wc-flex-inventory'); ?></label>
</th>
<td>
<input type="number" id="share_percentage" name="share_percentage"
min="0" max="100" value="100" class="small-text">
<span class="description">%</span>
<p class="description">
<?php esc_html_e('该店铺愿意共享的库存百分比', 'wc-flex-inventory'); ?>
</p>
</td>
</tr>
</table>
<p class="submit">
<button type="submit" class="button button-primary">
<?php esc_html_e('提交申请', 'wc-flex-inventory'); ?>
</button>
<button type="button" class="button button-secondary cancel-modal">
<?php esc_html_e('取消', 'wc-flex-inventory'); ?>
</button>
</p>
</form>
</div>
</div>
</div>
<?php
}
/**
* 渲染库存监控页面
*/
public function render_inventory_monitor() {
?>
<div class="wrap wc-flex-inventory">
<h1><?php esc_html_e('库存监控与分析', 'wc-flex-inventory'); ?></h1>
<div class="inventory-dashboard">
<div class="dashboard-row">
<div class="dashboard-card">
<h3><?php esc_html_e('总共享库存', 'wc-flex-inventory'); ?></h3>
<div class="card-value" id="total-shared-inventory">0</div>
</div>
<div class="dashboard-card">
<h3><?php esc_html_e('活跃店铺', 'wc-flex-inventory'); ?></h3>
<div class="card-value" id="active-stores">0</div>
</div>
<div class="dashboard-card">
<h3><?php esc_html_e('今日分配', 'wc-flex-inventory'); ?></h3>
<div class="card-value" id="today-allocations">0</div>
</div>
<div class="dashboard-card">
<h3><?php esc_html_e('库存周转率', 'wc-flex-inventory'); ?></h3>
<div class="card-value" id="inventory-turnover">0%</div>
</div>
</div>
<div class="dashboard-row">
<div class="dashboard-chart">
<h3><?php esc_html_e('库存分布', 'wc-flex-inventory'); ?></h3>
<canvas id="inventory-distribution-chart" width="400" height="200"></canvas>
</div>
<div class="dashboard-chart">
<h3><?php esc_html_e('分配趋势', 'wc-flex-inventory'); ?></h3>
<canvas id="allocation-trend-chart" width="400" height="200"></canvas>
</div>
</div>
<div class="dashboard-row">
<div class="inventory-alerts">
<h3><?php esc_html_e('库存预警', 'wc-flex-inventory'); ?></h3>
<div id="inventory-alerts-list">
<!-- 预警列表将通过AJAX加载 -->
</div>
</div>
</div>
</div>
</div>
<?php
}
}
AJAX处理
/**
* AJAX处理器
* 处理前端AJAX请求
*/
class WC_Flexible_Inventory_AJAX_Handler {
public function __construct() {
add_action('wp_ajax_wc_flex_get_stores', [$this, 'get_stores']);
add_action('wp_ajax_wc_flex_add_store', [$this, 'add_store']);
add_action('wp_ajax_wc_flex_update_store_status', [$this, 'update_store_status']);
add_action('wp_ajax_wc_flex_get_inventory_stats', [$this, 'get_inventory_stats']);
}
/**
* 获取店铺列表
*/
public function get_stores() {
$this->verify_nonce();
global $wpdb;
$table_name = $wpdb->prefix . 'wc_flex_inventory_network';
$page = isset($_POST['page']) ? intval($_POST['page']) : 1;
$per_page = 20;
$offset = ($page - 1) * $per_page;
// 获取店铺数据
$stores = $wpdb->get_results(
$wpdb->prepare(
"SELECT * FROM $table_name ORDER BY created_at DESC LIMIT %d OFFSET %d",
$per_page,
$offset
),
ARRAY_A
);
// 获取总数
$total = $wpdb->get_var("SELECT COUNT(*) FROM $table_name");
wp_send_json_success([
'stores' => $stores,
'pagination' => [
'total' => $total,
'per_page' => $per_page,
'current_page' => $page,
'total_pages' => ceil($total / $per_page)
]
]);
}
/**
* 添加新店铺
*/
public function add_store() {
$this->verify_nonce();
$store_data = [
'store_name' => sanitize_text_field($_POST['store_name']),
'store_url' => esc_url_raw($_POST['store_url']),
'contact_email' => sanitize_email($_POST['contact_email']),
'share_percentage' => isset($_POST['share_percentage']) ?
intval($_POST['share_percentage']) : 100
];
$network_manager = new WC_Flexible_Inventory_Network();
$result = $network_manager->add_store_to_network($store_data);
if ($result) {
wp_send_json_success([
'message' => __('店铺申请已提交,等待审核。', 'wc-flex-inventory'),
'store_id' => $result
]);
} else {
wp_send_json_error([
'message' => __('添加店铺失败,请检查输入数据。', 'wc-flex-inventory')
]);
}
}
/**
* 更新店铺状态
*/
public function update_store_status() {
$this->verify_nonce();
$store_id = intval($_POST['store_id']);
$status = sanitize_text_field($_POST['status']);
if (!in_array($status, ['active', 'inactive', 'pending'])) {
wp_send_json_error(['message' => '无效的状态值']);
}
global $wpdb;
$table_name = $wpdb->prefix . 'wc_flex_inventory_network';
$result = $wpdb->update(
$table_name,
['status' => $status],
['network_id' => $store_id],
['%s'],
['%d']
);
if ($result !== false) {
// 如果激活店铺,发送通知邮件
if ($status === 'active') {
$this->send_activation_email($store_id);
}
wp_send_json_success(['message' => '店铺状态已更新']);
} else {
wp_send_json_error(['message' => '更新失败']);
}
}
/**
* 获取库存统计
*/
public function get_inventory_stats() {
$this->verify_nonce();
global $wpdb;
$stats = [];
// 获取总共享库存
$inventory_table = $wpdb->prefix . 'wc_flex_inventory_records';
$stats['total_shared'] = $wpdb->get_var(
"SELECT SUM(shared_quantity) FROM $inventory_table"
) ?: 0;
// 获取活跃店铺数量
$network_table = $wpdb->prefix . 'wc_flex_inventory_network';
$stats['active_stores'] = $wpdb->get_var(
"SELECT COUNT(*) FROM $network_table WHERE status = 'active'"
) ?: 0;
// 获取今日分配数量
$allocations_table = $wpdb->prefix . 'wc_flex_inventory_allocations';
$today = date('Y-m-d');
$stats['today_allocations'] = $wpdb->get_var(
$wpdb->prepare(
"SELECT SUM(allocated_quantity) FROM $allocations_table
WHERE DATE(created_at) = %s",
$today
)
) ?: 0;
// 获取库存预警
$stats['alerts'] = $this->get_inventory_alerts();
wp_send_json_success($stats);
}
/**
* 验证nonce
*/
private function verify_nonce() {
if (!isset($_POST['nonce']) ||
!wp_verify_nonce($_POST['nonce'], 'wc_flex_inventory_nonce')) {
wp_send_json_error(['message' => '安全验证失败']);
}
}
}
安全与错误处理
安全防护
/**
* 安全防护类
* 处理插件安全相关功能
*/
class WC_Flexible_Inventory_Security {
/**
* 验证API请求
*/
public static function validate_api_request($request) {
$api_key = $request->get_header('Authorization');
if (empty($api_key)) {
return new WP_Error(
'missing_api_key',
'API密钥缺失',
['status' => 401]
);
}
// 移除Bearer前缀
$api_key = str_replace('Bearer ', '', $api_key);
// 验证API密钥
global $wpdb;
$table_name = $wpdb->prefix . 'wc_flex_inventory_network';
$valid = $wpdb->get_var(
$wpdb->prepare(
"SELECT COUNT(*) FROM $table_name
WHERE api_key = %s AND status = 'active'",
$api_key
)
);
if (!$valid) {
return new WP_Error(
'invalid_api_key',
'无效的API密钥',
['status' => 403]
);
}
return true;
}
/**
* 数据输入验证
*/
public static function validate_input($data, $rules) {
$errors = [];
foreach ($rules as $field => $rule) {
$value = isset($data[$field]) ? $data[$field] : null;
if (in_array('required', $rule) && empty($value)) {
$errors[$field] = "字段 {$field} 是必填项";
continue;
}
if ($value !== null) {
if (in_array('email', $rule) && !is_email($value)) {
$errors[$field] = "字段 {$field} 必须是有效的邮箱地址";
}
if (in_array('url', $rule) && !filter_var($value, FILTER_VALIDATE_URL)) {
$errors[$field] = "字段 {$field} 必须是有效的URL";
}
if (in_array('numeric', $rule) && !is_numeric($value)) {
$errors[$field] = "字段 {$field} 必须是数字";
