init_hooks(); } /** * 初始化钩子 */ private function init_hooks() { // 管理菜单 add_action('admin_menu', array($this, 'add_admin_menus')); // 产品数据面板 add_filter('woocommerce_product_data_tabs', array($this, 'add_product_data_tabs')); add_action('woocommerce_product_data_panels', array($this, 'add_product_data_panels')); add_action('woocommerce_process_product_meta', array($this, 'save_product_meta')); // 产品类型 add_filter('product_type_selector', array($this, 'add_product_types')); // 订单管理 add_action('add_meta_boxes', array($this, 'add_order_meta_boxes')); add_action('woocommerce_order_status_changed', array($this, 'handle_order_status_change'), 10, 4); // 列表表格 add_filter('manage_edit-product_columns', array($this, 'add_product_columns')); add_action('manage_product_posts_custom_column', array($this, 'product_column_content'), 10, 2); // 设置页面 add_filter('woocommerce_settings_tabs_array', array($this, 'add_settings_tab'), 50); add_action('woocommerce_settings_tabs_yoone_subscriptions', array($this, 'settings_tab_content')); add_action('woocommerce_update_options_yoone_subscriptions', array($this, 'update_settings')); // 通知 add_action('admin_notices', array($this, 'admin_notices')); } /** * 添加管理菜单 */ public function add_admin_menus() { // 主菜单 add_menu_page( __('Yoone 订阅', 'yoone-subscriptions'), __('Yoone 订阅', 'yoone-subscriptions'), 'manage_woocommerce', 'yoone-subscriptions', array($this, 'subscriptions_page'), 'dashicons-update', 56 ); // 订阅管理 add_submenu_page( 'yoone-subscriptions', __('订阅管理', 'yoone-subscriptions'), __('订阅管理', 'yoone-subscriptions'), 'manage_woocommerce', 'yoone-subscriptions', array($this, 'subscriptions_page') ); // 混装产品 add_submenu_page( 'yoone-subscriptions', __('混装产品', 'yoone-subscriptions'), __('混装产品', 'yoone-subscriptions'), 'manage_woocommerce', 'yoone-bundles', array($this, 'bundles_page') ); // 支付设置 add_submenu_page( 'yoone-subscriptions', __('支付设置', 'yoone-subscriptions'), __('支付设置', 'yoone-subscriptions'), 'manage_woocommerce', 'yoone-payment-settings', array($this, 'payment_settings_page') ); // 报告 add_submenu_page( 'yoone-subscriptions', __('报告', 'yoone-subscriptions'), __('报告', 'yoone-subscriptions'), 'manage_woocommerce', 'yoone-reports', array($this, 'reports_page') ); } /** * 订阅管理页面 */ public function subscriptions_page() { $action = isset($_GET['action']) ? $_GET['action'] : 'list'; switch ($action) { case 'view': $this->view_subscription(); break; case 'edit': $this->edit_subscription(); break; default: $this->list_subscriptions(); break; } } /** * 订阅列表 */ private function list_subscriptions() { global $wpdb; $per_page = 20; $current_page = isset($_GET['paged']) ? max(1, intval($_GET['paged'])) : 1; $offset = ($current_page - 1) * $per_page; $status_filter = isset($_GET['status']) ? $_GET['status'] : ''; $search = isset($_GET['s']) ? $_GET['s'] : ''; $where_conditions = array('1=1'); $params = array(); if ($status_filter) { $where_conditions[] = 'status = %s'; $params[] = $status_filter; } if ($search) { $where_conditions[] = '(id LIKE %s OR customer_id IN (SELECT ID FROM ' . $wpdb->users . ' WHERE display_name LIKE %s OR user_email LIKE %s))'; $params[] = '%' . $search . '%'; $params[] = '%' . $search . '%'; $params[] = '%' . $search . '%'; } $where_clause = implode(' AND ', $where_conditions); // 获取总数 $total_query = "SELECT COUNT(*) FROM {$wpdb->prefix}yoone_subscriptions WHERE {$where_clause}"; $total_items = $wpdb->get_var($wpdb->prepare($total_query, $params)); // 获取订阅列表 $params[] = $per_page; $params[] = $offset; $subscriptions_query = "SELECT * FROM {$wpdb->prefix}yoone_subscriptions WHERE {$where_clause} ORDER BY created_at DESC LIMIT %d OFFSET %d"; $subscriptions = $wpdb->get_results($wpdb->prepare($subscriptions_query, $params)); include YOONE_SUBSCRIPTIONS_PLUGIN_PATH . 'templates/admin/subscriptions-list.php'; } /** * 查看订阅 */ private function view_subscription() { $subscription_id = isset($_GET['id']) ? intval($_GET['id']) : 0; if (!$subscription_id) { wp_die(__('无效的订阅ID', 'yoone-subscriptions')); } global $wpdb; $subscription = $wpdb->get_row($wpdb->prepare( "SELECT * FROM {$wpdb->prefix}yoone_subscriptions WHERE id = %d", $subscription_id )); if (!$subscription) { wp_die(__('订阅不存在', 'yoone-subscriptions')); } // 获取订阅项目 $items = $wpdb->get_results($wpdb->prepare( "SELECT * FROM {$wpdb->prefix}yoone_subscription_items WHERE subscription_id = %d", $subscription_id )); // 获取日志 $logs = $wpdb->get_results($wpdb->prepare( "SELECT * FROM {$wpdb->prefix}yoone_subscription_logs WHERE subscription_id = %d ORDER BY created_at DESC LIMIT 50", $subscription_id )); include YOONE_SUBSCRIPTIONS_PLUGIN_PATH . 'templates/admin/subscription-view.php'; } /** * 编辑订阅 */ private function edit_subscription() { $subscription_id = isset($_GET['id']) ? intval($_GET['id']) : 0; if (!$subscription_id) { wp_die(__('无效的订阅ID', 'yoone-subscriptions')); } // 处理表单提交 if (isset($_POST['submit'])) { $this->save_subscription($subscription_id); } global $wpdb; $subscription = $wpdb->get_row($wpdb->prepare( "SELECT * FROM {$wpdb->prefix}yoone_subscriptions WHERE id = %d", $subscription_id )); if (!$subscription) { wp_die(__('订阅不存在', 'yoone-subscriptions')); } include YOONE_SUBSCRIPTIONS_PLUGIN_PATH . 'templates/admin/subscription-edit.php'; } /** * 保存订阅 */ private function save_subscription($subscription_id) { if (!wp_verify_nonce($_POST['_wpnonce'], 'edit_subscription_' . $subscription_id)) { wp_die(__('安全验证失败', 'yoone-subscriptions')); } global $wpdb; $update_data = array( 'status' => sanitize_text_field($_POST['status']), 'next_payment_date' => sanitize_text_field($_POST['next_payment_date']), 'updated_at' => current_time('mysql') ); $result = $wpdb->update( $wpdb->prefix . 'yoone_subscriptions', $update_data, array('id' => $subscription_id) ); if ($result !== false) { add_action('admin_notices', function() { echo '

' . __('订阅已更新', 'yoone-subscriptions') . '

'; }); } } /** * 混装产品页面 */ public function bundles_page() { $action = isset($_GET['action']) ? $_GET['action'] : 'list'; switch ($action) { case 'add': $this->add_bundle(); break; case 'edit': $this->edit_bundle(); break; case 'delete': $this->delete_bundle(); break; default: $this->list_bundles(); break; } } /** * 添加混装产品 */ private function add_bundle() { if (isset($_POST['submit'])) { $this->save_bundle(); } include YOONE_SUBSCRIPTIONS_PLUGIN_PATH . 'templates/admin/bundle-add.php'; } /** * 编辑混装产品 */ private function edit_bundle() { $bundle_id = isset($_GET['id']) ? intval($_GET['id']) : 0; if (!$bundle_id) { wp_die(__('无效的混装产品ID', 'yoone-subscriptions')); } if (isset($_POST['submit'])) { $this->save_bundle($bundle_id); } global $wpdb; $bundle = $wpdb->get_row($wpdb->prepare( "SELECT * FROM {$wpdb->prefix}yoone_bundles WHERE id = %d", $bundle_id )); if (!$bundle) { wp_die(__('混装产品不存在', 'yoone-subscriptions')); } $items = $wpdb->get_results($wpdb->prepare( "SELECT * FROM {$wpdb->prefix}yoone_bundle_items WHERE bundle_id = %d ORDER BY sort_order", $bundle_id )); include YOONE_SUBSCRIPTIONS_PLUGIN_PATH . 'templates/admin/bundle-edit.php'; } /** * 删除混装产品 */ private function delete_bundle() { $bundle_id = isset($_GET['id']) ? intval($_GET['id']) : 0; if (!$bundle_id) { wp_die(__('无效的混装产品ID', 'yoone-subscriptions')); } if (!wp_verify_nonce($_GET['_wpnonce'], 'delete_bundle_' . $bundle_id)) { wp_die(__('安全验证失败', 'yoone-subscriptions')); } global $wpdb; // 删除混装项目 $wpdb->delete( $wpdb->prefix . 'yoone_bundle_items', array('bundle_id' => $bundle_id) ); // 删除混装产品 $result = $wpdb->delete( $wpdb->prefix . 'yoone_bundles', array('id' => $bundle_id) ); if ($result) { wp_redirect(admin_url('admin.php?page=yoone-bundles&deleted=1')); exit; } else { wp_die(__('删除失败', 'yoone-subscriptions')); } } /** * 保存混装产品 */ private function save_bundle($bundle_id = 0) { $nonce_action = $bundle_id ? 'edit_bundle_' . $bundle_id : 'add_bundle'; if (!wp_verify_nonce($_POST['_wpnonce'], $nonce_action)) { wp_die(__('安全验证失败', 'yoone-subscriptions')); } global $wpdb; $bundle_data = array( 'name' => sanitize_text_field($_POST['name']), 'description' => sanitize_textarea_field($_POST['description']), 'discount_type' => sanitize_text_field($_POST['discount_type']), 'discount_value' => floatval($_POST['discount_value']), 'status' => sanitize_text_field($_POST['status']), 'updated_at' => current_time('mysql') ); if ($bundle_id) { // 更新现有混装产品 $result = $wpdb->update( $wpdb->prefix . 'yoone_bundles', $bundle_data, array('id' => $bundle_id) ); } else { // 创建新混装产品 $bundle_data['created_at'] = current_time('mysql'); $result = $wpdb->insert( $wpdb->prefix . 'yoone_bundles', $bundle_data ); $bundle_id = $wpdb->insert_id; } if ($result !== false) { // 保存混装项目 if (isset($_POST['bundle_items']) && is_array($_POST['bundle_items'])) { // 删除现有项目 $wpdb->delete( $wpdb->prefix . 'yoone_bundle_items', array('bundle_id' => $bundle_id) ); // 添加新项目 foreach ($_POST['bundle_items'] as $sort_order => $item) { $wpdb->insert( $wpdb->prefix . 'yoone_bundle_items', array( 'bundle_id' => $bundle_id, 'product_id' => intval($item['product_id']), 'quantity' => intval($item['quantity']), 'sort_order' => intval($sort_order) ) ); } } wp_redirect(admin_url('admin.php?page=yoone-bundles&saved=1')); exit; } else { wp_die(__('保存失败', 'yoone-subscriptions')); } } /** * 混装产品列表 */ private function list_bundles() { global $wpdb; $bundles = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}yoone_bundles ORDER BY created_at DESC" ); include YOONE_SUBSCRIPTIONS_PLUGIN_PATH . 'templates/admin/bundles-list.php'; } /** * 支付设置页面 */ public function payment_settings_page() { if (isset($_POST['submit'])) { $this->save_payment_settings(); } include YOONE_SUBSCRIPTIONS_PLUGIN_PATH . 'templates/admin/payment-settings.php'; } /** * 保存支付设置 */ private function save_payment_settings() { if (!wp_verify_nonce($_POST['_wpnonce'], 'yoone_payment_settings')) { wp_die(__('安全验证失败', 'yoone-subscriptions')); } $settings = array( 'yoone_moneris_enabled' => isset($_POST['moneris_enabled']) ? 'yes' : 'no', 'yoone_moneris_testmode' => isset($_POST['moneris_testmode']) ? 'yes' : 'no', 'yoone_moneris_store_id' => sanitize_text_field($_POST['moneris_store_id']), 'yoone_moneris_api_token' => sanitize_text_field($_POST['moneris_api_token']), ); foreach ($settings as $key => $value) { update_option($key, $value); } add_action('admin_notices', function() { echo '

' . __('设置已保存', 'yoone-subscriptions') . '

'; }); } /** * 报告页面 */ public function reports_page() { include YOONE_SUBSCRIPTIONS_PLUGIN_PATH . 'templates/admin/reports.php'; } /** * 添加产品数据标签 */ public function add_product_data_tabs($tabs) { $tabs['yoone_subscription'] = array( 'label' => __('订阅设置', 'yoone-subscriptions'), 'target' => 'yoone_subscription_data', 'class' => array('show_if_simple', 'show_if_variable'), ); $tabs['yoone_bundle'] = array( 'label' => __('混装设置', 'yoone-subscriptions'), 'target' => 'yoone_bundle_data', 'class' => array('show_if_yoone_bundle'), ); return $tabs; } /** * 添加产品数据面板 */ public function add_product_data_panels() { global $post; // 订阅设置面板 echo '
'; woocommerce_wp_checkbox(array( 'id' => '_yoone_subscription_enabled', 'label' => __('启用订阅', 'yoone-subscriptions'), 'description' => __('将此产品设置为订阅产品', 'yoone-subscriptions'), )); woocommerce_wp_select(array( 'id' => '_yoone_subscription_trial_period', 'label' => __('试用期', 'yoone-subscriptions'), 'options' => array( '' => __('无试用期', 'yoone-subscriptions'), '7' => __('7天', 'yoone-subscriptions'), '14' => __('14天', 'yoone-subscriptions'), '30' => __('30天', 'yoone-subscriptions'), ), )); echo '
'; echo '

' . __('订阅周期', 'yoone-subscriptions') . '

'; $periods = get_post_meta($post->ID, '_yoone_subscription_periods', true); if (!is_array($periods)) { $periods = array(); } echo '
'; foreach ($periods as $key => $period) { $this->render_subscription_period_row($key, $period); } echo '
'; echo ''; echo '
'; echo '
'; // 混装设置面板 echo '
'; woocommerce_wp_text_input(array( 'id' => '_yoone_bundle_min_quantity', 'label' => __('最小数量', 'yoone-subscriptions'), 'type' => 'number', 'custom_attributes' => array('min' => '1'), )); woocommerce_wp_select(array( 'id' => '_yoone_bundle_discount_type', 'label' => __('折扣类型', 'yoone-subscriptions'), 'options' => array( 'percentage' => __('百分比', 'yoone-subscriptions'), 'fixed' => __('固定金额', 'yoone-subscriptions'), ), )); woocommerce_wp_text_input(array( 'id' => '_yoone_bundle_discount_value', 'label' => __('折扣值', 'yoone-subscriptions'), 'type' => 'number', 'custom_attributes' => array('step' => '0.01', 'min' => '0'), )); echo '
'; echo '

' . __('混装项目', 'yoone-subscriptions') . '

'; echo '
'; echo ''; echo '
'; echo '
'; } /** * 渲染订阅周期行 */ private function render_subscription_period_row($key, $period) { echo '
'; echo ''; echo ''; echo ''; echo ''; echo ''; echo '
'; } /** * 保存产品元数据 */ public function save_product_meta($post_id) { // 保存订阅设置 $subscription_enabled = isset($_POST['_yoone_subscription_enabled']) ? 'yes' : 'no'; update_post_meta($post_id, '_yoone_subscription_enabled', $subscription_enabled); if (isset($_POST['_yoone_subscription_trial_period'])) { update_post_meta($post_id, '_yoone_subscription_trial_period', sanitize_text_field($_POST['_yoone_subscription_trial_period'])); } if (isset($_POST['_yoone_subscription_periods'])) { update_post_meta($post_id, '_yoone_subscription_periods', $_POST['_yoone_subscription_periods']); } // 保存混装设置 if (isset($_POST['_yoone_bundle_min_quantity'])) { update_post_meta($post_id, '_yoone_bundle_min_quantity', intval($_POST['_yoone_bundle_min_quantity'])); } if (isset($_POST['_yoone_bundle_discount_type'])) { update_post_meta($post_id, '_yoone_bundle_discount_type', sanitize_text_field($_POST['_yoone_bundle_discount_type'])); } if (isset($_POST['_yoone_bundle_discount_value'])) { update_post_meta($post_id, '_yoone_bundle_discount_value', floatval($_POST['_yoone_bundle_discount_value'])); } } /** * 添加产品类型 */ public function add_product_types($types) { $types['yoone_bundle'] = __('混装产品', 'yoone-subscriptions'); return $types; } /** * 添加订单元框 */ public function add_order_meta_boxes() { add_meta_box( 'yoone-subscription-info', __('订阅信息', 'yoone-subscriptions'), array($this, 'order_subscription_meta_box'), 'shop_order', 'side', 'default' ); } /** * 订单订阅信息元框 */ public function order_subscription_meta_box($post) { global $wpdb; $subscriptions = $wpdb->get_results($wpdb->prepare( "SELECT * FROM {$wpdb->prefix}yoone_subscriptions WHERE parent_order_id = %d", $post->ID )); if (empty($subscriptions)) { echo '

' . __('此订单没有关联的订阅', 'yoone-subscriptions') . '

'; return; } foreach ($subscriptions as $subscription) { echo '
'; echo '

' . __('订阅ID:', 'yoone-subscriptions') . ' ' . $subscription->id . '

'; echo '

' . __('状态:', 'yoone-subscriptions') . ' ' . Yoone_Frontend::get_subscription_status_label($subscription->status) . '

'; echo '

' . __('下次付款:', 'yoone-subscriptions') . ' ' . $subscription->next_payment_date . '

'; echo '

' . __('查看详情', 'yoone-subscriptions') . '

'; echo '
'; } } /** * 处理订单状态变化 */ public function handle_order_status_change($order_id, $old_status, $new_status, $order) { if ($new_status === 'completed') { $this->create_subscription_from_order($order); } } /** * 从订单创建订阅 */ private function create_subscription_from_order($order) { foreach ($order->get_items() as $item) { $product_id = $item->get_product_id(); $subscription_enabled = get_post_meta($product_id, '_yoone_subscription_enabled', true); if ($subscription_enabled === 'yes') { $subscription_period = $item->get_meta('_yoone_subscription_period'); if ($subscription_period) { $this->create_subscription($order, $item, $subscription_period); } } } } /** * 创建订阅 */ private function create_subscription($order, $item, $period) { global $wpdb; $subscription_data = array( 'customer_id' => $order->get_customer_id(), 'parent_order_id' => $order->get_id(), 'status' => 'active', 'billing_period' => $period['period'], 'billing_interval' => $period['interval'], 'total' => $item->get_total(), 'currency' => $order->get_currency(), 'payment_method' => $order->get_payment_method(), 'payment_method_title' => $order->get_payment_method_title(), 'next_payment_date' => $this->calculate_next_payment_date($period), 'start_date' => current_time('mysql'), 'created_at' => current_time('mysql'), ); $result = $wpdb->insert( $wpdb->prefix . 'yoone_subscriptions', $subscription_data ); if ($result) { $subscription_id = $wpdb->insert_id; // 创建订阅项目 $wpdb->insert( $wpdb->prefix . 'yoone_subscription_items', array( 'subscription_id' => $subscription_id, 'product_id' => $item->get_product_id(), 'variation_id' => $item->get_variation_id(), 'quantity' => $item->get_quantity(), 'price' => $item->get_total() / $item->get_quantity(), ) ); // 记录日志 Yoone_Logger::info("从订单 {$order->get_id()} 创建订阅 {$subscription_id}"); } } /** * 计算下次付款日期 */ private function calculate_next_payment_date($period) { $interval = $period['interval']; $period_type = $period['period']; switch ($period_type) { case 'day': return date('Y-m-d H:i:s', strtotime("+{$interval} days")); case 'week': return date('Y-m-d H:i:s', strtotime("+{$interval} weeks")); case 'month': return date('Y-m-d H:i:s', strtotime("+{$interval} months")); case 'year': return date('Y-m-d H:i:s', strtotime("+{$interval} years")); default: return date('Y-m-d H:i:s', strtotime("+1 month")); } } /** * 添加产品列 */ public function add_product_columns($columns) { $columns['yoone_subscription'] = __('订阅', 'yoone-subscriptions'); $columns['yoone_bundle'] = __('混装', 'yoone-subscriptions'); return $columns; } /** * 产品列内容 */ public function product_column_content($column, $post_id) { switch ($column) { case 'yoone_subscription': $enabled = get_post_meta($post_id, '_yoone_subscription_enabled', true); echo $enabled === 'yes' ? '' : '—'; break; case 'yoone_bundle': $product = wc_get_product($post_id); echo $product && $product->get_type() === 'yoone_bundle' ? '' : '—'; break; } } /** * 添加设置标签 */ public function add_settings_tab($settings_tabs) { $settings_tabs['yoone_subscriptions'] = __('Yoone 订阅', 'yoone-subscriptions'); return $settings_tabs; } /** * 设置标签内容 */ public function settings_tab_content() { woocommerce_admin_fields($this->get_settings()); } /** * 更新设置 */ public function update_settings() { woocommerce_update_options($this->get_settings()); } /** * 获取设置字段 */ private function get_settings() { return array( 'section_title' => array( 'name' => __('Yoone 订阅设置', 'yoone-subscriptions'), 'type' => 'title', 'desc' => '', 'id' => 'yoone_subscriptions_section_title' ), 'subscription_enabled' => array( 'name' => __('启用订阅功能', 'yoone-subscriptions'), 'type' => 'checkbox', 'desc' => __('启用订阅功能', 'yoone-subscriptions'), 'id' => 'yoone_subscriptions_enabled' ), 'bundle_enabled' => array( 'name' => __('启用混装功能', 'yoone-subscriptions'), 'type' => 'checkbox', 'desc' => __('启用混装产品功能', 'yoone-subscriptions'), 'id' => 'yoone_bundles_enabled' ), 'section_end' => array( 'type' => 'sectionend', 'id' => 'yoone_subscriptions_section_end' ) ); } /** * 管理通知 */ public function admin_notices() { // 检查WooCommerce依赖 if (!class_exists('WooCommerce')) { echo '

'; echo __('Yoone Subscriptions 需要 WooCommerce 插件才能正常工作。', 'yoone-subscriptions'); echo '

'; } } }