init_hooks(); $this->schedule_events(); } /** * 初始化钩子 */ private function init_hooks() { // 订阅续费处理 add_action('yoone_process_subscription_renewals', array($this, 'process_subscription_renewals')); // 清理过期令牌 add_action('yoone_cleanup_expired_tokens', array($this, 'cleanup_expired_tokens')); // 清理过期订阅 add_action('yoone_cleanup_expired_subscriptions', array($this, 'cleanup_expired_subscriptions')); // 发送订阅提醒邮件 add_action('yoone_send_subscription_reminders', array($this, 'send_subscription_reminders')); // 清理日志文件 add_action('yoone_cleanup_logs', array($this, 'cleanup_logs')); // 添加自定义计划间隔 add_filter('cron_schedules', array($this, 'add_cron_schedules')); } /** * 安排计划事件 */ private function schedule_events() { // 每小时处理订阅续费 if (!wp_next_scheduled('yoone_process_subscription_renewals')) { wp_schedule_event(time(), 'hourly', 'yoone_process_subscription_renewals'); } // 每天清理过期令牌 if (!wp_next_scheduled('yoone_cleanup_expired_tokens')) { wp_schedule_event(time(), 'daily', 'yoone_cleanup_expired_tokens'); } // 每天清理过期订阅 if (!wp_next_scheduled('yoone_cleanup_expired_subscriptions')) { wp_schedule_event(time(), 'daily', 'yoone_cleanup_expired_subscriptions'); } // 每天发送订阅提醒邮件 if (!wp_next_scheduled('yoone_send_subscription_reminders')) { wp_schedule_event(time(), 'daily', 'yoone_send_subscription_reminders'); } // 每周清理日志文件 if (!wp_next_scheduled('yoone_cleanup_logs')) { wp_schedule_event(time(), 'weekly', 'yoone_cleanup_logs'); } } /** * 添加自定义计划间隔 * * @param array $schedules 现有计划 * @return array 更新后的计划 */ public function add_cron_schedules($schedules) { // 每15分钟 $schedules['fifteen_minutes'] = array( 'interval' => 15 * 60, 'display' => __('每15分钟', 'yoone-subscriptions') ); // 每30分钟 $schedules['thirty_minutes'] = array( 'interval' => 30 * 60, 'display' => __('每30分钟', 'yoone-subscriptions') ); return $schedules; } /** * 处理订阅续费 */ public function process_subscription_renewals() { Yoone_Logger::info('开始处理订阅续费'); global $wpdb; // 获取需要续费的订阅 $subscriptions = $wpdb->get_results($wpdb->prepare(" SELECT * FROM {$wpdb->prefix}yoone_subscriptions WHERE status = 'active' AND next_payment_date <= %s AND next_payment_date IS NOT NULL LIMIT 50 ", current_time('mysql'))); $processed = 0; $failed = 0; foreach ($subscriptions as $subscription_data) { try { $subscription = new Yoone_Subscription($subscription_data->id); if ($subscription->process_renewal()) { $processed++; Yoone_Logger::log_subscription($subscription->get_id(), '订阅续费成功'); } else { $failed++; Yoone_Logger::log_subscription($subscription->get_id(), '订阅续费失败', Yoone_Logger::ERROR); } } catch (Exception $e) { $failed++; Yoone_Logger::error('订阅续费异常: ' . $e->getMessage(), array( 'subscription_id' => $subscription_data->id )); } } Yoone_Logger::info("订阅续费处理完成: 成功 {$processed}, 失败 {$failed}"); } /** * 清理过期令牌 */ public function cleanup_expired_tokens() { Yoone_Logger::info('开始清理过期支付令牌'); global $wpdb; $deleted = $wpdb->query($wpdb->prepare(" DELETE FROM {$wpdb->prefix}yoone_payment_tokens WHERE expires_at < %s ", current_time('mysql'))); Yoone_Logger::info("清理过期令牌完成: 删除 {$deleted} 个令牌"); } /** * 清理过期订阅 */ public function cleanup_expired_subscriptions() { Yoone_Logger::info('开始清理过期订阅'); global $wpdb; // 将长时间未付款的活跃订阅标记为过期 $expired_days = apply_filters('yoone_subscription_expiry_days', 30); $updated = $wpdb->query($wpdb->prepare(" UPDATE {$wpdb->prefix}yoone_subscriptions SET status = 'expired', updated_at = %s WHERE status = 'active' AND next_payment_date < %s ", current_time('mysql'), date('Y-m-d H:i:s', strtotime("-{$expired_days} days")))); if ($updated > 0) { Yoone_Logger::info("标记过期订阅完成: 更新 {$updated} 个订阅"); // 发送过期通知邮件 $this->send_expiry_notifications(); } } /** * 发送订阅提醒邮件 */ public function send_subscription_reminders() { Yoone_Logger::info('开始发送订阅提醒邮件'); global $wpdb; // 获取即将到期的订阅(3天内) $subscriptions = $wpdb->get_results($wpdb->prepare(" SELECT s.*, u.user_email, u.display_name FROM {$wpdb->prefix}yoone_subscriptions s LEFT JOIN {$wpdb->users} u ON s.customer_id = u.ID WHERE s.status = 'active' AND s.next_payment_date BETWEEN %s AND %s AND s.reminder_sent = 0 ", current_time('mysql'), date('Y-m-d H:i:s', strtotime('+3 days')))); $sent = 0; foreach ($subscriptions as $subscription_data) { try { $this->send_renewal_reminder($subscription_data); // 标记提醒已发送 $wpdb->update( $wpdb->prefix . 'yoone_subscriptions', array('reminder_sent' => 1), array('id' => $subscription_data->id), array('%d'), array('%d') ); $sent++; } catch (Exception $e) { Yoone_Logger::error('发送提醒邮件失败: ' . $e->getMessage(), array( 'subscription_id' => $subscription_data->id )); } } Yoone_Logger::info("发送订阅提醒邮件完成: 发送 {$sent} 封邮件"); } /** * 清理日志文件 */ public function cleanup_logs() { Yoone_Logger::info('开始清理日志文件'); $days_to_keep = apply_filters('yoone_log_retention_days', 30); Yoone_Logger::cleanup_old_logs($days_to_keep); Yoone_Logger::info("清理日志文件完成: 保留 {$days_to_keep} 天内的日志"); } /** * 发送续费提醒邮件 * * @param object $subscription_data 订阅数据 */ private function send_renewal_reminder($subscription_data) { $subject = sprintf(__('您的订阅即将续费 - %s', 'yoone-subscriptions'), get_bloginfo('name')); $message = sprintf( __('亲爱的 %s, 您的订阅即将在 %s 自动续费。 订阅详情: - 订阅ID: %d - 金额: %s - 下次付款日期: %s 如需管理您的订阅,请访问:%s 谢谢! %s', 'yoone-subscriptions'), $subscription_data->display_name, Yoone_Helper::format_date($subscription_data->next_payment_date, 'Y-m-d'), $subscription_data->id, wc_price($subscription_data->total), Yoone_Helper::format_date($subscription_data->next_payment_date, 'Y-m-d H:i'), wc_get_account_endpoint_url('subscriptions'), get_bloginfo('name') ); wp_mail($subscription_data->user_email, $subject, $message); } /** * 发送过期通知邮件 */ private function send_expiry_notifications() { global $wpdb; // 获取刚刚标记为过期的订阅 $subscriptions = $wpdb->get_results($wpdb->prepare(" SELECT s.*, u.user_email, u.display_name FROM {$wpdb->prefix}yoone_subscriptions s LEFT JOIN {$wpdb->users} u ON s.customer_id = u.ID WHERE s.status = 'expired' AND s.updated_at >= %s ", date('Y-m-d H:i:s', strtotime('-1 hour')))); foreach ($subscriptions as $subscription_data) { $this->send_expiry_notification($subscription_data); } } /** * 发送过期通知邮件 * * @param object $subscription_data 订阅数据 */ private function send_expiry_notification($subscription_data) { $subject = sprintf(__('您的订阅已过期 - %s', 'yoone-subscriptions'), get_bloginfo('name')); $message = sprintf( __('亲爱的 %s, 您的订阅已因长时间未付款而过期。 订阅详情: - 订阅ID: %d - 金额: %s - 过期时间: %s 如需重新激活订阅,请访问:%s 谢谢! %s', 'yoone-subscriptions'), $subscription_data->display_name, $subscription_data->id, wc_price($subscription_data->total), Yoone_Helper::format_date($subscription_data->updated_at, 'Y-m-d H:i'), wc_get_account_endpoint_url('subscriptions'), get_bloginfo('name') ); wp_mail($subscription_data->user_email, $subject, $message); } /** * 取消所有计划事件 */ public static function unschedule_all_events() { $events = array( 'yoone_process_subscription_renewals', 'yoone_cleanup_expired_tokens', 'yoone_cleanup_expired_subscriptions', 'yoone_send_subscription_reminders', 'yoone_cleanup_logs' ); foreach ($events as $event) { $timestamp = wp_next_scheduled($event); if ($timestamp) { wp_unschedule_event($timestamp, $event); } } } /** * 手动触发订阅续费处理 */ public static function manual_process_renewals() { $cron = new self(); $cron->process_subscription_renewals(); } /** * 手动清理过期令牌 */ public static function manual_cleanup_tokens() { $cron = new self(); $cron->cleanup_expired_tokens(); } }