文章目录[隐藏]
实操指南:设计高效订单管理接口的4个最佳实践
引言:为什么订单管理接口如此重要?
在电子商务和在线服务日益普及的今天,订单管理系统已成为各类网站和应用的核心组件。对于基于WordPress的电商网站而言,一个高效、可靠的订单管理接口不仅直接影响用户体验,更关系到业务流程的顺畅度和数据安全性。
WordPress作为全球最流行的内容管理系统,拥有WooCommerce这样的强大电商插件,但许多企业仍需要根据自身业务需求定制订单管理功能。设计良好的订单管理接口能够:
- 提升订单处理效率
- 减少人工操作错误
- 提供实时数据同步
- 支持复杂的业务逻辑
- 确保数据一致性和安全性
本文将基于WordPress开发环境,分享四个设计高效订单管理接口的最佳实践,帮助行业新人和程序员构建稳定可靠的订单管理系统。
实践一:遵循RESTful API设计原则
1.1 RESTful API的核心优势
RESTful API已成为现代Web服务的事实标准,它通过统一的接口设计规范,使API更易于理解、使用和维护。在WordPress中,我们可以利用其内置的REST API功能来构建订单管理接口。
1.2 WordPress REST API基础
WordPress从4.7版本开始内置了REST API,为开发者提供了标准的API开发框架。对于订单管理,我们可以创建自定义的REST端点:
// 注册自定义订单REST API端点
add_action('rest_api_init', function () {
// 获取订单列表
register_rest_route('order-manager/v1', '/orders', [
'methods' => 'GET',
'callback' => 'get_orders_list',
'permission_callback' => 'check_order_permissions'
]);
// 获取单个订单详情
register_rest_route('order-manager/v1', '/orders/(?P<id>d+)', [
'methods' => 'GET',
'callback' => 'get_single_order',
'permission_callback' => 'check_order_permissions'
]);
// 创建新订单
register_rest_route('order-manager/v1', '/orders', [
'methods' => 'POST',
'callback' => 'create_new_order',
'permission_callback' => 'check_order_permissions'
]);
// 更新订单状态
register_rest_route('order-manager/v1', '/orders/(?P<id>d+)/status', [
'methods' => 'PUT',
'callback' => 'update_order_status',
'permission_callback' => 'check_order_permissions'
]);
});
1.3 资源命名与端点设计最佳实践
- 使用名词复数形式表示资源集合:
/orders而不是/getOrders - 使用HTTP方法明确操作意图:GET(获取)、POST(创建)、PUT(更新)、DELETE(删除)
- 嵌套资源合理设计:
/orders/123/items表示订单123的商品项 - 版本控制:在URL中包含API版本,如
/v1/orders
1.4 权限控制实现
// 权限检查回调函数
function check_order_permissions($request) {
// 检查用户是否登录
if (!is_user_logged_in()) {
return new WP_Error('rest_forbidden', '您没有权限访问此资源', ['status' => 401]);
}
// 获取当前用户
$current_user = wp_get_current_user();
// 检查用户角色 - 只有管理员和商店经理可以管理订单
if (!in_array('administrator', $current_user->roles) &&
!in_array('shop_manager', $current_user->roles)) {
return new WP_Error('rest_forbidden', '您没有权限管理订单', ['status' => 403]);
}
return true;
}
实践二:优化数据库查询与数据结构设计
2.1 WordPress订单数据存储分析
WordPress通常使用posts表存储订单主信息,postmeta表存储订单元数据。这种设计灵活但可能导致性能问题,特别是当订单数量庞大时。
2.2 高效数据库查询技巧
// 不推荐的查询方式 - 多次查询meta数据
function get_order_details_slow($order_id) {
$order = [];
$order['customer_name'] = get_post_meta($order_id, '_customer_name', true);
$order['customer_email'] = get_post_meta($order_id, '_customer_email', true);
$order['total_amount'] = get_post_meta($order_id, '_order_total', true);
// ...更多字段查询
return $order;
}
// 推荐的查询方式 - 单次查询获取所有meta数据
function get_order_details_fast($order_id) {
// 一次性获取所有meta数据
$all_meta = get_post_meta($order_id);
// 处理meta数据
$order = [];
$order['customer_name'] = isset($all_meta['_customer_name'][0]) ? $all_meta['_customer_name'][0] : '';
$order['customer_email'] = isset($all_meta['_customer_email'][0]) ? $all_meta['_customer_email'][0] : '';
$order['total_amount'] = isset($all_meta['_order_total'][0]) ? $all_meta['_order_total'][0] : 0;
// 使用缓存减少数据库查询
$cache_key = 'order_details_' . $order_id;
$cached_order = wp_cache_get($cache_key, 'orders');
if (false === $cached_order) {
// 从数据库获取数据
$cached_order = $order;
wp_cache_set($cache_key, $cached_order, 'orders', 3600); // 缓存1小时
}
return $cached_order;
}
2.3 自定义订单表设计
对于高流量电商网站,可以考虑创建专门的订单表来优化性能:
// 创建自定义订单表
function create_custom_order_table() {
global $wpdb;
$table_name = $wpdb->prefix . 'custom_orders';
$charset_collate = $wpdb->get_charset_collate();
$sql = "CREATE TABLE IF NOT EXISTS $table_name (
order_id bigint(20) NOT NULL AUTO_INCREMENT,
order_number varchar(100) NOT NULL,
customer_id bigint(20) NOT NULL,
customer_email varchar(100) NOT NULL,
total_amount decimal(10,2) NOT NULL,
status varchar(50) NOT NULL,
payment_method varchar(100),
created_at datetime DEFAULT CURRENT_TIMESTAMP NOT NULL,
updated_at datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL,
PRIMARY KEY (order_id),
INDEX idx_customer_id (customer_id),
INDEX idx_status (status),
INDEX idx_created_at (created_at),
UNIQUE KEY uniq_order_number (order_number)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
}
add_action('after_setup_theme', 'create_custom_order_table');
2.4 数据库索引优化策略
- 为经常查询的字段创建索引:customer_id、status、created_at
- 避免过度索引,影响写入性能
- 定期优化数据库表
- 使用EXPLAIN分析查询性能
实践三:实现可靠的数据验证与错误处理
3.1 输入数据验证
// 订单创建数据验证
function validate_order_data($order_data) {
$errors = [];
// 验证必填字段
$required_fields = [
'customer_email' => '客户邮箱',
'total_amount' => '订单总金额',
'items' => '订单商品'
];
foreach ($required_fields as $field => $field_name) {
if (empty($order_data[$field])) {
$errors[] = $field_name . '不能为空';
}
}
// 验证邮箱格式
if (!empty($order_data['customer_email']) &&
!filter_var($order_data['customer_email'], FILTER_VALIDATE_EMAIL)) {
$errors[] = '邮箱格式不正确';
}
// 验证金额格式
if (!empty($order_data['total_amount']) &&
!is_numeric($order_data['total_amount'])) {
$errors[] = '订单金额必须是数字';
}
// 验证商品数据
if (!empty($order_data['items']) && is_array($order_data['items'])) {
foreach ($order_data['items'] as $index => $item) {
if (empty($item['product_id']) || empty($item['quantity'])) {
$errors[] = '第' . ($index + 1) . '个商品信息不完整';
}
}
}
return $errors;
}
3.2 统一错误响应格式
// 统一的API响应处理类
class Order_API_Response {
public static function success($data = null, $message = '操作成功') {
return new WP_REST_Response([
'success' => true,
'message' => $message,
'data' => $data,
'timestamp' => current_time('timestamp')
], 200);
}
public static function error($message, $error_code = 'order_error', $status_code = 400) {
return new WP_Error(
$error_code,
$message,
['status' => $status_code]
);
}
public static function validation_error($errors) {
return new WP_Error(
'validation_failed',
'数据验证失败',
[
'status' => 422,
'errors' => $errors
]
);
}
}
// 在API回调中使用统一响应
function create_new_order($request) {
$order_data = $request->get_json_params();
// 数据验证
$validation_errors = validate_order_data($order_data);
if (!empty($validation_errors)) {
return Order_API_Response::validation_error($validation_errors);
}
try {
// 创建订单逻辑
$order_id = save_order_to_database($order_data);
if ($order_id) {
// 记录订单创建日志
log_order_action($order_id, 'create', '订单创建成功');
return Order_API_Response::success(
['order_id' => $order_id],
'订单创建成功'
);
} else {
return Order_API_Response::error('订单创建失败');
}
} catch (Exception $e) {
// 记录异常
error_log('订单创建异常: ' . $e->getMessage());
return Order_API_Response::error(
'系统处理订单时发生错误',
'internal_server_error',
500
);
}
}
3.3 事务处理确保数据一致性
// 使用数据库事务处理订单创建
function save_order_with_transaction($order_data) {
global $wpdb;
// 开始事务
$wpdb->query('START TRANSACTION');
try {
// 插入订单主记录
$order_result = $wpdb->insert(
$wpdb->prefix . 'custom_orders',
[
'order_number' => generate_order_number(),
'customer_id' => $order_data['customer_id'],
'customer_email' => $order_data['customer_email'],
'total_amount' => $order_data['total_amount'],
'status' => 'pending'
]
);
if (!$order_result) {
throw new Exception('订单主记录插入失败');
}
$order_id = $wpdb->insert_id;
// 插入订单商品项
foreach ($order_data['items'] as $item) {
$item_result = $wpdb->insert(
$wpdb->prefix . 'order_items',
[
'order_id' => $order_id,
'product_id' => $item['product_id'],
'quantity' => $item['quantity'],
'price' => $item['price']
]
);
if (!$item_result) {
throw new Exception('订单商品项插入失败');
}
// 更新商品库存
$update_stock = $wpdb->query($wpdb->prepare(
"UPDATE {$wpdb->prefix}products
SET stock = stock - %d
WHERE product_id = %d",
$item['quantity'],
$item['product_id']
));
if ($update_stock === false) {
throw new Exception('商品库存更新失败');
}
}
// 提交事务
$wpdb->query('COMMIT');
return $order_id;
} catch (Exception $e) {
// 回滚事务
$wpdb->query('ROLLBACK');
error_log('订单事务失败: ' . $e->getMessage());
return false;
}
}
实践四:保障接口安全与性能优化
4.1 多层次安全防护
// API安全防护措施
class Order_API_Security {
// 1. 防止SQL注入
public static function safe_query($wpdb, $query, $params = []) {
if (empty($params)) {
return $wpdb->query($query);
}
return $wpdb->query($wpdb->prepare($query, $params));
}
// 2. 输入数据清理
public static function sanitize_order_input($input) {
$sanitized = [];
foreach ($input as $key => $value) {
if (is_array($value)) {
$sanitized[$key] = self::sanitize_order_input($value);
} else {
// 根据字段类型进行不同的清理
switch ($key) {
case 'customer_email':
$sanitized[$key] = sanitize_email($value);
break;
case 'customer_name':
case 'shipping_address':
$sanitized[$key] = sanitize_text_field($value);
break;
case 'order_notes':
$sanitized[$key] = sanitize_textarea_field($value);
break;
case 'total_amount':
case 'product_price':
$sanitized[$key] = floatval($value);
break;
case 'quantity':
$sanitized[$key] = intval($value);
break;
default:
$sanitized[$key] = sanitize_text_field($value);
}
}
}
return $sanitized;
}
// 3. 防止CSRF攻击
public static function verify_nonce($request) {
$nonce = $request->get_header('X-WP-Nonce');
if (!wp_verify_nonce($nonce, 'wp_rest')) {
return new WP_Error(
'invalid_nonce',
'安全验证失败,请刷新页面重试',
['status' => 403]
);
}
return true;
}
// 4. 速率限制
public static function rate_limit($user_id, $action, $limit = 10, $period = 60) {
$transient_key = 'rate_limit_' . $user_id . '_' . $action;
$attempts = get_transient($transient_key);
if ($attempts === false) {
$attempts = 1;
set_transient($transient_key, $attempts, $period);
} elseif ($attempts < $limit) {
$attempts++;
set_transient($transient_key, $attempts, $period);
} else {
return new WP_Error(
'rate_limit_exceeded',
'操作过于频繁,请稍后再试',
['status' => 429]
);
}
return true;
}
}
4.2 性能优化策略
// 订单接口性能优化
class Order_API_Performance {
// 1. 查询结果分页
public static function get_paginated_orders($page = 1, $per_page = 20, $filters = []) {
global $wpdb;
$offset = ($page - 1) * $per_page;
// 基础查询
$query = "SELECT * FROM {$wpdb->prefix}custom_orders WHERE 1=1";
$query_params = [];
// 添加过滤条件
if (!empty($filters['status'])) {
$query .= " AND status = %s";
$query_params[] = $filters['status'];
}
if (!empty($filters['customer_id'])) {
$query .= " AND customer_id = %d";
$query_params[] = $filters['customer_id'];
}
if (!empty($filters['start_date'])) {
$query .= " AND created_at >= %s";
$query_params[] = $filters['start_date'];
}
if (!empty($filters['end_date'])) {
$query .= " AND created_at <= %s";
$query_params[] = $filters['end_date'];
}
// 添加排序
$query .= " ORDER BY created_at DESC";
// 获取总数
$count_query = str_replace('SELECT *', 'SELECT COUNT(*)', $query);
if (!empty($query_params)) {
$count_query = $wpdb->prepare($count_query, $query_params);
}
$total_items = $wpdb->get_var($count_query);
// 获取分页数据
$query .= " LIMIT %d OFFSET %d";
$query_params[] = $per_page;
$query_params[] = $offset;
$prepared_query = $wpdb->prepare($query, $query_params);
$orders = $wpdb->get_results($prepared_query, ARRAY_A);
return [
'data' => $orders,
'pagination' => [
'page' => $page,
'per_page' => $per_page,
'total_items' => $total_items,
'total_pages' => ceil($total_items / $per_page)
]
4.3 缓存策略实施
// 2. 多级缓存实现
public static function get_order_with_cache($order_id) {
$cache_key = 'order_full_' . $order_id;
// 第一层:内存缓存(WordPress对象缓存)
$cached_order = wp_cache_get($cache_key, 'orders');
if ($cached_order !== false) {
return $cached_order;
}
// 第二层:数据库缓存(自定义缓存表)
global $wpdb;
$cache_data = $wpdb->get_var($wpdb->prepare(
"SELECT cache_value FROM {$wpdb->prefix}api_cache
WHERE cache_key = %s AND expires_at > NOW()",
$cache_key
));
if ($cache_data) {
$order_data = maybe_unserialize($cache_data);
wp_cache_set($cache_key, $order_data, 'orders', 300); // 5分钟内存缓存
return $order_data;
}
// 第三层:实际数据库查询
$order_data = self::fetch_full_order_from_db($order_id);
if ($order_data) {
// 更新所有缓存层
wp_cache_set($cache_key, $order_data, 'orders', 300);
$wpdb->replace(
$wpdb->prefix . 'api_cache',
[
'cache_key' => $cache_key,
'cache_value' => maybe_serialize($order_data),
'created_at' => current_time('mysql'),
'expires_at' => date('Y-m-d H:i:s', time() + 3600) // 1小时后过期
]
);
}
return $order_data;
}
// 3. 延迟加载与关联数据优化
public static function fetch_full_order_from_db($order_id) {
global $wpdb;
// 主订单信息
$order = $wpdb->get_row($wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}custom_orders WHERE order_id = %d",
$order_id
), ARRAY_A);
if (!$order) {
return null;
}
// 延迟加载商品项(按需加载)
$order['items'] = function() use ($order_id) {
global $wpdb;
return $wpdb->get_results($wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}order_items WHERE order_id = %d",
$order_id
), ARRAY_A);
};
// 延迟加载客户信息
$order['customer'] = function() use ($order) {
if (!empty($order['customer_id'])) {
return get_userdata($order['customer_id']);
}
return null;
};
return $order;
}
// 4. 批量操作优化
public static function batch_update_order_status($order_ids, $new_status) {
global $wpdb;
if (empty($order_ids)) {
return 0;
}
// 使用IN语句批量更新,减少查询次数
$placeholders = implode(',', array_fill(0, count($order_ids), '%d'));
$query = $wpdb->prepare(
"UPDATE {$wpdb->prefix}custom_orders
SET status = %s, updated_at = NOW()
WHERE order_id IN ($placeholders)",
array_merge([$new_status], $order_ids)
);
$affected_rows = $wpdb->query($query);
// 清除相关缓存
foreach ($order_ids as $order_id) {
wp_cache_delete('order_full_' . $order_id, 'orders');
wp_cache_delete('order_basic_' . $order_id, 'orders');
}
return $affected_rows;
}
4.4 异步处理与队列机制
// 订单异步处理类
class Order_Async_Processor {
private static $queue_table;
public static function init() {
global $wpdb;
self::$queue_table = $wpdb->prefix . 'order_async_queue';
// 创建异步任务表
self::create_queue_table();
// 注册后台处理钩子
add_action('order_async_process', [__CLASS__, 'process_queue']);
}
private static function create_queue_table() {
global $wpdb;
$charset_collate = $wpdb->get_charset_collate();
$sql = "CREATE TABLE IF NOT EXISTS " . self::$queue_table . " (
task_id bigint(20) NOT NULL AUTO_INCREMENT,
task_type varchar(50) NOT NULL,
task_data longtext NOT NULL,
priority int(11) DEFAULT 10,
attempts int(11) DEFAULT 0,
max_attempts int(11) DEFAULT 3,
status varchar(20) DEFAULT 'pending',
scheduled_at datetime DEFAULT CURRENT_TIMESTAMP,
processed_at datetime NULL,
created_at datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (task_id),
INDEX idx_status_type (status, task_type),
INDEX idx_scheduled (scheduled_at)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
}
// 添加异步任务
public static function add_async_task($task_type, $task_data, $priority = 10, $delay = 0) {
global $wpdb;
$scheduled_at = date('Y-m-d H:i:s', time() + $delay);
$result = $wpdb->insert(
self::$queue_table,
[
'task_type' => $task_type,
'task_data' => maybe_serialize($task_data),
'priority' => $priority,
'scheduled_at' => $scheduled_at,
'status' => 'pending'
]
);
if ($result) {
// 触发后台处理(使用WordPress的cron系统)
if (!wp_next_scheduled('order_async_process')) {
wp_schedule_single_event(time() + 5, 'order_async_process');
}
return $wpdb->insert_id;
}
return false;
}
// 处理队列任务
public static function process_queue() {
global $wpdb;
// 获取待处理任务(按优先级和计划时间)
$tasks = $wpdb->get_results(
"SELECT * FROM " . self::$queue_table . "
WHERE status = 'pending'
AND scheduled_at <= NOW()
ORDER BY priority ASC, scheduled_at ASC
LIMIT 10"
);
foreach ($tasks as $task) {
// 标记为处理中
$wpdb->update(
self::$queue_table,
['status' => 'processing', 'attempts' => $task->attempts + 1],
['task_id' => $task->task_id]
);
try {
// 根据任务类型执行不同处理
$task_data = maybe_unserialize($task->task_data);
$result = self::execute_task($task->task_type, $task_data);
if ($result) {
// 标记为完成
$wpdb->update(
self::$queue_table,
['status' => 'completed', 'processed_at' => current_time('mysql')],
['task_id' => $task->task_id]
);
} else {
// 检查重试次数
if ($task->attempts + 1 >= $task->max_attempts) {
$wpdb->update(
self::$queue_table,
['status' => 'failed', 'processed_at' => current_time('mysql')],
['task_id' => $task->task_id]
);
} else {
// 重新排队,延迟重试
$delay = min(300 * pow(2, $task->attempts), 3600); // 指数退避
$wpdb->update(
self::$queue_table,
[
'status' => 'pending',
'scheduled_at' => date('Y-m-d H:i:s', time() + $delay)
],
['task_id' => $task->task_id]
);
}
}
} catch (Exception $e) {
error_log('异步任务处理失败: ' . $e->getMessage());
$wpdb->update(
self::$queue_table,
['status' => 'failed', 'processed_at' => current_time('mysql')],
['task_id' => $task->task_id]
);
}
}
// 检查是否还有待处理任务
$remaining = $wpdb->get_var(
"SELECT COUNT(*) FROM " . self::$queue_table . "
WHERE status = 'pending' AND scheduled_at <= NOW()"
);
if ($remaining > 0) {
// 安排下一次处理
wp_schedule_single_event(time() + 5, 'order_async_process');
}
}
// 执行具体任务
private static function execute_task($task_type, $task_data) {
switch ($task_type) {
case 'send_order_email':
return self::send_order_email($task_data);
case 'sync_to_erp':
return self::sync_order_to_erp($task_data);
case 'generate_invoice':
return self::generate_order_invoice($task_data);
case 'update_inventory':
return self::update_inventory_async($task_data);
default:
throw new Exception("未知的任务类型: {$task_type}");
}
}
// 示例:异步发送订单邮件
private static function send_order_email($order_data) {
$to = $order_data['customer_email'];
$subject = '您的订单确认 - #' . $order_data['order_number'];
$message = self::generate_order_email_template($order_data);
$headers = ['Content-Type: text/html; charset=UTF-8'];
return wp_mail($to, $subject, $message, $headers);
}
}
实战案例:完整订单管理接口实现
5.1 订单管理接口完整类
/**
* 订单管理API主类
*/
class Order_Management_API {
private static $instance = null;
private $version = '1.0.0';
private $namespace = 'order-manager/v1';
public static function get_instance() {
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
private function __construct() {
$this->init_hooks();
}
private function init_hooks() {
add_action('rest_api_init', [$this, 'register_routes']);
add_action('init', [$this, 'init_order_tables']);
add_action('order_async_process', ['Order_Async_Processor', 'process_queue']);
}
public function init_order_tables() {
global $wpdb;
// 创建订单相关数据表
$charset_collate = $wpdb->get_charset_collate();
$tables = [
'custom_orders' => "
CREATE TABLE IF NOT EXISTS {$wpdb->prefix}custom_orders (
order_id bigint(20) NOT NULL AUTO_INCREMENT,
order_number varchar(100) NOT NULL,
customer_id bigint(20) NOT NULL,
customer_email varchar(100) NOT NULL,
customer_name varchar(200),
total_amount decimal(10,2) NOT NULL,
discount_amount decimal(10,2) DEFAULT 0.00,
shipping_amount decimal(10,2) DEFAULT 0.00,
tax_amount decimal(10,2) DEFAULT 0.00,
final_amount decimal(10,2) NOT NULL,
currency varchar(10) DEFAULT 'CNY',
status varchar(50) NOT NULL DEFAULT 'pending',
payment_method varchar(100),
payment_status varchar(50) DEFAULT 'pending',
shipping_method varchar(100),
shipping_address text,
billing_address text,
order_notes text,
ip_address varchar(45),
user_agent text,
created_at datetime DEFAULT CURRENT_TIMESTAMP NOT NULL,
updated_at datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL,
PRIMARY KEY (order_id),
UNIQUE KEY uniq_order_number (order_number),
INDEX idx_customer_id (customer_id),
INDEX idx_status (status),
INDEX idx_payment_status (payment_status),
INDEX idx_created_at (created_at),
INDEX idx_customer_email (customer_email)
) $charset_collate
",
'order_items' => "
CREATE TABLE IF NOT EXISTS {$wpdb->prefix}order_items (
item_id bigint(20) NOT NULL AUTO_INCREMENT,
order_id bigint(20) NOT NULL,
product_id bigint(20) NOT NULL,
product_name varchar(255) NOT NULL,
product_sku varchar(100),
quantity int(11) NOT NULL,
unit_price decimal(10,2) NOT NULL,
subtotal decimal(10,2) NOT NULL,
tax_rate decimal(5,2) DEFAULT 0.00,
tax_amount decimal(10,2) DEFAULT 0.00,
discount_rate decimal(5,2) DEFAULT 0.00,
discount_amount decimal(10,2) DEFAULT 0.00,
total_price decimal(10,2) NOT NULL,
variant_data text,
created_at datetime DEFAULT CURRENT_TIMESTAMP NOT NULL,
PRIMARY KEY (item_id),
INDEX idx_order_id (order_id),
INDEX idx_product_id (product_id),
FOREIGN KEY (order_id) REFERENCES {$wpdb->prefix}custom_orders(order_id) ON DELETE CASCADE
) $charset_collate
",
'order_status_history' => "
CREATE TABLE IF NOT EXISTS {$wpdb->prefix}order_status_history (
history_id bigint(20) NOT NULL AUTO_INCREMENT,
order_id bigint(20) NOT NULL,
old_status varchar(50),
new_status varchar(50) NOT NULL,
changed_by bigint(20),
change_reason text,
note text,
created_at datetime DEFAULT CURRENT_TIMESTAMP NOT NULL,
PRIMARY KEY (history_id),
INDEX idx_order_id (order_id),
INDEX idx_created_at (created_at),
FOREIGN KEY (order_id) REFERENCES {$wpdb->prefix}custom_orders(order_id) ON DELETE CASCADE
) $charset_collate
"
];
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
foreach ($tables as $table_sql) {
dbDelta($table_sql);
}
}
public function register_routes() {
// 订单集合路由
register_rest_route($this->namespace, '/orders', [
[
'methods' => WP_REST_Server::READABLE,
'callback' => [$this, 'get_orders'],
'permission_callback' => [$this, 'check_order_permissions'],
'args' => $this->get_collection_params()
],
[
'methods' => WP_REST_Server::CREATABLE,
'callback' => [$this, 'create_order'],
'permission_callback' => [$this, 'check_order_permissions']
]
]);
// 单个订单路由
register_rest_route($this->namespace, '/orders/(?P<id>d+)', [
[
'methods' => WP_REST_Server::READABLE,
'callback' => [$this, 'get_order'],
'permission_callback' => [$this, 'check_order_permissions']
],
[
'methods' => WP_REST_Server::EDITABLE,
'callback' => [$this, 'update_order'],
'permission_callback' => [$this, 'check_order_permissions']
],
[
'methods' => WP_REST_Server::DELETABLE,
'callback' => [$this, 'delete_order'],
'permission_callback' => [$this, 'check_order_permissions']
]
]);
// 订单状态管理
register_rest_route($this->namespace, '/orders/(?P<id>d+)/status', [
[
'methods' => WP_REST_Server::EDITABLE,
'callback' => [$this, 'update_order_status'],
'permission_callback' => [$this, 'check_order_permissions']
]
]);
// 批量操作
register_rest_route($this->namespace, '/orders/batch', [
[
'methods' => WP_REST_Server::EDITABLE,
'callback' => [$this, 'batch_update_orders'],
'permission_callback' => [$this, 'check_order_permissions']
]
]);
// 统计接口
register_rest_route($this->namespace, '/orders/stats', [
[
'methods' => WP_REST_Server::READABLE,
'callback' => [$this, 'get_order_stats'],
'permission_callback' => [$this, 'check_order_permissions']
]
]);
}
public function check_order_permissions($request) {
// 检查用户是否登录
if (!is_user_logged_in()) {
return new WP_Error(
'rest_not_logged_in',
'您需要登录才能访问此接口',
['status' => 401]
);
}
$current_user = wp_get_current_user();
$user_roles = $current_user->roles;
// 允许的角色:管理员、编辑、商店经理
$allowed_roles = ['administrator', 'editor', 'shop_manager'];
foreach ($user_roles as $role) {
if (in_array($role, $allowed_roles)) {
return true;
}
}
// 检查特定权限
$method = $request->get_method();
$route = $request->get_route();
// 普通用户只能查看自己的订单
if ($method === 'GET' && strpos($route, '/orders/') !== false) {
$params = $request->get_params();
if (isset($params['id'])) {
$order = $this->get_order_from_db($params['id']);
