文章目录
-
- 随着互联网活动的日益普及,在线抽奖已成为企业营销、社区互动和用户增长的重要手段。然而,如何确保抽奖过程的公平性和中奖结果的公信力,一直是组织者面临的挑战。本文将详细介绍如何通过WordPress程序的代码二次开发,实现一个功能完善的在线抽奖与中奖结果公证展示系统。我们将从系统设计、功能实现、安全性保障到用户体验优化等多个维度进行全面解析,帮助开发者构建一个既实用又可信赖的在线抽奖平台。
-
- 在线抽奖系统不仅是一个简单的随机选择工具,更是一个集用户参与、活动管理、结果公证和营销推广于一体的综合平台。一个优秀的在线抽奖系统应具备以下特点: 公平性:确保每个参与者有平等的获奖机会 透明性:抽奖过程和中奖结果可追溯、可验证 易用性:用户参与简单,管理后台操作便捷 可扩展性:支持多种抽奖规则和活动形式 安全性:防止作弊和恶意攻击
- 基于WordPress开发在线抽奖系统,我们需要实现以下核心功能: 用户参与模块:注册、登录、参与抽奖 抽奖活动管理:创建、编辑、删除抽奖活动 抽奖规则设置:参与条件、中奖人数、奖品设置 实时抽奖引擎:公平的随机算法实现 中奖结果展示:可视化展示中奖结果 公证验证系统:提供抽奖过程的可验证证据 数据统计与分析:参与数据、中奖率等统计
- 选择WordPress作为开发基础有以下优势: 成熟的用户管理系统 丰富的插件生态和主题支持 良好的扩展性和二次开发能力 广泛的技术社区支持 系统架构采用WordPress核心+自定义插件+定制主题的模式,确保系统稳定性的同时提供高度定制化功能。
-
- 在开始开发前,需要准备以下环境: 本地开发环境:推荐使用XAMPP、MAMP或Local by Flywheel WordPress安装:最新稳定版WordPress 代码编辑器:VS Code、PHPStorm等 版本控制:Git 调试工具:Query Monitor、Debug Bar等WordPress调试插件
- 我们将创建一个独立插件来管理所有抽奖功能: <?php /** * Plugin Name: 在线抽奖与公证系统 * Plugin URI: https://yourwebsite.com/ * Description: 功能完整的在线抽奖与中奖结果公证展示系统 * Version: 1.0.0 * Author: Your Name * License: GPL v2 or later */ // 防止直接访问 if (!defined('ABSPATH')) { exit; } // 定义插件常量 define('LOTTERY_PLUGIN_PATH', plugin_dir_path(__FILE__)); define('LOTTERY_PLUGIN_URL', plugin_dir_url(__FILE__)); define('LOTTERY_VERSION', '1.0.0'); // 初始化插件 require_once LOTTERY_PLUGIN_PATH . 'includes/class-lottery-core.php'; function lottery_init() { $lottery = new Lottery_Core(); $lottery->init(); } add_action('plugins_loaded', 'lottery_init');
- 我们需要创建自定义数据表来存储抽奖活动、参与记录和中奖信息: // 在插件激活时创建数据表 function lottery_create_tables() { global $wpdb; $charset_collate = $wpdb->get_charset_collate(); // 抽奖活动表 $table_activities = $wpdb->prefix . 'lottery_activities'; $sql_activities = "CREATE TABLE IF NOT EXISTS $table_activities ( id INT(11) NOT NULL AUTO_INCREMENT, title VARCHAR(255) NOT NULL, description TEXT, start_date DATETIME NOT NULL, end_date DATETIME NOT NULL, status ENUM('draft', 'active', 'ended', 'cancelled') DEFAULT 'draft', rules TEXT, prizes TEXT, winner_count INT(11) DEFAULT 1, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id) ) $charset_collate;"; // 参与记录表 $table_participants = $wpdb->prefix . 'lottery_participants'; $sql_participants = "CREATE TABLE IF NOT EXISTS $table_participants ( id INT(11) NOT NULL AUTO_INCREMENT, activity_id INT(11) NOT NULL, user_id INT(11), user_email VARCHAR(255), user_name VARCHAR(255), ip_address VARCHAR(45), user_agent TEXT, participation_code VARCHAR(100) UNIQUE, status ENUM('valid', 'invalid') DEFAULT 'valid', participated_at DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), INDEX activity_user (activity_id, user_id), FOREIGN KEY (activity_id) REFERENCES $table_activities(id) ON DELETE CASCADE ) $charset_collate;"; // 中奖记录表 $table_winners = $wpdb->prefix . 'lottery_winners'; $sql_winners = "CREATE TABLE IF NOT EXISTS $table_winners ( id INT(11) NOT NULL AUTO_INCREMENT, activity_id INT(11) NOT NULL, participant_id INT(11) NOT NULL, prize_level INT(11), prize_name VARCHAR(255), awarded_at DATETIME DEFAULT CURRENT_TIMESTAMP, verification_hash VARCHAR(255), PRIMARY KEY (id), FOREIGN KEY (activity_id) REFERENCES $table_activities(id) ON DELETE CASCADE, FOREIGN KEY (participant_id) REFERENCES $table_participants(id) ON DELETE CASCADE ) $charset_collate;"; require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); dbDelta($sql_activities); dbDelta($sql_participants); dbDelta($sql_winners); } register_activation_hook(__FILE__, 'lottery_create_tables');
-
-
- 创建抽奖活动管理后台页面: class Lottery_Admin { public function __construct() { add_action('admin_menu', array($this, 'add_admin_menu')); add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts')); } public function add_admin_menu() { add_menu_page( '在线抽奖系统', '抽奖管理', 'manage_options', 'lottery-management', array($this, 'render_admin_page'), 'dashicons-tickets-alt', 30 ); add_submenu_page( 'lottery-management', '抽奖活动', '活动列表', 'manage_options', 'lottery-activities', array($this, 'render_activities_page') ); add_submenu_page( 'lottery-management', '添加抽奖活动', '添加活动', 'manage_options', 'lottery-add-activity', array($this, 'render_add_activity_page') ); } public function render_activities_page() { include LOTTERY_PLUGIN_PATH . 'admin/views/activities-list.php'; } public function render_add_activity_page() { include LOTTERY_PLUGIN_PATH . 'admin/views/activity-form.php'; } public function enqueue_admin_scripts($hook) { if (strpos($hook, 'lottery') !== false) { wp_enqueue_style('lottery-admin-style', LOTTERY_PLUGIN_URL . 'assets/css/admin.css'); wp_enqueue_script('lottery-admin-script', LOTTERY_PLUGIN_URL . 'assets/js/admin.js', array('jquery', 'jquery-ui-datepicker'), LOTTERY_VERSION, true); wp_enqueue_style('jquery-ui-style', '//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css'); } } }
- // 处理活动表单提交 function lottery_save_activity() { if (!isset($_POST['lottery_nonce']) || !wp_verify_nonce($_POST['lottery_nonce'], 'lottery_save_activity')) { wp_die('安全验证失败'); } global $wpdb; $table_name = $wpdb->prefix . 'lottery_activities'; $data = array( 'title' => sanitize_text_field($_POST['title']), 'description' => wp_kses_post($_POST['description']), 'start_date' => sanitize_text_field($_POST['start_date']), 'end_date' => sanitize_text_field($_POST['end_date']), 'status' => sanitize_text_field($_POST['status']), 'winner_count' => intval($_POST['winner_count']), 'rules' => wp_json_encode($_POST['rules']), 'prizes' => wp_json_encode($_POST['prizes']) ); if (isset($_POST['activity_id']) && !empty($_POST['activity_id'])) { // 更新现有活动 $wpdb->update($table_name, $data, array('id' => intval($_POST['activity_id']))); $message = '活动更新成功'; } else { // 创建新活动 $wpdb->insert($table_name, $data); $message = '活动创建成功'; } wp_redirect(admin_url('admin.php?page=lottery-activities&message=' . urlencode($message))); exit; } add_action('admin_post_lottery_save_activity', 'lottery_save_activity');
-
- 创建短代码让用户可以在任何页面参与抽奖: class Lottery_Shortcodes { public function __construct() { add_shortcode('lottery_participation', array($this, 'render_participation_form')); add_shortcode('lottery_results', array($this, 'render_results_display')); } public function render_participation_form($atts) { $atts = shortcode_atts(array( 'activity_id' => 0, 'title' => '参与抽奖' ), $atts); $activity_id = intval($atts['activity_id']); if (!$activity_id) { return '<p>错误:未指定抽奖活动</p>'; } // 检查活动状态 $activity = $this->get_activity($activity_id); if (!$activity) { return '<p>错误:抽奖活动不存在</p>'; } // 检查活动时间 $current_time = current_time('mysql'); if ($current_time < $activity->start_date) { return '<div class="lottery-notice">抽奖活动尚未开始</div>'; } if ($current_time > $activity->end_date) { return '<div class="lottery-notice">抽奖活动已结束</div>'; } // 检查用户是否已参与 $user_id = get_current_user_id(); $has_participated = $this->check_participation($activity_id, $user_id); if ($has_participated) { return '<div class="lottery-notice">您已参与本次抽奖,请等待开奖结果</div>'; } // 渲染参与表单 ob_start(); include LOTTERY_PLUGIN_PATH . 'public/views/participation-form.php'; return ob_get_clean(); } private function get_activity($activity_id) { global $wpdb; $table_name = $wpdb->prefix . 'lottery_activities'; return $wpdb->get_row($wpdb->prepare( "SELECT * FROM $table_name WHERE id = %d AND status = 'active'", $activity_id )); } private function check_participation($activity_id, $user_id) { global $wpdb; $table_name = $wpdb->prefix . 'lottery_participants'; if ($user_id) { return $wpdb->get_var($wpdb->prepare( "SELECT COUNT(*) FROM $table_name WHERE activity_id = %d AND user_id = %d", $activity_id, $user_id )); } return false; } }
- // 处理用户参与请求 function lottery_handle_participation() { // 验证nonce if (!isset($_POST['lottery_nonce']) || !wp_verify_nonce($_POST['lottery_nonce'], 'lottery_participate')) { wp_send_json_error(array('message' => '安全验证失败')); } $activity_id = intval($_POST['activity_id']); // 验证活动 $activity = lottery_get_activity($activity_id); if (!$activity || $activity->status !== 'active') { wp_send_json_error(array('message' => '抽奖活动无效或已结束')); } // 检查时间 $current_time = current_time('mysql'); if ($current_time < $activity->start_date || $current_time > $activity->end_date) { wp_send_json_error(array('message' => '不在抽奖活动时间内')); } // 获取用户信息 $user_id = get_current_user_id(); $user_email = ''; $user_name = ''; if ($user_id) { $user = get_userdata($user_id); $user_email = $user->user_email; $user_name = $user->display_name; } else { // 匿名用户需要提供邮箱 if (empty($_POST['user_email']) || !is_email($_POST['user_email'])) { wp_send_json_error(array('message' => '请输入有效的邮箱地址')); } $user_email = sanitize_email($_POST['user_email']); $user_name = !empty($_POST['user_name']) ? sanitize_text_field($_POST['user_name']) : ''; } // 检查是否已参与 if (lottery_check_participation($activity_id, $user_id, $user_email)) { wp_send_json_error(array('message' => '您已经参与过本次抽奖')); } // 生成参与码 $participation_code = lottery_generate_participation_code(); // 保存参与记录 global $wpdb; $table_name = $wpdb->prefix . 'lottery_participants'; $data = array( 'activity_id' => $activity_id, 'user_id' => $user_id, 'user_email' => $user_email, 'user_name' => $user_name, 'ip_address' => lottery_get_client_ip(), 'user_agent' => $_SERVER['HTTP_USER_AGENT'], 'participation_code' => $participation_code ); $result = $wpdb->insert($table_name, $data); if ($result) { // 发送确认邮件 lottery_send_participation_email($user_email, $activity, $participation_code); wp_send_json_success(array( 'message' => '参与成功!您的参与码是:' . $participation_code, 'code' => $participation_code )); } else { wp_send_json_error(array('message' => '参与失败,请稍后重试')); } } add_action('wp_ajax_lottery_participate', 'lottery_handle_participation'); add_action('wp_ajax_nopriv_lottery_participate', 'lottery_handle_participation');
-
- class Lottery_Draw_Engine { /** * 执行抽奖 * @param int $activity_id 活动ID * @param int $winner_count 中奖人数 * @return array 中奖者列表 */ public function draw_winners($activity_id, $winner_count) { // 获取所有有效参与者 $participants = $this->get_valid_participants($activity_id); if (empty($participants)) { return array('success' => false, 'message' => '没有有效参与者'); } if (count($participants) < $winner_count) { return array('success' => false, 'message' => '参与者数量少于中奖人数'); } // 使用加密安全的随机数生成器 $winners = $this->secure_random_draw($participants, $winner_count); // 记录中奖结果 $result = $this->record_winners($activity_id, $winners); // 生成可验证的抽奖证明 $verification_data = $this->generate_verification_data($activity_id, $participants, $winners); return array( 'success' => true, 'winners' => $winners, 'verification_hash' => $verification_data['hash'], 'verification_data' => $verification_data['data'] ); } /** * 加密安全的随机抽选算法 */ private function secure_random_draw($participants, $winner_count) { $total = count($participants); $winners = array(); $selected_indices = array(); // 使用加密安全的随机数生成器 while (count($winners) < $winner_count) { // 生成随机索引 $random_index = random_int(0, $total - 1); // 确保不重复选择 if (!in_array($random_index, $selected_indices)) { $selected_indices[] = $random_index; $winners[] = $participants[$random_index]; } } return $winners; } /** * 生成可验证的抽奖证明 */ private function generate_verification_data($activity_id, $participants, $winners) { // 创建抽奖数据快照 $snapshot = array( 'activity_id' => $activity_id, 'draw_time' => current_time('mysql'), 'total_participants' => count($participants), 'participant_ids' => array_column($participants, 'id'), 'winner_ids' => array_column($winners, 'id'), 'server_seed' => bin2hex(random_bytes(32)), 'client_seed' => $this->get_client_seed($activity_id) ); // 计算验证哈希 $hash_data = json_encode($snapshot); $verification_hash = hash('sha256', $hash_data); // 保存验证数据 $this->save_verification_data($activity_id, $hash_data, $verification_hash); return array( 'hash' => $verification_hash, 'data' => $snapshot ); } /** * 获取客户端种子(基于活动数据) */ private function get_client_seed($activity_id) { global $wpdb; $table_name = $wpdb->prefix . 'lottery_activities'; $activity = $wpdb->get_row($wpdb->prepare( "SELECT title, start_date, end_date FROM $table_name WHERE id = %d", $activity_id )); if ($activity) { return hash('sha256', $activity->title . $activity->start_date . $activity->end_date); } return hash('sha256', (string) $activity_id); } }
- // 后台执行抽奖的接口 function lottery_execute_draw() { if (!current_user_can('manage_options')) { wp_die('权限不足'); } $activity_id = intval($_POST['activity_id']); // 验证活动状态 $activity = lottery_get_activity($activity_id); if (!$activity || $activity->status !== 'active') { wp_send_json_error(array('message' => '活动状态不允许抽奖')); } // 检查是否已开奖 if (lottery_has_winners($activity_id)) { wp_send_json_error(array('message' => '该活动已开奖')); } // 执行抽奖 $draw_engine = new Lottery_Draw_Engine(); $result = $draw_engine->draw_winners($activity_id, $activity->winner_count); if ($result['success']) { // 更新活动状态 lottery_update_activity_status($activity_id, 'ended'); // 发送中奖通知 lottery_send_winner_notifications($activity_id, $result['winners']); wp_send_json_success(array( 'message' => '抽奖完成', 'winners' => $result['winners'], 'verification_hash' => $result['verification_hash'] )); } else { wp_send_json_error(array('message' => $result['message'])); } } add_action('wp_ajax_lottery_execute_draw', 'lottery_execute_draw');
-
- class Lottery_Results_Display { public function render_results($activity_id) { $activity = lottery_get_activity($activity_id); $winners = lottery_get_winners($activity_id); $verification_data = lottery_get_verification_data($activity_id); ob_start(); ?> <div class="lottery-results-container"> <div class="lottery-results-header"> <h2><?php echo esc_html($activity->title); ?> - 中奖结果</h2> <div class="lottery-meta"> <span class="lottery-date">开奖时间: <?php echo date('Y-m-d H:i:s', strtotime($verification_data['draw_time'])); ?></span> <span class="lottery-participants">参与人数: <?php echo $verification_data['total_participants']; ?></span> </div> </div> <div class="lottery-verification-section"> <h3>抽奖公正性验证</h3> <div class="verification-info"> <p>验证哈希: <code class="verification-hash"><?php echo esc_html($verification_data['hash']); ?></code></p> <button class="btn-verify" onclick="lotteryShowVerificationDetails()">查看验证详情</button> </div> <div id="verification-details" style="display: none;"> <h4>抽奖数据快照</h4> <pre><?php echo json_encode($verification_data['data'], JSON_PRETTY_PRINT); ?></pre> <p>您可以使用SHA256哈希验证器验证上述数据的哈希值是否匹配。</p> </div> </div> <div class="lottery-winners-section"> <h3>中奖名单</h3> <?php if (!empty($winners)): ?> <div class="winners-list"> <?php foreach ($winners as $index => $winner): ?> <div class="winner-item"> <div class="winner-rank"><?php echo $index + 1; ?></div> <div class="winner-info"> <h4><?php echo esc_html($winner->prize_name); ?></h4> <p class="winner-name"> <?php if ($winner->user_name) { echo esc_html(mb_substr($winner->user_name, 0, 1) . '**'); } else { echo esc_html(substr($winner->user_email, 0, 3) . '***' . substr($winner->user_email, strpos($winner->user_email, '@'))); } ?> </p> <p class="winner-code">参与码: <?php echo esc_html($winner->participation_code); ?></p> </div> </div> <?php endforeach; ?> </div> <?php else: ?> <p class="no-winners">暂无中奖者</p> <?php endif; ?> </div> <div class="lottery-statistics"> <h3>抽奖统计</h3> <div class="stats-grid"> <div class="stat-item"> <span class="stat-label">总参与人数</span> <span class="stat-value"><?php echo $verification_data['total_participants']; ?></span> </div> <div class="stat-item"> <span class="stat-label">中奖人数</span> <span class="stat-value"><?php echo count($winners); ?></span> </div> <div class="stat-item"> <span class="stat-label">中奖率</span> <span class="stat-value"> <?php if ($verification_data['total_participants'] > 0) { echo round((count($winners) / $verification_data['total_participants']) * 100, 2) . '%'; } else { echo '0%'; } ?> </span> </div> </div> </div> </div> <script> function lotteryShowVerificationDetails() { var details = document.getElementById('verification-details'); if (details.style.display === 'none') { details.style.display = 'block'; } else { details.style.display = 'none'; } } </script> <?php return ob_get_clean(); } }
- class Lottery_Verification_System { /** * 验证抽奖结果的真实性 */ public function verify_draw_result($activity_id, $user_provided_hash = '') { global $wpdb; // 获取存储的验证数据 $table_name = $wpdb->prefix . 'lottery_verification'; $verification = $wpdb->get_row($wpdb->prepare( "SELECT * FROM $table_name WHERE activity_id = %d", $activity_id )); if (!$verification) { return array( 'valid' => false, 'message' => '未找到该活动的验证数据' ); } // 计算哈希 $calculated_hash = hash('sha256', $verification->verification_data); // 验证哈希 if ($user_provided_hash && $user_provided_hash !== $calculated_hash) { return array( 'valid' => false, 'message' => '哈希值不匹配,数据可能被篡改' ); } // 解析验证数据 $verification_data = json_decode($verification->verification_data, true); // 验证参与者数据 $participants_valid = $this->verify_participants( $activity_id, $verification_data['participant_ids'] ); // 验证中奖者数据 $winners_valid = $this->verify_winners( $activity_id, $verification_data['winner_ids'] ); // 重新计算哈希验证 $recalculated_hash = hash('sha256', json_encode($verification_data)); return array( 'valid' => $participants_valid && $winners_valid && ($recalculated_hash === $calculated_hash), 'message' => $participants_valid && $winners_valid ? '验证通过' : '数据验证失败', 'verification_data' => $verification_data, 'stored_hash' => $verification->hash_value, 'calculated_hash' => $calculated_hash ); } /** * 提供公开的验证接口 */ public function public_verification_endpoint() { if (!isset($_GET['activity_id']) || !isset($_GET['hash'])) { wp_send_json_error(array('message' => '缺少必要参数')); } $activity_id = intval($_GET['activity_id']); $hash = sanitize_text_field($_GET['hash']); $result = $this->verify_draw_result($activity_id, $hash); wp_send_json(array( 'success' => $result['valid'], 'data' => $result )); } }
-
-
- /* assets/css/lottery-public.css */ .lottery-container { max-width: 1200px; margin: 0 auto; padding: 20px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif; } /* 参与表单样式 */ .lottery-participation-form { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 15px; padding: 40px; color: white; box-shadow: 0 20px 40px rgba(0,0,0,0.1); } .lottery-form-title { font-size: 2.5rem; margin-bottom: 10px; text-align: center; } .lottery-form-description { text-align: center; opacity: 0.9; margin-bottom: 30px; } .form-group { margin-bottom: 20px; } .form-control { width: 100%; padding: 12px 15px; border: none; border-radius: 8px; font-size: 16px; background: rgba(255,255,255,0.9); } .btn-participate { background: #ff6b6b; color: white; border: none; padding: 15px 30px; border-radius: 8px; font-size: 18px; font-weight: bold; cursor: pointer; width: 100%; transition: transform 0.3s, box-shadow 0.3s; } .btn-participate:hover { transform: translateY(-2px); box-shadow: 0 10px 20px rgba(255,107,107,0.3); } /* 结果展示样式 */ .lottery-results-container { background: white; border-radius: 15px; overflow: hidden; box-shadow: 0 10px 30px rgba(0,0,0,0.1); } .lottery-results-header { background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%); color: white; padding: 30px; text-align: center; } .winners-list { padding: 20px; } .winner-item { display: flex; align-items: center; padding: 20px; margin-bottom: 15px; background: #f8f9fa; border-radius: 10px; border-left: 5px solid #4facfe; transition: transform 0.3s; } .winner-item:hover { transform: translateX(10px); background: #e9ecef; } .winner-rank { font-size: 24px; font-weight: bold; color: #4facfe; margin-right: 20px; min-width: 50px; } .winner-info h4 { margin: 0 0 5px 0; color: #333; } .winner-name { font-size: 18px; font-weight: bold; color: #555; margin: 0 0 5px 0; } .winner-code { font-family: monospace; color: #666; font-size: 14px; margin: 0; } /* 统计信息样式 */ .lottery-statistics { padding: 30px; background: #f8f9fa; } .stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; } .stat-item { background: white; padding: 20px; border-radius: 10px; text-align: center; box-shadow: 0 5px 15px rgba(0,0,0,0.05); } .stat-label { display: block; color: #666; font-size: 14px; margin-bottom: 5px; } .stat-value { display: block; font-size: 32px; font-weight: bold; color: #4facfe; } /* 响应式设计 */ @media (max-width: 768px) { .lottery-container { padding: 10px; } .lottery-participation-form { padding: 20px; } .lottery-form-title { font-size: 1.8rem; } .winner-item { flex-direction: column; text-align: center; } .winner-rank { margin-right: 0; margin-bottom: 10px; } .stats-grid { grid-template-columns: 1fr; } } /* 动画效果 */ @keyframes fadeIn { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } .lottery-results-container { animation: fadeIn 0.6s ease-out; } .winner-item { animation: fadeIn 0.5s ease-out; animation-fill-mode: both; } .winner-item:nth-child(1) { animation-delay: 0.1s; } .winner-item:nth-child(2) { animation-delay: 0.2s; } .winner-item:nth-child(3) { animation-delay: 0.3s; } .winner-item:nth-child(4) { animation-delay: 0.4s; } .winner-item:nth-child(5) { animation-delay: 0.5s; }
- // assets/js/lottery-public.js jQuery(document).ready(function($) { // 参与抽奖 $('.lottery-participation-form').on('submit', function(e) { e.preventDefault(); var form = $(this); var submitBtn = form.find('.btn-participate'); var originalText = submitBtn.text(); // 显示加载状态 submitBtn.prop('disabled', true).text('提交中...'); // 收集表单数据 var formData = form.serialize(); $.ajax({ url: lottery_ajax.ajax_url, type: 'POST', data: { action: 'lottery_participate', nonce: lottery_ajax.nonce, form_data: formData }, success: function(response) { if (response.success) { // 显示成功消息 form.html(` <div class="participation-success"> <div class="success-icon">🎉</div> <h3>参与成功!</h3>
随着互联网活动的日益普及,在线抽奖已成为企业营销、社区互动和用户增长的重要手段。然而,如何确保抽奖过程的公平性和中奖结果的公信力,一直是组织者面临的挑战。本文将详细介绍如何通过WordPress程序的代码二次开发,实现一个功能完善的在线抽奖与中奖结果公证展示系统。我们将从系统设计、功能实现、安全性保障到用户体验优化等多个维度进行全面解析,帮助开发者构建一个既实用又可信赖的在线抽奖平台。
在线抽奖系统不仅是一个简单的随机选择工具,更是一个集用户参与、活动管理、结果公证和营销推广于一体的综合平台。一个优秀的在线抽奖系统应具备以下特点:
- 公平性:确保每个参与者有平等的获奖机会
- 透明性:抽奖过程和中奖结果可追溯、可验证
- 易用性:用户参与简单,管理后台操作便捷
- 可扩展性:支持多种抽奖规则和活动形式
- 安全性:防止作弊和恶意攻击
基于WordPress开发在线抽奖系统,我们需要实现以下核心功能:
- 用户参与模块:注册、登录、参与抽奖
- 抽奖活动管理:创建、编辑、删除抽奖活动
- 抽奖规则设置:参与条件、中奖人数、奖品设置
- 实时抽奖引擎:公平的随机算法实现
- 中奖结果展示:可视化展示中奖结果
- 公证验证系统:提供抽奖过程的可验证证据
- 数据统计与分析:参与数据、中奖率等统计
选择WordPress作为开发基础有以下优势:
- 成熟的用户管理系统
- 丰富的插件生态和主题支持
- 良好的扩展性和二次开发能力
- 广泛的技术社区支持
系统架构采用WordPress核心+自定义插件+定制主题的模式,确保系统稳定性的同时提供高度定制化功能。
在开始开发前,需要准备以下环境:
- 本地开发环境:推荐使用XAMPP、MAMP或Local by Flywheel
- WordPress安装:最新稳定版WordPress
- 代码编辑器:VS Code、PHPStorm等
- 版本控制:Git
- 调试工具:Query Monitor、Debug Bar等WordPress调试插件
我们将创建一个独立插件来管理所有抽奖功能:
<?php
/**
* Plugin Name: 在线抽奖与公证系统
* Plugin URI: https://yourwebsite.com/
* Description: 功能完整的在线抽奖与中奖结果公证展示系统
* Version: 1.0.0
* Author: Your Name
* License: GPL v2 or later
*/
// 防止直接访问
if (!defined('ABSPATH')) {
exit;
}
// 定义插件常量
define('LOTTERY_PLUGIN_PATH', plugin_dir_path(__FILE__));
define('LOTTERY_PLUGIN_URL', plugin_dir_url(__FILE__));
define('LOTTERY_VERSION', '1.0.0');
// 初始化插件
require_once LOTTERY_PLUGIN_PATH . 'includes/class-lottery-core.php';
function lottery_init() {
$lottery = new Lottery_Core();
$lottery->init();
}
add_action('plugins_loaded', 'lottery_init');
我们需要创建自定义数据表来存储抽奖活动、参与记录和中奖信息:
// 在插件激活时创建数据表
function lottery_create_tables() {
global $wpdb;
$charset_collate = $wpdb->get_charset_collate();
// 抽奖活动表
$table_activities = $wpdb->prefix . 'lottery_activities';
$sql_activities = "CREATE TABLE IF NOT EXISTS $table_activities (
id INT(11) NOT NULL AUTO_INCREMENT,
title VARCHAR(255) NOT NULL,
description TEXT,
start_date DATETIME NOT NULL,
end_date DATETIME NOT NULL,
status ENUM('draft', 'active', 'ended', 'cancelled') DEFAULT 'draft',
rules TEXT,
prizes TEXT,
winner_count INT(11) DEFAULT 1,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id)
) $charset_collate;";
// 参与记录表
$table_participants = $wpdb->prefix . 'lottery_participants';
$sql_participants = "CREATE TABLE IF NOT EXISTS $table_participants (
id INT(11) NOT NULL AUTO_INCREMENT,
activity_id INT(11) NOT NULL,
user_id INT(11),
user_email VARCHAR(255),
user_name VARCHAR(255),
ip_address VARCHAR(45),
user_agent TEXT,
participation_code VARCHAR(100) UNIQUE,
status ENUM('valid', 'invalid') DEFAULT 'valid',
participated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
INDEX activity_user (activity_id, user_id),
FOREIGN KEY (activity_id) REFERENCES $table_activities(id) ON DELETE CASCADE
) $charset_collate;";
// 中奖记录表
$table_winners = $wpdb->prefix . 'lottery_winners';
$sql_winners = "CREATE TABLE IF NOT EXISTS $table_winners (
id INT(11) NOT NULL AUTO_INCREMENT,
activity_id INT(11) NOT NULL,
participant_id INT(11) NOT NULL,
prize_level INT(11),
prize_name VARCHAR(255),
awarded_at DATETIME DEFAULT CURRENT_TIMESTAMP,
verification_hash VARCHAR(255),
PRIMARY KEY (id),
FOREIGN KEY (activity_id) REFERENCES $table_activities(id) ON DELETE CASCADE,
FOREIGN KEY (participant_id) REFERENCES $table_participants(id) ON DELETE CASCADE
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql_activities);
dbDelta($sql_participants);
dbDelta($sql_winners);
}
register_activation_hook(__FILE__, 'lottery_create_tables');
创建抽奖活动管理后台页面:
class Lottery_Admin {
public function __construct() {
add_action('admin_menu', array($this, 'add_admin_menu'));
add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'));
}
public function add_admin_menu() {
add_menu_page(
'在线抽奖系统',
'抽奖管理',
'manage_options',
'lottery-management',
array($this, 'render_admin_page'),
'dashicons-tickets-alt',
30
);
add_submenu_page(
'lottery-management',
'抽奖活动',
'活动列表',
'manage_options',
'lottery-activities',
array($this, 'render_activities_page')
);
add_submenu_page(
'lottery-management',
'添加抽奖活动',
'添加活动',
'manage_options',
'lottery-add-activity',
array($this, 'render_add_activity_page')
);
}
public function render_activities_page() {
include LOTTERY_PLUGIN_PATH . 'admin/views/activities-list.php';
}
public function render_add_activity_page() {
include LOTTERY_PLUGIN_PATH . 'admin/views/activity-form.php';
}
public function enqueue_admin_scripts($hook) {
if (strpos($hook, 'lottery') !== false) {
wp_enqueue_style('lottery-admin-style', LOTTERY_PLUGIN_URL . 'assets/css/admin.css');
wp_enqueue_script('lottery-admin-script', LOTTERY_PLUGIN_URL . 'assets/js/admin.js', array('jquery', 'jquery-ui-datepicker'), LOTTERY_VERSION, true);
wp_enqueue_style('jquery-ui-style', '//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css');
}
}
}
// 处理活动表单提交
function lottery_save_activity() {
if (!isset($_POST['lottery_nonce']) || !wp_verify_nonce($_POST['lottery_nonce'], 'lottery_save_activity')) {
wp_die('安全验证失败');
}
global $wpdb;
$table_name = $wpdb->prefix . 'lottery_activities';
$data = array(
'title' => sanitize_text_field($_POST['title']),
'description' => wp_kses_post($_POST['description']),
'start_date' => sanitize_text_field($_POST['start_date']),
'end_date' => sanitize_text_field($_POST['end_date']),
'status' => sanitize_text_field($_POST['status']),
'winner_count' => intval($_POST['winner_count']),
'rules' => wp_json_encode($_POST['rules']),
'prizes' => wp_json_encode($_POST['prizes'])
);
if (isset($_POST['activity_id']) && !empty($_POST['activity_id'])) {
// 更新现有活动
$wpdb->update($table_name, $data, array('id' => intval($_POST['activity_id'])));
$message = '活动更新成功';
} else {
// 创建新活动
$wpdb->insert($table_name, $data);
$message = '活动创建成功';
}
wp_redirect(admin_url('admin.php?page=lottery-activities&message=' . urlencode($message)));
exit;
}
add_action('admin_post_lottery_save_activity', 'lottery_save_activity');
// 处理活动表单提交
function lottery_save_activity() {
if (!isset($_POST['lottery_nonce']) || !wp_verify_nonce($_POST['lottery_nonce'], 'lottery_save_activity')) {
wp_die('安全验证失败');
}
global $wpdb;
$table_name = $wpdb->prefix . 'lottery_activities';
$data = array(
'title' => sanitize_text_field($_POST['title']),
'description' => wp_kses_post($_POST['description']),
'start_date' => sanitize_text_field($_POST['start_date']),
'end_date' => sanitize_text_field($_POST['end_date']),
'status' => sanitize_text_field($_POST['status']),
'winner_count' => intval($_POST['winner_count']),
'rules' => wp_json_encode($_POST['rules']),
'prizes' => wp_json_encode($_POST['prizes'])
);
if (isset($_POST['activity_id']) && !empty($_POST['activity_id'])) {
// 更新现有活动
$wpdb->update($table_name, $data, array('id' => intval($_POST['activity_id'])));
$message = '活动更新成功';
} else {
// 创建新活动
$wpdb->insert($table_name, $data);
$message = '活动创建成功';
}
wp_redirect(admin_url('admin.php?page=lottery-activities&message=' . urlencode($message)));
exit;
}
add_action('admin_post_lottery_save_activity', 'lottery_save_activity');
创建短代码让用户可以在任何页面参与抽奖:
class Lottery_Shortcodes {
public function __construct() {
add_shortcode('lottery_participation', array($this, 'render_participation_form'));
add_shortcode('lottery_results', array($this, 'render_results_display'));
}
public function render_participation_form($atts) {
$atts = shortcode_atts(array(
'activity_id' => 0,
'title' => '参与抽奖'
), $atts);
$activity_id = intval($atts['activity_id']);
if (!$activity_id) {
return '<p>错误:未指定抽奖活动</p>';
}
// 检查活动状态
$activity = $this->get_activity($activity_id);
if (!$activity) {
return '<p>错误:抽奖活动不存在</p>';
}
// 检查活动时间
$current_time = current_time('mysql');
if ($current_time < $activity->start_date) {
return '<div class="lottery-notice">抽奖活动尚未开始</div>';
}
if ($current_time > $activity->end_date) {
return '<div class="lottery-notice">抽奖活动已结束</div>';
}
// 检查用户是否已参与
$user_id = get_current_user_id();
$has_participated = $this->check_participation($activity_id, $user_id);
if ($has_participated) {
return '<div class="lottery-notice">您已参与本次抽奖,请等待开奖结果</div>';
}
// 渲染参与表单
ob_start();
include LOTTERY_PLUGIN_PATH . 'public/views/participation-form.php';
return ob_get_clean();
}
private function get_activity($activity_id) {
global $wpdb;
$table_name = $wpdb->prefix . 'lottery_activities';
return $wpdb->get_row($wpdb->prepare(
"SELECT * FROM $table_name WHERE id = %d AND status = 'active'",
$activity_id
));
}
private function check_participation($activity_id, $user_id) {
global $wpdb;
$table_name = $wpdb->prefix . 'lottery_participants';
if ($user_id) {
return $wpdb->get_var($wpdb->prepare(
"SELECT COUNT(*) FROM $table_name WHERE activity_id = %d AND user_id = %d",
$activity_id, $user_id
));
}
return false;
}
}
// 处理用户参与请求
function lottery_handle_participation() {
// 验证nonce
if (!isset($_POST['lottery_nonce']) || !wp_verify_nonce($_POST['lottery_nonce'], 'lottery_participate')) {
wp_send_json_error(array('message' => '安全验证失败'));
}
$activity_id = intval($_POST['activity_id']);
// 验证活动
$activity = lottery_get_activity($activity_id);
if (!$activity || $activity->status !== 'active') {
wp_send_json_error(array('message' => '抽奖活动无效或已结束'));
}
// 检查时间
$current_time = current_time('mysql');
if ($current_time < $activity->start_date || $current_time > $activity->end_date) {
wp_send_json_error(array('message' => '不在抽奖活动时间内'));
}
// 获取用户信息
$user_id = get_current_user_id();
$user_email = '';
$user_name = '';
if ($user_id) {
$user = get_userdata($user_id);
$user_email = $user->user_email;
$user_name = $user->display_name;
} else {
// 匿名用户需要提供邮箱
if (empty($_POST['user_email']) || !is_email($_POST['user_email'])) {
wp_send_json_error(array('message' => '请输入有效的邮箱地址'));
}
$user_email = sanitize_email($_POST['user_email']);
$user_name = !empty($_POST['user_name']) ? sanitize_text_field($_POST['user_name']) : '';
}
// 检查是否已参与
if (lottery_check_participation($activity_id, $user_id, $user_email)) {
wp_send_json_error(array('message' => '您已经参与过本次抽奖'));
}
// 生成参与码
$participation_code = lottery_generate_participation_code();
// 保存参与记录
global $wpdb;
$table_name = $wpdb->prefix . 'lottery_participants';
$data = array(
'activity_id' => $activity_id,
'user_id' => $user_id,
'user_email' => $user_email,
'user_name' => $user_name,
'ip_address' => lottery_get_client_ip(),
'user_agent' => $_SERVER['HTTP_USER_AGENT'],
'participation_code' => $participation_code
);
$result = $wpdb->insert($table_name, $data);
if ($result) {
// 发送确认邮件
lottery_send_participation_email($user_email, $activity, $participation_code);
wp_send_json_success(array(
'message' => '参与成功!您的参与码是:' . $participation_code,
'code' => $participation_code
));
} else {
wp_send_json_error(array('message' => '参与失败,请稍后重试'));
}
}
add_action('wp_ajax_lottery_participate', 'lottery_handle_participation');
add_action('wp_ajax_nopriv_lottery_participate', 'lottery_handle_participation');
// 处理用户参与请求
function lottery_handle_participation() {
// 验证nonce
if (!isset($_POST['lottery_nonce']) || !wp_verify_nonce($_POST['lottery_nonce'], 'lottery_participate')) {
wp_send_json_error(array('message' => '安全验证失败'));
}
$activity_id = intval($_POST['activity_id']);
// 验证活动
$activity = lottery_get_activity($activity_id);
if (!$activity || $activity->status !== 'active') {
wp_send_json_error(array('message' => '抽奖活动无效或已结束'));
}
// 检查时间
$current_time = current_time('mysql');
if ($current_time < $activity->start_date || $current_time > $activity->end_date) {
wp_send_json_error(array('message' => '不在抽奖活动时间内'));
}
// 获取用户信息
$user_id = get_current_user_id();
$user_email = '';
$user_name = '';
if ($user_id) {
$user = get_userdata($user_id);
$user_email = $user->user_email;
$user_name = $user->display_name;
} else {
// 匿名用户需要提供邮箱
if (empty($_POST['user_email']) || !is_email($_POST['user_email'])) {
wp_send_json_error(array('message' => '请输入有效的邮箱地址'));
}
$user_email = sanitize_email($_POST['user_email']);
$user_name = !empty($_POST['user_name']) ? sanitize_text_field($_POST['user_name']) : '';
}
// 检查是否已参与
if (lottery_check_participation($activity_id, $user_id, $user_email)) {
wp_send_json_error(array('message' => '您已经参与过本次抽奖'));
}
// 生成参与码
$participation_code = lottery_generate_participation_code();
// 保存参与记录
global $wpdb;
$table_name = $wpdb->prefix . 'lottery_participants';
$data = array(
'activity_id' => $activity_id,
'user_id' => $user_id,
'user_email' => $user_email,
'user_name' => $user_name,
'ip_address' => lottery_get_client_ip(),
'user_agent' => $_SERVER['HTTP_USER_AGENT'],
'participation_code' => $participation_code
);
$result = $wpdb->insert($table_name, $data);
if ($result) {
// 发送确认邮件
lottery_send_participation_email($user_email, $activity, $participation_code);
wp_send_json_success(array(
'message' => '参与成功!您的参与码是:' . $participation_code,
'code' => $participation_code
));
} else {
wp_send_json_error(array('message' => '参与失败,请稍后重试'));
}
}
add_action('wp_ajax_lottery_participate', 'lottery_handle_participation');
add_action('wp_ajax_nopriv_lottery_participate', 'lottery_handle_participation');
class Lottery_Draw_Engine {
/**
* 执行抽奖
* @param int $activity_id 活动ID
* @param int $winner_count 中奖人数
* @return array 中奖者列表
*/
public function draw_winners($activity_id, $winner_count) {
// 获取所有有效参与者
$participants = $this->get_valid_participants($activity_id);
if (empty($participants)) {
return array('success' => false, 'message' => '没有有效参与者');
}
if (count($participants) < $winner_count) {
return array('success' => false, 'message' => '参与者数量少于中奖人数');
}
// 使用加密安全的随机数生成器
$winners = $this->secure_random_draw($participants, $winner_count);
// 记录中奖结果
$result = $this->record_winners($activity_id, $winners);
// 生成可验证的抽奖证明
$verification_data = $this->generate_verification_data($activity_id, $participants, $winners);
return array(
'success' => true,
'winners' => $winners,
'verification_hash' => $verification_data['hash'],
'verification_data' => $verification_data['data']
);
}
/**
* 加密安全的随机抽选算法
*/
private function secure_random_draw($participants, $winner_count) {
$total = count($participants);
$winners = array();
$selected_indices = array();
// 使用加密安全的随机数生成器
while (count($winners) < $winner_count) {
// 生成随机索引
$random_index = random_int(0, $total - 1);
// 确保不重复选择
if (!in_array($random_index, $selected_indices)) {
$selected_indices[] = $random_index;
$winners[] = $participants[$random_index];
}
}
return $winners;
}
/**
* 生成可验证的抽奖证明
*/
private function generate_verification_data($activity_id, $participants, $winners) {
// 创建抽奖数据快照
$snapshot = array(
'activity_id' => $activity_id,
'draw_time' => current_time('mysql'),
'total_participants' => count($participants),
'participant_ids' => array_column($participants, 'id'),
'winner_ids' => array_column($winners, 'id'),
'server_seed' => bin2hex(random_bytes(32)),
'client_seed' => $this->get_client_seed($activity_id)
);
// 计算验证哈希
$hash_data = json_encode($snapshot);
$verification_hash = hash('sha256', $hash_data);
// 保存验证数据
$this->save_verification_data($activity_id, $hash_data, $verification_hash);
return array(
'hash' => $verification_hash,
'data' => $snapshot
);
}
/**
* 获取客户端种子(基于活动数据)
*/
private function get_client_seed($activity_id) {
global $wpdb;
$table_name = $wpdb->prefix . 'lottery_activities';
$activity = $wpdb->get_row($wpdb->prepare(
"SELECT title, start_date, end_date FROM $table_name WHERE id = %d",
$activity_id
));
if ($activity) {
return hash('sha256', $activity->title . $activity->start_date . $activity->end_date);
}
return hash('sha256', (string) $activity_id);
}
}
class Lottery_Draw_Engine {
/**
* 执行抽奖
* @param int $activity_id 活动ID
* @param int $winner_count 中奖人数
* @return array 中奖者列表
*/
public function draw_winners($activity_id, $winner_count) {
// 获取所有有效参与者
$participants = $this->get_valid_participants($activity_id);
if (empty($participants)) {
return array('success' => false, 'message' => '没有有效参与者');
}
if (count($participants) < $winner_count) {
return array('success' => false, 'message' => '参与者数量少于中奖人数');
}
// 使用加密安全的随机数生成器
$winners = $this->secure_random_draw($participants, $winner_count);
// 记录中奖结果
$result = $this->record_winners($activity_id, $winners);
// 生成可验证的抽奖证明
$verification_data = $this->generate_verification_data($activity_id, $participants, $winners);
return array(
'success' => true,
'winners' => $winners,
'verification_hash' => $verification_data['hash'],
'verification_data' => $verification_data['data']
);
}
/**
* 加密安全的随机抽选算法
*/
private function secure_random_draw($participants, $winner_count) {
$total = count($participants);
$winners = array();
$selected_indices = array();
// 使用加密安全的随机数生成器
while (count($winners) < $winner_count) {
// 生成随机索引
$random_index = random_int(0, $total - 1);
// 确保不重复选择
if (!in_array($random_index, $selected_indices)) {
$selected_indices[] = $random_index;
$winners[] = $participants[$random_index];
}
}
return $winners;
}
/**
* 生成可验证的抽奖证明
*/
private function generate_verification_data($activity_id, $participants, $winners) {
// 创建抽奖数据快照
$snapshot = array(
'activity_id' => $activity_id,
'draw_time' => current_time('mysql'),
'total_participants' => count($participants),
'participant_ids' => array_column($participants, 'id'),
'winner_ids' => array_column($winners, 'id'),
'server_seed' => bin2hex(random_bytes(32)),
'client_seed' => $this->get_client_seed($activity_id)
);
// 计算验证哈希
$hash_data = json_encode($snapshot);
$verification_hash = hash('sha256', $hash_data);
// 保存验证数据
$this->save_verification_data($activity_id, $hash_data, $verification_hash);
return array(
'hash' => $verification_hash,
'data' => $snapshot
);
}
/**
* 获取客户端种子(基于活动数据)
*/
private function get_client_seed($activity_id) {
global $wpdb;
$table_name = $wpdb->prefix . 'lottery_activities';
$activity = $wpdb->get_row($wpdb->prepare(
"SELECT title, start_date, end_date FROM $table_name WHERE id = %d",
$activity_id
));
if ($activity) {
return hash('sha256', $activity->title . $activity->start_date . $activity->end_date);
}
return hash('sha256', (string) $activity_id);
}
}
// 后台执行抽奖的接口
function lottery_execute_draw() {
if (!current_user_can('manage_options')) {
wp_die('权限不足');
}
$activity_id = intval($_POST['activity_id']);
// 验证活动状态
$activity = lottery_get_activity($activity_id);
if (!$activity || $activity->status !== 'active') {
wp_send_json_error(array('message' => '活动状态不允许抽奖'));
}
// 检查是否已开奖
if (lottery_has_winners($activity_id)) {
wp_send_json_error(array('message' => '该活动已开奖'));
}
// 执行抽奖
$draw_engine = new Lottery_Draw_Engine();
$result = $draw_engine->draw_winners($activity_id, $activity->winner_count);
if ($result['success']) {
// 更新活动状态
lottery_update_activity_status($activity_id, 'ended');
// 发送中奖通知
lottery_send_winner_notifications($activity_id, $result['winners']);
wp_send_json_success(array(
'message' => '抽奖完成',
'winners' => $result['winners'],
'verification_hash' => $result['verification_hash']
));
} else {
wp_send_json_error(array('message' => $result['message']));
}
}
add_action('wp_ajax_lottery_execute_draw', 'lottery_execute_draw');
// 后台执行抽奖的接口
function lottery_execute_draw() {
if (!current_user_can('manage_options')) {
wp_die('权限不足');
}
$activity_id = intval($_POST['activity_id']);
// 验证活动状态
$activity = lottery_get_activity($activity_id);
if (!$activity || $activity->status !== 'active') {
wp_send_json_error(array('message' => '活动状态不允许抽奖'));
}
// 检查是否已开奖
if (lottery_has_winners($activity_id)) {
wp_send_json_error(array('message' => '该活动已开奖'));
}
// 执行抽奖
$draw_engine = new Lottery_Draw_Engine();
$result = $draw_engine->draw_winners($activity_id, $activity->winner_count);
if ($result['success']) {
// 更新活动状态
lottery_update_activity_status($activity_id, 'ended');
// 发送中奖通知
lottery_send_winner_notifications($activity_id, $result['winners']);
wp_send_json_success(array(
'message' => '抽奖完成',
'winners' => $result['winners'],
'verification_hash' => $result['verification_hash']
));
} else {
wp_send_json_error(array('message' => $result['message']));
}
}
add_action('wp_ajax_lottery_execute_draw', 'lottery_execute_draw');
class Lottery_Results_Display {
public function render_results($activity_id) {
$activity = lottery_get_activity($activity_id);
$winners = lottery_get_winners($activity_id);
$verification_data = lottery_get_verification_data($activity_id);
ob_start();
?>
<div class="lottery-results-container">
<div class="lottery-results-header">
<h2><?php echo esc_html($activity->title); ?> - 中奖结果</h2>
<div class="lottery-meta">
<span class="lottery-date">开奖时间: <?php echo date('Y-m-d H:i:s', strtotime($verification_data['draw_time'])); ?></span>
<span class="lottery-participants">参与人数: <?php echo $verification_data['total_participants']; ?></span>
</div>
</div>
<div class="lottery-verification-section">
<h3>抽奖公正性验证</h3>
<div class="verification-info">
<p>验证哈希: <code class="verification-hash"><?php echo esc_html($verification_data['hash']); ?></code></p>
<button class="btn-verify" onclick="lotteryShowVerificationDetails()">查看验证详情</button>
</div>
<div id="verification-details" style="display: none;">
<h4>抽奖数据快照</h4>
<pre><?php echo json_encode($verification_data['data'], JSON_PRETTY_PRINT); ?></pre>
<p>您可以使用SHA256哈希验证器验证上述数据的哈希值是否匹配。</p>
</div>
</div>
<div class="lottery-winners-section">
<h3>中奖名单</h3>
<?php if (!empty($winners)): ?>
<div class="winners-list">
<?php foreach ($winners as $index => $winner): ?>
<div class="winner-item">
<div class="winner-rank"><?php echo $index + 1; ?></div>
<div class="winner-info">
<h4><?php echo esc_html($winner->prize_name); ?></h4>
<p class="winner-name">
<?php
if ($winner->user_name) {
echo esc_html(mb_substr($winner->user_name, 0, 1) . '**');
} else {
echo esc_html(substr($winner->user_email, 0, 3) . '***' . substr($winner->user_email, strpos($winner->user_email, '@')));
}
?>
</p>
<p class="winner-code">参与码: <?php echo esc_html($winner->participation_code); ?></p>
</div>
</div>
<?php endforeach; ?>
</div>
<?php else: ?>
<p class="no-winners">暂无中奖者</p>
<?php endif; ?>
</div>
<div class="lottery-statistics">
<h3>抽奖统计</h3>
<div class="stats-grid">
<div class="stat-item">
<span class="stat-label">总参与人数</span>
<span class="stat-value"><?php echo $verification_data['total_participants']; ?></span>
</div>
<div class="stat-item">
<span class="stat-label">中奖人数</span>
<span class="stat-value"><?php echo count($winners); ?></span>
</div>
<div class="stat-item">
<span class="stat-label">中奖率</span>
<span class="stat-value">
<?php
if ($verification_data['total_participants'] > 0) {
echo round((count($winners) / $verification_data['total_participants']) * 100, 2) . '%';
} else {
echo '0%';
}
?>
</span>
</div>
</div>
</div>
</div>
<script>
function lotteryShowVerificationDetails() {
var details = document.getElementById('verification-details');
if (details.style.display === 'none') {
details.style.display = 'block';
} else {
details.style.display = 'none';
}
}
</script>
<?php
return ob_get_clean();
}
}
class Lottery_Results_Display {
public function render_results($activity_id) {
$activity = lottery_get_activity($activity_id);
$winners = lottery_get_winners($activity_id);
$verification_data = lottery_get_verification_data($activity_id);
ob_start();
?>
<div class="lottery-results-container">
<div class="lottery-results-header">
<h2><?php echo esc_html($activity->title); ?> - 中奖结果</h2>
<div class="lottery-meta">
<span class="lottery-date">开奖时间: <?php echo date('Y-m-d H:i:s', strtotime($verification_data['draw_time'])); ?></span>
<span class="lottery-participants">参与人数: <?php echo $verification_data['total_participants']; ?></span>
</div>
</div>
<div class="lottery-verification-section">
<h3>抽奖公正性验证</h3>
<div class="verification-info">
<p>验证哈希: <code class="verification-hash"><?php echo esc_html($verification_data['hash']); ?></code></p>
<button class="btn-verify" onclick="lotteryShowVerificationDetails()">查看验证详情</button>
</div>
<div id="verification-details" style="display: none;">
<h4>抽奖数据快照</h4>
<pre><?php echo json_encode($verification_data['data'], JSON_PRETTY_PRINT); ?></pre>
<p>您可以使用SHA256哈希验证器验证上述数据的哈希值是否匹配。</p>
</div>
</div>
<div class="lottery-winners-section">
<h3>中奖名单</h3>
<?php if (!empty($winners)): ?>
<div class="winners-list">
<?php foreach ($winners as $index => $winner): ?>
<div class="winner-item">
<div class="winner-rank"><?php echo $index + 1; ?></div>
<div class="winner-info">
<h4><?php echo esc_html($winner->prize_name); ?></h4>
<p class="winner-name">
<?php
if ($winner->user_name) {
echo esc_html(mb_substr($winner->user_name, 0, 1) . '**');
} else {
echo esc_html(substr($winner->user_email, 0, 3) . '***' . substr($winner->user_email, strpos($winner->user_email, '@')));
}
?>
</p>
<p class="winner-code">参与码: <?php echo esc_html($winner->participation_code); ?></p>
</div>
</div>
<?php endforeach; ?>
</div>
<?php else: ?>
<p class="no-winners">暂无中奖者</p>
<?php endif; ?>
</div>
<div class="lottery-statistics">
<h3>抽奖统计</h3>
<div class="stats-grid">
<div class="stat-item">
<span class="stat-label">总参与人数</span>
<span class="stat-value"><?php echo $verification_data['total_participants']; ?></span>
</div>
<div class="stat-item">
<span class="stat-label">中奖人数</span>
<span class="stat-value"><?php echo count($winners); ?></span>
</div>
<div class="stat-item">
<span class="stat-label">中奖率</span>
<span class="stat-value">
<?php
if ($verification_data['total_participants'] > 0) {
echo round((count($winners) / $verification_data['total_participants']) * 100, 2) . '%';
} else {
echo '0%';
}
?>
</span>
</div>
</div>
</div>
</div>
<script>
function lotteryShowVerificationDetails() {
var details = document.getElementById('verification-details');
if (details.style.display === 'none') {
details.style.display = 'block';
} else {
details.style.display = 'none';
}
}
</script>
<?php
return ob_get_clean();
}
}
class Lottery_Verification_System {
/**
* 验证抽奖结果的真实性
*/
public function verify_draw_result($activity_id, $user_provided_hash = '') {
global $wpdb;
// 获取存储的验证数据
$table_name = $wpdb->prefix . 'lottery_verification';
$verification = $wpdb->get_row($wpdb->prepare(
"SELECT * FROM $table_name WHERE activity_id = %d",
$activity_id
));
if (!$verification) {
return array(
'valid' => false,
'message' => '未找到该活动的验证数据'
);
}
// 计算哈希
$calculated_hash = hash('sha256', $verification->verification_data);
// 验证哈希
if ($user_provided_hash && $user_provided_hash !== $calculated_hash) {
return array(
'valid' => false,
'message' => '哈希值不匹配,数据可能被篡改'
);
}
// 解析验证数据
$verification_data = json_decode($verification->verification_data, true);
// 验证参与者数据
$participants_valid = $this->verify_participants(
$activity_id,
$verification_data['participant_ids']
);
// 验证中奖者数据
$winners_valid = $this->verify_winners(
$activity_id,
$verification_data['winner_ids']
);
// 重新计算哈希验证
$recalculated_hash = hash('sha256', json_encode($verification_data));
return array(
'valid' => $participants_valid && $winners_valid && ($recalculated_hash === $calculated_hash),
'message' => $participants_valid && $winners_valid ? '验证通过' : '数据验证失败',
'verification_data' => $verification_data,
'stored_hash' => $verification->hash_value,
'calculated_hash' => $calculated_hash
);
}
/**
* 提供公开的验证接口
*/
public function public_verification_endpoint() {
if (!isset($_GET['activity_id']) || !isset($_GET['hash'])) {
wp_send_json_error(array('message' => '缺少必要参数'));
}
$activity_id = intval($_GET['activity_id']);
$hash = sanitize_text_field($_GET['hash']);
$result = $this->verify_draw_result($activity_id, $hash);
wp_send_json(array(
'success' => $result['valid'],
'data' => $result
));
}
}
class Lottery_Verification_System {
/**
* 验证抽奖结果的真实性
*/
public function verify_draw_result($activity_id, $user_provided_hash = '') {
global $wpdb;
// 获取存储的验证数据
$table_name = $wpdb->prefix . 'lottery_verification';
$verification = $wpdb->get_row($wpdb->prepare(
"SELECT * FROM $table_name WHERE activity_id = %d",
$activity_id
));
if (!$verification) {
return array(
'valid' => false,
'message' => '未找到该活动的验证数据'
);
}
// 计算哈希
$calculated_hash = hash('sha256', $verification->verification_data);
// 验证哈希
if ($user_provided_hash && $user_provided_hash !== $calculated_hash) {
return array(
'valid' => false,
'message' => '哈希值不匹配,数据可能被篡改'
);
}
// 解析验证数据
$verification_data = json_decode($verification->verification_data, true);
// 验证参与者数据
$participants_valid = $this->verify_participants(
$activity_id,
$verification_data['participant_ids']
);
// 验证中奖者数据
$winners_valid = $this->verify_winners(
$activity_id,
$verification_data['winner_ids']
);
// 重新计算哈希验证
$recalculated_hash = hash('sha256', json_encode($verification_data));
return array(
'valid' => $participants_valid && $winners_valid && ($recalculated_hash === $calculated_hash),
'message' => $participants_valid && $winners_valid ? '验证通过' : '数据验证失败',
'verification_data' => $verification_data,
'stored_hash' => $verification->hash_value,
'calculated_hash' => $calculated_hash
);
}
/**
* 提供公开的验证接口
*/
public function public_verification_endpoint() {
if (!isset($_GET['activity_id']) || !isset($_GET['hash'])) {
wp_send_json_error(array('message' => '缺少必要参数'));
}
$activity_id = intval($_GET['activity_id']);
$hash = sanitize_text_field($_GET['hash']);
$result = $this->verify_draw_result($activity_id, $hash);
wp_send_json(array(
'success' => $result['valid'],
'data' => $result
));
}
}
/* assets/css/lottery-public.css */
.lottery-container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
}
/* 参与表单样式 */
.lottery-participation-form {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 15px;
padding: 40px;
color: white;
box-shadow: 0 20px 40px rgba(0,0,0,0.1);
}
.lottery-form-title {
font-size: 2.5rem;
margin-bottom: 10px;
text-align: center;
}
.lottery-form-description {
text-align: center;
opacity: 0.9;
margin-bottom: 30px;
}
.form-group {
margin-bottom: 20px;
}
.form-control {
width: 100%;
padding: 12px 15px;
border: none;
border-radius: 8px;
font-size: 16px;
background: rgba(255,255,255,0.9);
}
.btn-participate {
background: #ff6b6b;
color: white;
border: none;
padding: 15px 30px;
border-radius: 8px;
font-size: 18px;
font-weight: bold;
cursor: pointer;
width: 100%;
transition: transform 0.3s, box-shadow 0.3s;
}
.btn-participate:hover {
transform: translateY(-2px);
box-shadow: 0 10px 20px rgba(255,107,107,0.3);
}
/* 结果展示样式 */
.lottery-results-container {
background: white;
border-radius: 15px;
overflow: hidden;
box-shadow: 0 10px 30px rgba(0,0,0,0.1);
}
.lottery-results-header {
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
color: white;
padding: 30px;
text-align: center;
}
.winners-list {
padding: 20px;
}
.winner-item {
display: flex;
align-items: center;
padding: 20px;
margin-bottom: 15px;
background: #f8f9fa;
border-radius: 10px;
border-left: 5px solid #4facfe;
transition: transform 0.3s;
}
.winner-item:hover {
transform: translateX(10px);
background: #e9ecef;
}
.winner-rank {
font-size: 24px;
font-weight: bold;
color: #4facfe;
margin-right: 20px;
min-width: 50px;
}
.winner-info h4 {
margin: 0 0 5px 0;
color: #333;
}
.winner-name {
font-size: 18px;
font-weight: bold;
color: #555;
margin: 0 0 5px 0;
}
.winner-code {
font-family: monospace;
color: #666;
font-size: 14px;
margin: 0;
}
/* 统计信息样式 */
.lottery-statistics {
padding: 30px;
background: #f8f9fa;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 20px;
}
.stat-item {
background: white;
padding: 20px;
border-radius: 10px;
text-align: center;
box-shadow: 0 5px 15px rgba(0,0,0,0.05);
}
.stat-label {
display: block;
color: #666;
font-size: 14px;
margin-bottom: 5px;
}
.stat-value {
display: block;
font-size: 32px;
font-weight: bold;
color: #4facfe;
}
/* 响应式设计 */
@media (max-width: 768px) {
.lottery-container {
padding: 10px;
}
.lottery-participation-form {
padding: 20px;
}
.lottery-form-title {
font-size: 1.8rem;
}
.winner-item {
flex-direction: column;
text-align: center;
}
.winner-rank {
margin-right: 0;
margin-bottom: 10px;
}
.stats-grid {
grid-template-columns: 1fr;
}
}
/* 动画效果 */
@keyframes fadeIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
.lottery-results-container {
animation: fadeIn 0.6s ease-out;
}
.winner-item {
animation: fadeIn 0.5s ease-out;
animation-fill-mode: both;
}
.winner-item:nth-child(1) { animation-delay: 0.1s; }
.winner-item:nth-child(2) { animation-delay: 0.2s; }
.winner-item:nth-child(3) { animation-delay: 0.3s; }
.winner-item:nth-child(4) { animation-delay: 0.4s; }
.winner-item:nth-child(5) { animation-delay: 0.5s; }
/* assets/css/lottery-public.css */
.lottery-container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
}
/* 参与表单样式 */
.lottery-participation-form {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 15px;
padding: 40px;
color: white;
box-shadow: 0 20px 40px rgba(0,0,0,0.1);
}
.lottery-form-title {
font-size: 2.5rem;
margin-bottom: 10px;
text-align: center;
}
.lottery-form-description {
text-align: center;
opacity: 0.9;
margin-bottom: 30px;
}
.form-group {
margin-bottom: 20px;
}
.form-control {
width: 100%;
padding: 12px 15px;
border: none;
border-radius: 8px;
font-size: 16px;
background: rgba(255,255,255,0.9);
}
.btn-participate {
background: #ff6b6b;
color: white;
border: none;
padding: 15px 30px;
border-radius: 8px;
font-size: 18px;
font-weight: bold;
cursor: pointer;
width: 100%;
transition: transform 0.3s, box-shadow 0.3s;
}
.btn-participate:hover {
transform: translateY(-2px);
box-shadow: 0 10px 20px rgba(255,107,107,0.3);
}
/* 结果展示样式 */
.lottery-results-container {
background: white;
border-radius: 15px;
overflow: hidden;
box-shadow: 0 10px 30px rgba(0,0,0,0.1);
}
.lottery-results-header {
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
color: white;
padding: 30px;
text-align: center;
}
.winners-list {
padding: 20px;
}
.winner-item {
display: flex;
align-items: center;
padding: 20px;
margin-bottom: 15px;
background: #f8f9fa;
border-radius: 10px;
border-left: 5px solid #4facfe;
transition: transform 0.3s;
}
.winner-item:hover {
transform: translateX(10px);
background: #e9ecef;
}
.winner-rank {
font-size: 24px;
font-weight: bold;
color: #4facfe;
margin-right: 20px;
min-width: 50px;
}
.winner-info h4 {
margin: 0 0 5px 0;
color: #333;
}
.winner-name {
font-size: 18px;
font-weight: bold;
color: #555;
margin: 0 0 5px 0;
}
.winner-code {
font-family: monospace;
color: #666;
font-size: 14px;
margin: 0;
}
/* 统计信息样式 */
.lottery-statistics {
padding: 30px;
background: #f8f9fa;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 20px;
}
.stat-item {
background: white;
padding: 20px;
border-radius: 10px;
text-align: center;
box-shadow: 0 5px 15px rgba(0,0,0,0.05);
}
.stat-label {
display: block;
color: #666;
font-size: 14px;
margin-bottom: 5px;
}
.stat-value {
display: block;
font-size: 32px;
font-weight: bold;
color: #4facfe;
}
/* 响应式设计 */
@media (max-width: 768px) {
.lottery-container {
padding: 10px;
}
.lottery-participation-form {
padding: 20px;
}
.lottery-form-title {
font-size: 1.8rem;
}
.winner-item {
flex-direction: column;
text-align: center;
}
.winner-rank {
margin-right: 0;
margin-bottom: 10px;
}
.stats-grid {
grid-template-columns: 1fr;
}
}
/* 动画效果 */
@keyframes fadeIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
.lottery-results-container {
animation: fadeIn 0.6s ease-out;
}
.winner-item {
animation: fadeIn 0.5s ease-out;
animation-fill-mode: both;
}
.winner-item:nth-child(1) { animation-delay: 0.1s; }
.winner-item:nth-child(2) { animation-delay: 0.2s; }
.winner-item:nth-child(3) { animation-delay: 0.3s; }
.winner-item:nth-child(4) { animation-delay: 0.4s; }
.winner-item:nth-child(5) { animation-delay: 0.5s; }
// assets/js/lottery-public.js
jQuery(document).ready(function($) {
// 参与抽奖
$('.lottery-participation-form').on('submit', function(e) {
e.preventDefault();
var form = $(this);
var submitBtn = form.find('.btn-participate');
var originalText = submitBtn.text();
// 显示加载状态
submitBtn.prop('disabled', true).text('提交中...');
// 收集表单数据
var formData = form.serialize();
$.ajax({
url: lottery_ajax.ajax_url,
type: 'POST',
data: {
action: 'lottery_participate',
nonce: lottery_ajax.nonce,
form_data: formData
},
success: function(response) {
if (response.success) {
// 显示成功消息
form.html(`
<div class="participation-success">
<div class="success-icon">🎉</div>
<h3>参与成功!</h3>
// assets/js/lottery-public.js
jQuery(document).ready(function($) {
// 参与抽奖
$('.lottery-participation-form').on('submit', function(e) {
e.preventDefault();
var form = $(this);
var submitBtn = form.find('.btn-participate');
var originalText = submitBtn.text();
// 显示加载状态
submitBtn.prop('disabled', true).text('提交中...');
// 收集表单数据
var formData = form.serialize();
$.ajax({
url: lottery_ajax.ajax_url,
type: 'POST',
data: {
action: 'lottery_participate',
nonce: lottery_ajax.nonce,
form_data: formData
},
success: function(response) {
if (response.success) {
// 显示成功消息
form.html(`
<div class="participation-success">
<div class="success-icon">🎉</div>
<h3>参与成功!</h3>


