文章目录
-
- 在文创产品领域,柔性订阅制服务正成为新的商业模式。与传统的固定周期订阅不同,柔性订阅允许用户根据自身需求灵活调整订阅频率、产品和时长。本教程将指导您开发一个完整的WordPress文创产品柔性订阅制服务插件。
- 首先,我们创建插件的基本文件结构: <?php /** * Plugin Name: 文创柔性订阅制服务 * Plugin URI: https://yourwebsite.com/ * Description: 为文创产品提供柔性订阅制服务解决方案 * Version: 1.0.0 * Author: 您的名称 * License: GPL v2 or later * Text Domain: cultural-subscription */ // 防止直接访问 if (!defined('ABSPATH')) { exit; } // 定义插件常量 define('CULTURAL_SUBSCRIPTION_VERSION', '1.0.0'); define('CULTURAL_SUBSCRIPTION_PLUGIN_DIR', plugin_dir_path(__FILE__)); define('CULTURAL_SUBSCRIPTION_PLUGIN_URL', plugin_dir_url(__FILE__)); // 初始化插件 class CulturalSubscription { private static $instance = null; 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() { // 激活/停用钩子 register_activation_hook(__FILE__, array($this, 'activate')); register_deactivation_hook(__FILE__, array($this, 'deactivate')); // 初始化 add_action('init', array($this, 'init')); // 管理菜单 add_action('admin_menu', array($this, 'add_admin_menu')); // 加载文本域 add_action('plugins_loaded', array($this, 'load_textdomain')); } public function activate() { // 创建必要的数据库表 $this->create_tables(); // 设置默认选项 $this->set_default_options(); // 刷新重写规则 flush_rewrite_rules(); } public function deactivate() { // 清理临时数据 // 注意:不删除用户订阅数据 flush_rewrite_rules(); } public function load_textdomain() { load_plugin_textdomain( 'cultural-subscription', false, dirname(plugin_basename(__FILE__)) . '/languages' ); } public function init() { // 注册自定义文章类型和分类 $this->register_post_types(); } public function add_admin_menu() { // 添加管理菜单 add_menu_page( __('文创订阅', 'cultural-subscription'), __('文创订阅', 'cultural-subscription'), 'manage_options', 'cultural-subscription', array($this, 'admin_dashboard'), 'dashicons-products', 30 ); } private function create_tables() { global $wpdb; $charset_collate = $wpdb->get_charset_collate(); $table_name = $wpdb->prefix . 'cultural_subscriptions'; $sql = "CREATE TABLE IF NOT EXISTS $table_name ( id bigint(20) NOT NULL AUTO_INCREMENT, user_id bigint(20) NOT NULL, plan_id bigint(20) NOT NULL, product_ids text NOT NULL, subscription_type varchar(50) NOT NULL, frequency varchar(20) NOT NULL, next_delivery_date date NOT NULL, status varchar(20) DEFAULT 'active', created_at datetime DEFAULT CURRENT_TIMESTAMP, updated_at datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY user_id (user_id), KEY status (status) ) $charset_collate;"; require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); dbDelta($sql); } private function set_default_options() { $default_options = array( 'currency' => 'CNY', 'min_subscription_period' => 1, // 月 'max_subscription_period' => 12, // 月 'grace_period' => 7, // 天 'auto_renew' => true, ); add_option('cultural_subscription_settings', $default_options); } private function register_post_types() { // 注册订阅计划类型 register_post_type('subscription_plan', array( 'labels' => array( 'name' => __('订阅计划', 'cultural-subscription'), 'singular_name' => __('订阅计划', 'cultural-subscription') ), 'public' => true, 'has_archive' => true, 'supports' => array('title', 'editor', 'thumbnail'), 'menu_icon' => 'dashicons-calendar-alt', 'rewrite' => array('slug' => 'subscription-plans'), ) ); } public function admin_dashboard() { // 管理面板HTML ?> <div class="wrap"> <h1><?php echo esc_html(get_admin_page_title()); ?></h1> <div class="cultural-subscription-dashboard"> <div class="dashboard-stats"> <div class="stat-card"> <h3><?php _e('活跃订阅', 'cultural-subscription'); ?></h3> <p class="stat-number">0</p> </div> <div class="stat-card"> <h3><?php _e('本月收入', 'cultural-subscription'); ?></h3> <p class="stat-number">¥0</p> </div> </div> </div> </div> <?php } } // 启动插件 CulturalSubscription::get_instance(); ?>
- 创建订阅计划管理类,处理柔性订阅的核心逻辑: <?php /** * 订阅计划管理类 */ class SubscriptionPlanManager { private $db; public function __construct() { global $wpdb; $this->db = $wpdb; } /** * 创建柔性订阅计划 * @param array $plan_data 计划数据 * @return int|false 计划ID或false */ public function create_flexible_plan($plan_data) { $defaults = array( 'title' => '', 'description' => '', 'base_price' => 0, 'frequency_options' => array('monthly', 'quarterly', 'yearly'), 'min_products' => 1, 'max_products' => 5, 'allow_customization' => true, 'status' => 'draft' ); $plan_data = wp_parse_args($plan_data, $defaults); // 验证数据 if (empty($plan_data['title']) || $plan_data['base_price'] <= 0) { return false; } // 插入到自定义文章类型 $post_id = wp_insert_post(array( 'post_title' => sanitize_text_field($plan_data['title']), 'post_content' => wp_kses_post($plan_data['description']), 'post_type' => 'subscription_plan', 'post_status' => $plan_data['status'], 'meta_input' => array( '_base_price' => floatval($plan_data['base_price']), '_frequency_options' => $plan_data['frequency_options'], '_min_products' => intval($plan_data['min_products']), '_max_products' => intval($plan_data['max_products']), '_allow_customization' => (bool)$plan_data['allow_customization'] ) )); return $post_id; } /** * 计算订阅价格 * @param int $plan_id 计划ID * @param array $options 用户选项 * @return float 总价格 */ public function calculate_price($plan_id, $options) { $base_price = get_post_meta($plan_id, '_base_price', true); $frequency = $options['frequency'] ?? 'monthly'; $product_count = count($options['products'] ?? array()); // 频率折扣系数 $frequency_multiplier = array( 'monthly' => 1.0, 'quarterly' => 0.95, // 5%折扣 'yearly' => 0.85 // 15%折扣 ); // 产品数量系数(鼓励多选) $product_multiplier = 1.0; if ($product_count > 1) { $product_multiplier = 0.9 + (0.05 * $product_count); // 每多一个产品增加5%折扣 } // 计算总价 $total_price = $base_price * ($frequency_multiplier[$frequency] ?? 1.0) * $product_multiplier; return round($total_price, 2); } /** * 获取可用的订阅计划 * @return array 计划列表 */ public function get_available_plans() { $args = array( 'post_type' => 'subscription_plan', 'post_status' => 'publish', 'posts_per_page' => -1, 'meta_query' => array( array( 'key' => '_base_price', 'value' => 0, 'compare' => '>', 'type' => 'NUMERIC' ) ) ); $plans = get_posts($args); $formatted_plans = array(); foreach ($plans as $plan) { $formatted_plans[] = array( 'id' => $plan->ID, 'title' => $plan->post_title, 'description' => $plan->post_content, 'base_price' => get_post_meta($plan->ID, '_base_price', true), 'frequency_options' => get_post_meta($plan->ID, '_frequency_options', true), 'features' => $this->extract_features($plan->post_content) ); } return $formatted_plans; } /** * 从描述中提取特性 * @param string $content 描述内容 * @return array 特性列表 */ private function extract_features($content) { // 简单的特性提取逻辑 $features = array(); $lines = explode("n", strip_tags($content)); foreach ($lines as $line) { $trimmed = trim($line); if (strlen($trimmed) > 3 && !empty($trimmed)) { $features[] = $trimmed; } } return array_slice($features, 0, 5); // 最多返回5个特性 } } ?>
- 创建前端用户界面,让用户可以管理自己的订阅: <?php /** * 用户订阅前端界面 */ class SubscriptionFrontend { public function __construct() { add_shortcode('cultural_subscription_plans', array($this, 'render_subscription_plans')); add_shortcode('cultural_my_subscriptions', array($this, 'render_my_subscriptions')); add_action('wp_enqueue_scripts', array($this, 'enqueue_frontend_scripts')); } /** * 渲染订阅计划选择页面 */ public function render_subscription_plans() { if (!is_user_logged_in()) { return '<div class="subscription-login-required">' . __('请先登录以查看订阅计划', 'cultural-subscription') . '</div>'; } $manager = new SubscriptionPlanManager(); $plans = $manager->get_available_plans(); ob_start(); ?> <div class="cultural-subscription-plans"> <h2><?php _e('选择您的文创订阅计划', 'cultural-subscription'); ?></h2> <div class="plans-container"> <?php foreach ($plans as $plan): ?> <div class="subscription-plan-card"> <h3><?php echo esc_html($plan['title']); ?></h3> <div class="plan-price"> <span class="base-price">¥<?php echo number_format($plan['base_price'], 2); ?></span> <span class="period">/月</span> </div> <div class="plan-features"> <ul> <?php foreach ($plan['features'] as $feature): ?> <li><?php echo esc_html($feature); ?></li> <?php endforeach; ?> </ul> </div> <div class="frequency-options"> <h4><?php _e('选择频率:', 'cultural-subscription'); ?></h4> <?php foreach ($plan['frequency_options'] as $freq): ?> <label class="frequency-option"> <input type="radio" name="frequency_<?php echo $plan['id']; ?>" value="<?php echo esc_attr($freq); ?>" data-plan-id="<?php echo $plan['id']; ?>"> <?php echo $this->get_frequency_label($freq); ?> </label> <?php endforeach; ?> </div> <button class="select-plan-btn" data-plan-id="<?php echo $plan['id']; ?>"> <?php _e('选择此计划', 'cultural-subscription'); ?> </button> </div> <?php endforeach; ?> </div> <!-- 产品选择模态框 --> <div id="product-selection-modal" class="modal"> <div class="modal-content"> <span class="close-modal">×</span> <h3><?php _e('选择文创产品', 'cultural-subscription'); ?></h3> <div id="product-selection-area"></div> <button id="confirm-subscription" class="button-primary"> <?php _e('确认订阅', 'cultural-subscription'); ?> </button> </div> </div> </div> <?php return ob_get_clean(); } /** * 渲染用户当前订阅 */ public function render_my_subscriptions() { if (!is_user_logged_in()) { return ''; } $user_id = get_current_user_id(); $subscriptions = $this->get_user_subscriptions($user_id); ob_start(); ?> <div class="my-subscriptions"> <h2><?php _e('我的订阅', 'cultural-subscription'); ?></h2> <?php if (empty($subscriptions)): ?> <p><?php _e('您当前没有活跃的订阅。', 'cultural-subscription'); ?></p> <?php else: ?> <div class="subscriptions-list"> <?php foreach ($subscriptions as $subscription): ?> <div class="subscription-item"> <div class="subscription-header"> <h3><?php echo get_the_title($subscription->plan_id); ?></h3> <span class="status-badge <?php echo esc_attr($subscription->status); ?>"> <?php echo $this->get_status_label($subscription->status); ?> </span> </div> <div class="subscription-details"> <p><strong><?php _e('频率:', 'cultural-subscription'); ?></strong> <?php echo $this->get_frequency_label($subscription->frequency); ?> </p> <p><strong><?php _e('下次配送:', 'cultural-subscription'); ?></strong> <?php echo date_i18n(get_option('date_format'), strtotime($subscription->next_delivery_date)); ?> </p> <div class="subscription-actions"> <button class="button modify-subscription" data-subscription-id="<?php echo $subscription->id; ?>"> <?php _e('修改订阅', 'cultural-subscription'); ?> </button> <button class="button cancel-subscription" data-subscription-id="<?php echo $subscription->id; ?>"> <?php _e('取消订阅', 'cultural-subscription'); ?> </button> </div> </div> </div> <?php endforeach; ?> </div> <?php endif; ?> </div> <?php return ob_get_clean(); } /** * 获取用户订阅 */ private function get_user_subscriptions($user_id) { global $wpdb; $table_name = $wpdb->prefix . 'cultural_subscriptions'; return $wpdb->get_results($wpdb->prepare( "SELECT * FROM $table_name WHERE user_id = %d ORDER BY created_at DESC", $user_id )); } /** * 获取频率标签 */ private function get_frequency_label($frequency) { $labels = array( 'monthly' => __('每月', 'cultural-subscription'), 'quarterly' => __('每季度', 'cultural-subscription'), 'yearly' => __('每年', 'cultural-subscription') ); return $labels[$frequency] ?? $frequency; } /** * 获取状态标签 */ private function get_status_label($status) { $labels = array( 'active' => __('活跃', 'cultural-subscription'), 'paused' => __('已暂停', 'cultural-subscription'), 'cancelled' => __('已取消', 'cultural-subscription'), 'expired' => __('已过期', 'cultural-subscription') ); return $labels[$status] ?? $status; } /** * 加载前端脚本和样式 */ public function enqueue_frontend_scripts() { wp_enqueue_style( 'cultural-subscription-frontend', CULTURAL_SUBSCRIPTION_PLUGIN_URL . 'assets/css/frontend.css', array(), CULTURAL_SUBSCRIPTION_VERSION ); wp_enqueue_script( 'cultural-subscription-frontend', CULTURAL_SUBSCRIPTION_PLUGIN_URL . 'assets/js/frontend.js', array('jquery'), CULTURAL_SUBSCRIPTION_VERSION, true ); wp_localize_script('cultural-subscription-frontend', 'culturalSubscription', array( 'ajax_url' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('cultural_subscription_nonce'), 'i18n' => array( 'confirm_cancel' => __('确定要取消订阅吗?', 'cultural-subscription'), 'loading' => __('加载中...', 'cultural-subscription'), 'error' => __('发生错误,请重试', 'cultural-subscription') ) )); } } // 初始化前端 new SubscriptionFrontend(); ?> ## 五、AJAX处理与支付集成 创建AJAX处理器和支付集成模块: <?php/** AJAX处理器 */ class SubscriptionAjaxHandler { public function __construct() { // 订阅相关AJAX add_action('wp_ajax_create_subscription', array($this, 'handle_create_subscription')); add_action('wp_ajax_nopriv_create_subscription', array($this, 'handle_no_privilege')); add_action('wp_ajax_modify_subscription', array($this, 'handle_modify_subscription')); add_action('wp_ajax_cancel_subscription', array($this, 'handle_cancel_subscription')); // 产品选择 add_action('wp_ajax_get_products_for_plan', array($this, 'handle_get_products')); } /** * 创建订阅 */ public function handle_create_subscription() { // 验证nonce if (!wp_verify_nonce($_POST['nonce'], 'cultural_subscription_nonce')) { wp_die('非法请求'); } // 验证用户 if (!is_user_logged_in()) { wp_send_json_error(array('message' => '请先登录')); } $user_id = get_current_user_id(); $plan_id = intval($_POST['plan_id']); $frequency = sanitize_text_field($_POST['frequency']); $product_ids = array_map('intval', $_POST['product_ids'] ?? array()); // 验证数据 if (!$plan_id || empty($product_ids)) { wp_send_json_error(array('message' => '请选择产品和计划')); } // 检查计划是否存在 $plan = get_post($plan_id); if (!$plan || $plan->post_type !== 'subscription_plan') { wp_send_json_error(array('message' => '订阅计划不存在')); } // 创建订阅记录 $subscription_id = $this->create_subscription_record(array( 'user_id' => $user_id, 'plan_id' => $plan_id, 'product_ids' => $product_ids, 'frequency' => $frequency, 'status' => 'pending_payment' )); if (!$subscription_id) { wp_send_json_error(array('message' => '创建订阅失败')); } // 生成支付 $payment_data = $this->create_payment($subscription_id); wp_send_json_success(array( 'message' => '订阅创建成功', 'subscription_id' => $subscription_id, 'payment_data' => $payment_data )); } /** * 创建订阅记录 */ private function create_subscription_record($data) { global $wpdb; $table_name = $wpdb->prefix . 'cultural_subscriptions'; // 计算下次配送日期 $next_delivery = $this->calculate_next_delivery($data['frequency']); $result = $wpdb->insert($table_name, array( 'user_id' => $data['user_id'], 'plan_id' => $data['plan_id'], 'product_ids' => json_encode($data['product_ids']), 'subscription_type' => 'flexible', 'frequency' => $data['frequency'], 'next_delivery_date' => $next_delivery, 'status' => $data['status'] )); return $result ? $wpdb->insert_id : false; } /** * 计算下次配送日期 */ private function calculate_next_delivery($frequency) { $today = current_time('Y-m-d'); switch ($frequency) { case 'monthly': return date('Y-m-d', strtotime($today . ' +1 month')); case 'quarterly': return date('Y-m-d', strtotime($today . ' +3 months')); case 'yearly': return date('Y-m-d', strtotime($today . ' +1 year')); default: return date('Y-m-d', strtotime($today . ' +1 month')); } } /** * 创建支付 */ private function create_payment($subscription_id) { // 这里集成支付网关 // 示例:使用WooCommerce支付 if (class_exists('WooCommerce')) { return $this->create_woocommerce_payment($subscription_id); } // 或者使用其他支付网关 return array( 'type' => 'manual', 'message' => '请等待管理员确认支付' ); } /** * 创建WooCommerce支付 */ private function create_woocommerce_payment($subscription_id) { global $wpdb; // 获取订阅信息 $table_name = $wpdb->prefix . 'cultural_subscriptions'; $subscription = $wpdb->get_row($wpdb->prepare( "SELECT * FROM $table_name WHERE id = %d", $subscription_id )); if (!$subscription) { return false; } // 创建订单 $order = wc_create_order(array( 'customer_id' => $subscription->user_id, 'created_via' => 'cultural_subscription' )); // 获取计划价格 $plan_manager = new SubscriptionPlanManager(); $price = $plan_manager->calculate_price( $subscription->plan_id, array( 'frequency' => $subscription->frequency, 'products' => json_decode($subscription->product_ids, true) ) ); // 添加产品到订单 $product_ids = json_decode($subscription->product_ids, true); foreach ($product_ids as $product_id) { $product = wc_get_product($product_id); if ($product) { $order->add_product($product, 1); } } // 设置订阅费用 $order->add_meta_data('_subscription_id', $subscription_id); $order->add_meta_data('_subscription_frequency', $subscription->frequency); $order->set_total($price); $order->save(); return array( 'type' => 'woocommerce', 'order_id' => $order->get_id(), 'payment_url' => $order->get_checkout_payment_url() ); } /** * 修改订阅 */ public function handle_modify_subscription() { // 验证nonce和用户权限 if (!wp_verify_nonce($_POST['nonce'], 'cultural_subscription_nonce') || !is_user_logged_in()) { wp_die('非法请求'); } $subscription_id = intval($_POST['subscription_id']); $user_id = get_current_user_id(); // 验证订阅所有权 if (!$this->validate_subscription_ownership($subscription_id, $user_id)) { wp_send_json_error(array('message' => '无权修改此订阅')); } // 获取修改选项 $new_frequency = sanitize_text_field($_POST['new_frequency'] ?? ''); $new_products = array_map('intval', $_POST['new_products'] ?? array()); // 更新订阅 $updated = $this->update_subscription($subscription_id, array( 'frequency' => $new_frequency, 'product_ids' => $new_products )); if ($updated) { wp_send_json_success(array('message' => '订阅修改成功')); } else { wp_send_json_error(array('message' => '修改失败')); } } /** * 验证订阅所有权 */ private function validate_subscription_ownership($subscription_id, $user_id) { global $wpdb; $table_name = $wpdb->prefix . 'cultural_subscriptions'; $subscription = $wpdb->get_row($wpdb->prepare( "SELECT user_id FROM $table_name WHERE id = %d", $subscription_id )); return $subscription && $subscription->user_id == $user_id; } /** * 更新订阅 */ private function update_subscription($subscription_id, $data) { global $wpdb; $table_name = $wpdb->prefix . 'cultural_subscriptions'; $update_data = array(); if (!empty($data['frequency'])) { $update_data['frequency'] = $data['frequency']; // 重新计算下次配送日期 $update_data['next_delivery_date'] = $this->calculate_next_delivery($data['frequency']); } if (!empty($data['product_ids'])) { $update_data['product_ids'] = json_encode($data['product_ids']); } if (empty($update_data)) { return false; } return $wpdb->update( $table_name, $update_data, array('id' => $subscription_id) ); } /** * 取消订阅 */ public function handle_cancel_subscription() { // 验证nonce和用户权限 if (!wp_verify_nonce($_POST['nonce'], 'cultural_subscription_nonce') || !is_user_logged_in()) { wp_die('非法请求'); } $subscription_id = intval($_POST['subscription_id']); $user_id = get_current_user_id(); // 验证订阅所有权 if (!$this->validate_subscription_ownership($subscription_id, $user_id)) { wp_send_json_error(array('message' => '无权取消此订阅')); } // 取消订阅(软删除) $cancelled = $this->cancel_subscription_record($subscription_id); if ($cancelled) { wp_send_json_success(array('message' => '订阅已取消')); } else { wp_send_json_error(array('message' => '取消失败')); } } /** * 取消订阅记录 */ private function cancel_subscription_record($subscription_id) { global $wpdb; $table_name = $wpdb->prefix . 'cultural_subscriptions'; return $wpdb->update( $table_name, array('status' => 'cancelled'), array('id' => $subscription_id) ); } /** * 获取计划相关产品 */ public function handle_get_products() { $plan_id = intval($_POST['plan_id']); // 这里应该根据计划获取相关文创产品 // 示例:获取所有文创产品 $args = array( 'post_type' => 'product', 'posts_per_page' => -1, 'tax_query' => array( array( 'taxonomy' => 'product_cat', 'field' => 'slug', 'terms' => 'cultural-creative' // 文创产品分类 ) ) ); $products = get_posts($args); $formatted_products = array(); foreach ($products as $product) { $product_obj = wc_get_product($product->ID); $formatted_products[] = array( 'id' => $product->ID, 'name' => $product->post_title, 'price' => $product_obj->get_price(), 'image' => get_the_post_thumbnail_url($product->ID, 'thumbnail') ); } wp_send_json_success($formatted_products); } /** * 无权限处理 */ public function handle_no_privilege() { wp_send_json_error(array('message' => '请先登录')); } } // 初始化AJAX处理器new SubscriptionAjaxHandler();?> ## 六、自动化任务与通知系统 创建定时任务和通知系统: <?php/** 自动化任务管理器 */ class SubscriptionAutomation { public function __construct() { // 注册定时任务 add_action('init', array($this, 'schedule_events')); // 定义定时任务钩子 add_action('cultural_subscription_daily_check', array($this, 'daily_check')); add_action('cultural_subscription_process_renewals', array($this, 'process_renewals')); add_action('cultural_subscription_send_reminders', array($this, 'send_reminders')); } /** * 安排定时任务 */ public function schedule_events() { if (!wp_next_scheduled('cultural_subscription_daily_check')) { wp_schedule_event(time(), 'daily', 'cultural_subscription_daily_check'); } if (!wp_next_scheduled('cultural_subscription_process_renewals')) { wp_schedule_event(time(), 'twicedaily', 'cultural_subscription_process_renewals'); } } /** * 每日检查 */ public function daily_check() { $this->check_expiring_subscriptions(); $this->update_subscription_statuses(); $this->cleanup_old_data(); } /** * 检查即将到期的订阅 */ private function check_expiring_subscriptions() { global $wpdb; $table_name = $wpdb->prefix . 'cultural_subscriptions'; // 查找7天内到期的订阅 $seven_days_later = date('Y-m-d', strtotime('+7 days')); $expiring_subscriptions = $wpdb->get_results($wpdb->prepare( "SELECT * FROM $table_name WHERE status = 'active' AND next_delivery_date <= %s AND next_delivery_date > %s", $seven_days_later, current_time('Y-m-d') )); foreach ($expiring_subscriptions as $subscription) { $this->send_expiration_reminder($subscription); } } /** * 发送到期提醒 */ private function send_expiration_reminder($subscription) { $user = get_user_by('id', $subscription->user_id); if (!$user) { return; } $plan_name = get_the_title($subscription->plan_id); $next_delivery = date_i18n(get_option('date_format'), strtotime($subscription->next_delivery_date)); $subject = sprintf(__('您的文创订阅即将配送 - %s', 'cultural-subscription'), $plan_name); $message = sprintf( __('亲爱的%s,<br><br>您的文创订阅"%s"将在%s进行下次配送。<br><br>如需修改配送内容或时间,请登录您的账户进行操作。<br><br>感谢您的订阅!', 'cultural-subscription'), $user->display_name, $plan_name, $next_delivery ); wp_mail($user->user_email, $subject, $message, array('Content-Type: text/html; charset=UTF-8')); } /** * 更新订阅状态 */ private function update_subscription_statuses() { global $wpdb; $table_name = $wpdb->prefix . 'cultural_subscriptions'; // 将过期的订阅标记为过期 $wpdb->query($wpdb->prepare( "UPDATE $table_name SET status = 'expired' WHERE status = 'active' AND next_delivery_date < %s", current_time('Y-m-d') )); } /** * 处理续订 */ public function process_renewals() { global $wpdb; $table_name = $wpdb->prefix . 'cultural_subscriptions'; // 查找需要续订的订阅 $today = current_time('Y-m-d'); $renewal_subscriptions = $wpdb->get_results($wpdb->prepare( "SELECT * FROM $table_name WHERE status = 'active' AND next_delivery_date = %s", $today )); foreach ($renewal_subscriptions as $subscription) { $this->process_single_renewal($subscription); } } /** * 处理单个续订 */ private function process_single_renewal($subscription) { // 创建新订单 $payment_data = $this->create_renewal_payment($subscription); if ($payment_data) { // 更新下次配送日期 $this->update_next_delivery_date($subscription->id); // 发送续订确认 $this->send_renewal_confirmation($subscription); } else { // 支付失败,进入宽限期 $this->handle_payment_failure($subscription); } } /**
在文创产品领域,柔性订阅制服务正成为新的商业模式。与传统的固定周期订阅不同,柔性订阅允许用户根据自身需求灵活调整订阅频率、产品和时长。本教程将指导您开发一个完整的WordPress文创产品柔性订阅制服务插件。
- 多层级订阅计划管理
- 灵活的订阅周期设置
- 用户自主调整订阅内容
- 自动化支付与续费处理
- 订阅状态监控与管理
首先,我们创建插件的基本文件结构:
<?php
/**
* Plugin Name: 文创柔性订阅制服务
* Plugin URI: https://yourwebsite.com/
* Description: 为文创产品提供柔性订阅制服务解决方案
* Version: 1.0.0
* Author: 您的名称
* License: GPL v2 or later
* Text Domain: cultural-subscription
*/
// 防止直接访问
if (!defined('ABSPATH')) {
exit;
}
// 定义插件常量
define('CULTURAL_SUBSCRIPTION_VERSION', '1.0.0');
define('CULTURAL_SUBSCRIPTION_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('CULTURAL_SUBSCRIPTION_PLUGIN_URL', plugin_dir_url(__FILE__));
// 初始化插件
class CulturalSubscription {
private static $instance = null;
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() {
// 激活/停用钩子
register_activation_hook(__FILE__, array($this, 'activate'));
register_deactivation_hook(__FILE__, array($this, 'deactivate'));
// 初始化
add_action('init', array($this, 'init'));
// 管理菜单
add_action('admin_menu', array($this, 'add_admin_menu'));
// 加载文本域
add_action('plugins_loaded', array($this, 'load_textdomain'));
}
public function activate() {
// 创建必要的数据库表
$this->create_tables();
// 设置默认选项
$this->set_default_options();
// 刷新重写规则
flush_rewrite_rules();
}
public function deactivate() {
// 清理临时数据
// 注意:不删除用户订阅数据
flush_rewrite_rules();
}
public function load_textdomain() {
load_plugin_textdomain(
'cultural-subscription',
false,
dirname(plugin_basename(__FILE__)) . '/languages'
);
}
public function init() {
// 注册自定义文章类型和分类
$this->register_post_types();
}
public function add_admin_menu() {
// 添加管理菜单
add_menu_page(
__('文创订阅', 'cultural-subscription'),
__('文创订阅', 'cultural-subscription'),
'manage_options',
'cultural-subscription',
array($this, 'admin_dashboard'),
'dashicons-products',
30
);
}
private function create_tables() {
global $wpdb;
$charset_collate = $wpdb->get_charset_collate();
$table_name = $wpdb->prefix . 'cultural_subscriptions';
$sql = "CREATE TABLE IF NOT EXISTS $table_name (
id bigint(20) NOT NULL AUTO_INCREMENT,
user_id bigint(20) NOT NULL,
plan_id bigint(20) NOT NULL,
product_ids text NOT NULL,
subscription_type varchar(50) NOT NULL,
frequency varchar(20) NOT NULL,
next_delivery_date date NOT NULL,
status varchar(20) DEFAULT 'active',
created_at datetime DEFAULT CURRENT_TIMESTAMP,
updated_at datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY user_id (user_id),
KEY status (status)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
}
private function set_default_options() {
$default_options = array(
'currency' => 'CNY',
'min_subscription_period' => 1, // 月
'max_subscription_period' => 12, // 月
'grace_period' => 7, // 天
'auto_renew' => true,
);
add_option('cultural_subscription_settings', $default_options);
}
private function register_post_types() {
// 注册订阅计划类型
register_post_type('subscription_plan',
array(
'labels' => array(
'name' => __('订阅计划', 'cultural-subscription'),
'singular_name' => __('订阅计划', 'cultural-subscription')
),
'public' => true,
'has_archive' => true,
'supports' => array('title', 'editor', 'thumbnail'),
'menu_icon' => 'dashicons-calendar-alt',
'rewrite' => array('slug' => 'subscription-plans'),
)
);
}
public function admin_dashboard() {
// 管理面板HTML
?>
<div class="wrap">
<h1><?php echo esc_html(get_admin_page_title()); ?></h1>
<div class="cultural-subscription-dashboard">
<div class="dashboard-stats">
<div class="stat-card">
<h3><?php _e('活跃订阅', 'cultural-subscription'); ?></h3>
<p class="stat-number">0</p>
</div>
<div class="stat-card">
<h3><?php _e('本月收入', 'cultural-subscription'); ?></h3>
<p class="stat-number">¥0</p>
</div>
</div>
</div>
</div>
<?php
}
}
// 启动插件
CulturalSubscription::get_instance();
?>
创建订阅计划管理类,处理柔性订阅的核心逻辑:
<?php
/**
* 订阅计划管理类
*/
class SubscriptionPlanManager {
private $db;
public function __construct() {
global $wpdb;
$this->db = $wpdb;
}
/**
* 创建柔性订阅计划
* @param array $plan_data 计划数据
* @return int|false 计划ID或false
*/
public function create_flexible_plan($plan_data) {
$defaults = array(
'title' => '',
'description' => '',
'base_price' => 0,
'frequency_options' => array('monthly', 'quarterly', 'yearly'),
'min_products' => 1,
'max_products' => 5,
'allow_customization' => true,
'status' => 'draft'
);
$plan_data = wp_parse_args($plan_data, $defaults);
// 验证数据
if (empty($plan_data['title']) || $plan_data['base_price'] <= 0) {
return false;
}
// 插入到自定义文章类型
$post_id = wp_insert_post(array(
'post_title' => sanitize_text_field($plan_data['title']),
'post_content' => wp_kses_post($plan_data['description']),
'post_type' => 'subscription_plan',
'post_status' => $plan_data['status'],
'meta_input' => array(
'_base_price' => floatval($plan_data['base_price']),
'_frequency_options' => $plan_data['frequency_options'],
'_min_products' => intval($plan_data['min_products']),
'_max_products' => intval($plan_data['max_products']),
'_allow_customization' => (bool)$plan_data['allow_customization']
)
));
return $post_id;
}
/**
* 计算订阅价格
* @param int $plan_id 计划ID
* @param array $options 用户选项
* @return float 总价格
*/
public function calculate_price($plan_id, $options) {
$base_price = get_post_meta($plan_id, '_base_price', true);
$frequency = $options['frequency'] ?? 'monthly';
$product_count = count($options['products'] ?? array());
// 频率折扣系数
$frequency_multiplier = array(
'monthly' => 1.0,
'quarterly' => 0.95, // 5%折扣
'yearly' => 0.85 // 15%折扣
);
// 产品数量系数(鼓励多选)
$product_multiplier = 1.0;
if ($product_count > 1) {
$product_multiplier = 0.9 + (0.05 * $product_count); // 每多一个产品增加5%折扣
}
// 计算总价
$total_price = $base_price *
($frequency_multiplier[$frequency] ?? 1.0) *
$product_multiplier;
return round($total_price, 2);
}
/**
* 获取可用的订阅计划
* @return array 计划列表
*/
public function get_available_plans() {
$args = array(
'post_type' => 'subscription_plan',
'post_status' => 'publish',
'posts_per_page' => -1,
'meta_query' => array(
array(
'key' => '_base_price',
'value' => 0,
'compare' => '>',
'type' => 'NUMERIC'
)
)
);
$plans = get_posts($args);
$formatted_plans = array();
foreach ($plans as $plan) {
$formatted_plans[] = array(
'id' => $plan->ID,
'title' => $plan->post_title,
'description' => $plan->post_content,
'base_price' => get_post_meta($plan->ID, '_base_price', true),
'frequency_options' => get_post_meta($plan->ID, '_frequency_options', true),
'features' => $this->extract_features($plan->post_content)
);
}
return $formatted_plans;
}
/**
* 从描述中提取特性
* @param string $content 描述内容
* @return array 特性列表
*/
private function extract_features($content) {
// 简单的特性提取逻辑
$features = array();
$lines = explode("n", strip_tags($content));
foreach ($lines as $line) {
$trimmed = trim($line);
if (strlen($trimmed) > 3 && !empty($trimmed)) {
$features[] = $trimmed;
}
}
return array_slice($features, 0, 5); // 最多返回5个特性
}
}
?>
创建前端用户界面,让用户可以管理自己的订阅:
<?php
/**
* 用户订阅前端界面
*/
class SubscriptionFrontend {
public function __construct() {
add_shortcode('cultural_subscription_plans', array($this, 'render_subscription_plans'));
add_shortcode('cultural_my_subscriptions', array($this, 'render_my_subscriptions'));
add_action('wp_enqueue_scripts', array($this, 'enqueue_frontend_scripts'));
}
/**
* 渲染订阅计划选择页面
*/
public function render_subscription_plans() {
if (!is_user_logged_in()) {
return '<div class="subscription-login-required">' .
__('请先登录以查看订阅计划', 'cultural-subscription') .
'</div>';
}
$manager = new SubscriptionPlanManager();
$plans = $manager->get_available_plans();
ob_start();
?>
<div class="cultural-subscription-plans">
<h2><?php _e('选择您的文创订阅计划', 'cultural-subscription'); ?></h2>
<div class="plans-container">
<?php foreach ($plans as $plan): ?>
<div class="subscription-plan-card">
<h3><?php echo esc_html($plan['title']); ?></h3>
<div class="plan-price">
<span class="base-price">¥<?php echo number_format($plan['base_price'], 2); ?></span>
<span class="period">/月</span>
</div>
<div class="plan-features">
<ul>
<?php foreach ($plan['features'] as $feature): ?>
<li><?php echo esc_html($feature); ?></li>
<?php endforeach; ?>
</ul>
</div>
<div class="frequency-options">
<h4><?php _e('选择频率:', 'cultural-subscription'); ?></h4>
<?php foreach ($plan['frequency_options'] as $freq): ?>
<label class="frequency-option">
<input type="radio"
name="frequency_<?php echo $plan['id']; ?>"
value="<?php echo esc_attr($freq); ?>"
data-plan-id="<?php echo $plan['id']; ?>">
<?php echo $this->get_frequency_label($freq); ?>
</label>
<?php endforeach; ?>
</div>
<button class="select-plan-btn"
data-plan-id="<?php echo $plan['id']; ?>">
<?php _e('选择此计划', 'cultural-subscription'); ?>
</button>
</div>
<?php endforeach; ?>
</div>
<!-- 产品选择模态框 -->
<div id="product-selection-modal" class="modal">
<div class="modal-content">
<span class="close-modal">×</span>
<h3><?php _e('选择文创产品', 'cultural-subscription'); ?></h3>
<div id="product-selection-area"></div>
<button id="confirm-subscription" class="button-primary">
<?php _e('确认订阅', 'cultural-subscription'); ?>
</button>
</div>
</div>
</div>
<?php
return ob_get_clean();
}
/**
* 渲染用户当前订阅
*/
public function render_my_subscriptions() {
if (!is_user_logged_in()) {
return '';
}
$user_id = get_current_user_id();
$subscriptions = $this->get_user_subscriptions($user_id);
ob_start();
?>
<div class="my-subscriptions">
<h2><?php _e('我的订阅', 'cultural-subscription'); ?></h2>
<?php if (empty($subscriptions)): ?>
<p><?php _e('您当前没有活跃的订阅。', 'cultural-subscription'); ?></p>
<?php else: ?>
<div class="subscriptions-list">
<?php foreach ($subscriptions as $subscription): ?>
<div class="subscription-item">
<div class="subscription-header">
<h3><?php echo get_the_title($subscription->plan_id); ?></h3>
<span class="status-badge <?php echo esc_attr($subscription->status); ?>">
<?php echo $this->get_status_label($subscription->status); ?>
</span>
</div>
<div class="subscription-details">
<p><strong><?php _e('频率:', 'cultural-subscription'); ?></strong>
<?php echo $this->get_frequency_label($subscription->frequency); ?>
</p>
<p><strong><?php _e('下次配送:', 'cultural-subscription'); ?></strong>
<?php echo date_i18n(get_option('date_format'), strtotime($subscription->next_delivery_date)); ?>
</p>
<div class="subscription-actions">
<button class="button modify-subscription"
data-subscription-id="<?php echo $subscription->id; ?>">
<?php _e('修改订阅', 'cultural-subscription'); ?>
</button>
<button class="button cancel-subscription"
data-subscription-id="<?php echo $subscription->id; ?>">
<?php _e('取消订阅', 'cultural-subscription'); ?>
</button>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>
<?php
return ob_get_clean();
}
/**
* 获取用户订阅
*/
private function get_user_subscriptions($user_id) {
global $wpdb;
$table_name = $wpdb->prefix . 'cultural_subscriptions';
return $wpdb->get_results($wpdb->prepare(
"SELECT * FROM $table_name WHERE user_id = %d ORDER BY created_at DESC",
$user_id
));
}
/**
* 获取频率标签
*/
private function get_frequency_label($frequency) {
$labels = array(
'monthly' => __('每月', 'cultural-subscription'),
'quarterly' => __('每季度', 'cultural-subscription'),
'yearly' => __('每年', 'cultural-subscription')
);
return $labels[$frequency] ?? $frequency;
}
/**
* 获取状态标签
*/
private function get_status_label($status) {
$labels = array(
'active' => __('活跃', 'cultural-subscription'),
'paused' => __('已暂停', 'cultural-subscription'),
'cancelled' => __('已取消', 'cultural-subscription'),
'expired' => __('已过期', 'cultural-subscription')
);
return $labels[$status] ?? $status;
}
/**
* 加载前端脚本和样式
*/
public function enqueue_frontend_scripts() {
wp_enqueue_style(
'cultural-subscription-frontend',
CULTURAL_SUBSCRIPTION_PLUGIN_URL . 'assets/css/frontend.css',
array(),
CULTURAL_SUBSCRIPTION_VERSION
);
wp_enqueue_script(
'cultural-subscription-frontend',
CULTURAL_SUBSCRIPTION_PLUGIN_URL . 'assets/js/frontend.js',
array('jquery'),
CULTURAL_SUBSCRIPTION_VERSION,
true
);
wp_localize_script('cultural-subscription-frontend', 'culturalSubscription', array(
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('cultural_subscription_nonce'),
'i18n' => array(
'confirm_cancel' => __('确定要取消订阅吗?', 'cultural-subscription'),
'loading' => __('加载中...', 'cultural-subscription'),
'error' => __('发生错误,请重试', 'cultural-subscription')
)
));
}
}
// 初始化前端
new SubscriptionFrontend();
?>
## 五、AJAX处理与支付集成
创建AJAX处理器和支付集成模块:
<?php
/**
- AJAX处理器
*/
class SubscriptionAjaxHandler {
public function __construct() {
// 订阅相关AJAX
add_action('wp_ajax_create_subscription', array($this, 'handle_create_subscription'));
add_action('wp_ajax_nopriv_create_subscription', array($this, 'handle_no_privilege'));
add_action('wp_ajax_modify_subscription', array($this, 'handle_modify_subscription'));
add_action('wp_ajax_cancel_subscription', array($this, 'handle_cancel_subscription'));
// 产品选择
add_action('wp_ajax_get_products_for_plan', array($this, 'handle_get_products'));
}
/**
* 创建订阅
*/
public function handle_create_subscription() {
// 验证nonce
if (!wp_verify_nonce($_POST['nonce'], 'cultural_subscription_nonce')) {
wp_die('非法请求');
}
// 验证用户
if (!is_user_logged_in()) {
wp_send_json_error(array('message' => '请先登录'));
}
$user_id = get_current_user_id();
$plan_id = intval($_POST['plan_id']);
$frequency = sanitize_text_field($_POST['frequency']);
$product_ids = array_map('intval', $_POST['product_ids'] ?? array());
// 验证数据
if (!$plan_id || empty($product_ids)) {
wp_send_json_error(array('message' => '请选择产品和计划'));
}
// 检查计划是否存在
$plan = get_post($plan_id);
if (!$plan || $plan->post_type !== 'subscription_plan') {
wp_send_json_error(array('message' => '订阅计划不存在'));
}
// 创建订阅记录
$subscription_id = $this->create_subscription_record(array(
'user_id' => $user_id,
'plan_id' => $plan_id,
'product_ids' => $product_ids,
'frequency' => $frequency,
'status' => 'pending_payment'
));
if (!$subscription_id) {
wp_send_json_error(array('message' => '创建订阅失败'));
}
// 生成支付
$payment_data = $this->create_payment($subscription_id);
wp_send_json_success(array(
'message' => '订阅创建成功',
'subscription_id' => $subscription_id,
'payment_data' => $payment_data
));
}
/**
* 创建订阅记录
*/
private function create_subscription_record($data) {
global $wpdb;
$table_name = $wpdb->prefix . 'cultural_subscriptions';
// 计算下次配送日期
$next_delivery = $this->calculate_next_delivery($data['frequency']);
$result = $wpdb->insert($table_name, array(
'user_id' => $data['user_id'],
'plan_id' => $data['plan_id'],
'product_ids' => json_encode($data['product_ids']),
'subscription_type' => 'flexible',
'frequency' => $data['frequency'],
'next_delivery_date' => $next_delivery,
'status' => $data['status']
));
return $result ? $wpdb->insert_id : false;
}
/**
* 计算下次配送日期
*/
private function calculate_next_delivery($frequency) {
$today = current_time('Y-m-d');
switch ($frequency) {
case 'monthly':
return date('Y-m-d', strtotime($today . ' +1 month'));
case 'quarterly':
return date('Y-m-d', strtotime($today . ' +3 months'));
case 'yearly':
return date('Y-m-d', strtotime($today . ' +1 year'));
default:
return date('Y-m-d', strtotime($today . ' +1 month'));
}
}
/**
* 创建支付
*/
private function create_payment($subscription_id) {
// 这里集成支付网关
// 示例:使用WooCommerce支付
if (class_exists('WooCommerce')) {
return $this->create_woocommerce_payment($subscription_id);
}
// 或者使用其他支付网关
return array(
'type' => 'manual',
'message' => '请等待管理员确认支付'
);
}
/**
* 创建WooCommerce支付
*/
private function create_woocommerce_payment($subscription_id) {
global $wpdb;
// 获取订阅信息
$table_name = $wpdb->prefix . 'cultural_subscriptions';
$subscription = $wpdb->get_row($wpdb->prepare(
"SELECT * FROM $table_name WHERE id = %d",
$subscription_id
));
if (!$subscription) {
return false;
}
// 创建订单
$order = wc_create_order(array(
'customer_id' => $subscription->user_id,
'created_via' => 'cultural_subscription'
));
// 获取计划价格
$plan_manager = new SubscriptionPlanManager();
$price = $plan_manager->calculate_price(
$subscription->plan_id,
array(
'frequency' => $subscription->frequency,
'products' => json_decode($subscription->product_ids, true)
)
);
// 添加产品到订单
$product_ids = json_decode($subscription->product_ids, true);
foreach ($product_ids as $product_id) {
$product = wc_get_product($product_id);
if ($product) {
$order->add_product($product, 1);
}
}
// 设置订阅费用
$order->add_meta_data('_subscription_id', $subscription_id);
$order->add_meta_data('_subscription_frequency', $subscription->frequency);
$order->set_total($price);
$order->save();
return array(
'type' => 'woocommerce',
'order_id' => $order->get_id(),
'payment_url' => $order->get_checkout_payment_url()
);
}
/**
* 修改订阅
*/
public function handle_modify_subscription() {
// 验证nonce和用户权限
if (!wp_verify_nonce($_POST['nonce'], 'cultural_subscription_nonce') || !is_user_logged_in()) {
wp_die('非法请求');
}
$subscription_id = intval($_POST['subscription_id']);
$user_id = get_current_user_id();
// 验证订阅所有权
if (!$this->validate_subscription_ownership($subscription_id, $user_id)) {
wp_send_json_error(array('message' => '无权修改此订阅'));
}
// 获取修改选项
$new_frequency = sanitize_text_field($_POST['new_frequency'] ?? '');
$new_products = array_map('intval', $_POST['new_products'] ?? array());
// 更新订阅
$updated = $this->update_subscription($subscription_id, array(
'frequency' => $new_frequency,
'product_ids' => $new_products
));
if ($updated) {
wp_send_json_success(array('message' => '订阅修改成功'));
} else {
wp_send_json_error(array('message' => '修改失败'));
}
}
/**
* 验证订阅所有权
*/
private function validate_subscription_ownership($subscription_id, $user_id) {
global $wpdb;
$table_name = $wpdb->prefix . 'cultural_subscriptions';
$subscription = $wpdb->get_row($wpdb->prepare(
"SELECT user_id FROM $table_name WHERE id = %d",
$subscription_id
));
return $subscription && $subscription->user_id == $user_id;
}
/**
* 更新订阅
*/
private function update_subscription($subscription_id, $data) {
global $wpdb;
$table_name = $wpdb->prefix . 'cultural_subscriptions';
$update_data = array();
if (!empty($data['frequency'])) {
$update_data['frequency'] = $data['frequency'];
// 重新计算下次配送日期
$update_data['next_delivery_date'] = $this->calculate_next_delivery($data['frequency']);
}
if (!empty($data['product_ids'])) {
$update_data['product_ids'] = json_encode($data['product_ids']);
}
if (empty($update_data)) {
return false;
}
return $wpdb->update(
$table_name,
$update_data,
array('id' => $subscription_id)
);
}
/**
* 取消订阅
*/
public function handle_cancel_subscription() {
// 验证nonce和用户权限
if (!wp_verify_nonce($_POST['nonce'], 'cultural_subscription_nonce') || !is_user_logged_in()) {
wp_die('非法请求');
}
$subscription_id = intval($_POST['subscription_id']);
$user_id = get_current_user_id();
// 验证订阅所有权
if (!$this->validate_subscription_ownership($subscription_id, $user_id)) {
wp_send_json_error(array('message' => '无权取消此订阅'));
}
// 取消订阅(软删除)
$cancelled = $this->cancel_subscription_record($subscription_id);
if ($cancelled) {
wp_send_json_success(array('message' => '订阅已取消'));
} else {
wp_send_json_error(array('message' => '取消失败'));
}
}
/**
* 取消订阅记录
*/
private function cancel_subscription_record($subscription_id) {
global $wpdb;
$table_name = $wpdb->prefix . 'cultural_subscriptions';
return $wpdb->update(
$table_name,
array('status' => 'cancelled'),
array('id' => $subscription_id)
);
}
/**
* 获取计划相关产品
*/
public function handle_get_products() {
$plan_id = intval($_POST['plan_id']);
// 这里应该根据计划获取相关文创产品
// 示例:获取所有文创产品
$args = array(
'post_type' => 'product',
'posts_per_page' => -1,
'tax_query' => array(
array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => 'cultural-creative' // 文创产品分类
)
)
);
$products = get_posts($args);
$formatted_products = array();
foreach ($products as $product) {
$product_obj = wc_get_product($product->ID);
$formatted_products[] = array(
'id' => $product->ID,
'name' => $product->post_title,
'price' => $product_obj->get_price(),
'image' => get_the_post_thumbnail_url($product->ID, 'thumbnail')
);
}
wp_send_json_success($formatted_products);
}
/**
* 无权限处理
*/
public function handle_no_privilege() {
wp_send_json_error(array('message' => '请先登录'));
}
}
// 初始化AJAX处理器
new SubscriptionAjaxHandler();
?>
## 六、自动化任务与通知系统
创建定时任务和通知系统:
<?php
/**
- 自动化任务管理器
*/
class SubscriptionAutomation {
public function __construct() {
// 注册定时任务
add_action('init', array($this, 'schedule_events'));
// 定义定时任务钩子
add_action('cultural_subscription_daily_check', array($this, 'daily_check'));
add_action('cultural_subscription_process_renewals', array($this, 'process_renewals'));
add_action('cultural_subscription_send_reminders', array($this, 'send_reminders'));
}
/**
* 安排定时任务
*/
public function schedule_events() {
if (!wp_next_scheduled('cultural_subscription_daily_check')) {
wp_schedule_event(time(), 'daily', 'cultural_subscription_daily_check');
}
if (!wp_next_scheduled('cultural_subscription_process_renewals')) {
wp_schedule_event(time(), 'twicedaily', 'cultural_subscription_process_renewals');
}
}
/**
* 每日检查
*/
public function daily_check() {
$this->check_expiring_subscriptions();
$this->update_subscription_statuses();
$this->cleanup_old_data();
}
/**
* 检查即将到期的订阅
*/
private function check_expiring_subscriptions() {
global $wpdb;
$table_name = $wpdb->prefix . 'cultural_subscriptions';
// 查找7天内到期的订阅
$seven_days_later = date('Y-m-d', strtotime('+7 days'));
$expiring_subscriptions = $wpdb->get_results($wpdb->prepare(
"SELECT * FROM $table_name
WHERE status = 'active'
AND next_delivery_date <= %s
AND next_delivery_date > %s",
$seven_days_later,
current_time('Y-m-d')
));
foreach ($expiring_subscriptions as $subscription) {
$this->send_expiration_reminder($subscription);
}
}
/**
* 发送到期提醒
*/
private function send_expiration_reminder($subscription) {
$user = get_user_by('id', $subscription->user_id);
if (!$user) {
return;
}
$plan_name = get_the_title($subscription->plan_id);
$next_delivery = date_i18n(get_option('date_format'), strtotime($subscription->next_delivery_date));
$subject = sprintf(__('您的文创订阅即将配送 - %s', 'cultural-subscription'), $plan_name);
$message = sprintf(
__('亲爱的%s,<br><br>您的文创订阅"%s"将在%s进行下次配送。<br><br>如需修改配送内容或时间,请登录您的账户进行操作。<br><br>感谢您的订阅!', 'cultural-subscription'),
$user->display_name,
$plan_name,
$next_delivery
);
wp_mail($user->user_email, $subject, $message, array('Content-Type: text/html; charset=UTF-8'));
}
/**
* 更新订阅状态
*/
private function update_subscription_statuses() {
global $wpdb;
$table_name = $wpdb->prefix . 'cultural_subscriptions';
// 将过期的订阅标记为过期
$wpdb->query($wpdb->prepare(
"UPDATE $table_name
SET status = 'expired'
WHERE status = 'active'
AND next_delivery_date < %s",
current_time('Y-m-d')
));
}
/**
* 处理续订
*/
public function process_renewals() {
global $wpdb;
$table_name = $wpdb->prefix . 'cultural_subscriptions';
// 查找需要续订的订阅
$today = current_time('Y-m-d');
$renewal_subscriptions = $wpdb->get_results($wpdb->prepare(
"SELECT * FROM $table_name
WHERE status = 'active'
AND next_delivery_date = %s",
$today
));
foreach ($renewal_subscriptions as $subscription) {
$this->process_single_renewal($subscription);
}
}
/**
* 处理单个续订
*/
private function process_single_renewal($subscription) {
// 创建新订单
$payment_data = $this->create_renewal_payment($subscription);
if ($payment_data) {
// 更新下次配送日期
$this->update_next_delivery_date($subscription->id);
// 发送续订确认
$this->send_renewal_confirmation($subscription);
} else {
// 支付失败,进入宽限期
$this->handle_payment_failure($subscription);
}
}
/**


