WordPress Security for Event and Ticketing Websites
Event websites handle registrations, payments, and attendee data. Learn how to secure your event site, protect ticket sales, and prevent fraud.
Event and ticketing websites handle sensitive data including personal information, payment details, and access credentials. Whether you're managing conferences, concerts, or workshops, security is essential for protecting attendees and your reputation.
Event Site Security Challenges
- Payment processing - Ticket sales require PCI compliance
- Attendee data - Personal and contact information
- High traffic periods - Ticket release spikes
- Ticket fraud - Scalping and fake tickets
- Check-in systems - QR codes and access control
Registration Security
Secure Registration Forms
// Secure event registration
function secure_event_registration($data) {
// Validate nonce
if (!wp_verify_nonce($data['_wpnonce'], 'event_registration')) {
return new WP_Error('invalid_nonce', 'Security check failed.');
}
// Sanitize all input
$clean_data = array(
'name' => sanitize_text_field($data['name']),
'email' => sanitize_email($data['email']),
'phone' => sanitize_text_field($data['phone']),
'event_id' => absint($data['event_id']),
'ticket_type' => sanitize_key($data['ticket_type'])
);
// Rate limit registrations
$ip = wpfs_get_client_ip();
$key = 'reg_attempts_' . md5($ip);
$attempts = get_transient($key) ?: 0;
if ($attempts > 10) {
return new WP_Error('rate_limited', 'Too many registration attempts.');
}
set_transient($key, $attempts + 1, HOUR_IN_SECONDS);
// Validate email isn't already registered
if (is_email_registered_for_event($clean_data['email'], $clean_data['event_id'])) {
return new WP_Error('duplicate', 'This email is already registered.');
}
return $clean_data;
}
Prevent Bot Registrations
// Honeypot and timing protection
function add_registration_protection() {
// Honeypot field
echo '
';
// Timestamp for timing check
echo '';
}
add_action('event_registration_form', 'add_registration_protection');
function validate_registration_protection($data) {
// Check honeypot
if (!empty($data['website_url'])) {
return new WP_Error('bot_detected', 'Registration failed.');
}
// Check timing (form submitted too quickly)
$load_time = intval($data['form_loaded']);
if (time() - $load_time < 3) {
return new WP_Error('too_fast', 'Please complete the form properly.');
}
return $data;
}
Ticket Security
Generate Secure Tickets
// Create secure, unique ticket codes
function generate_secure_ticket($registration_id, $event_id) {
// Generate unique ticket code
$random = bin2hex(random_bytes(8));
$data = $registration_id . '-' . $event_id . '-' . time();
$hash = hash('sha256', $data . $random);
$ticket_code = strtoupper(substr($hash, 0, 16));
// Store ticket with hash for verification
$ticket = array(
'code' => $ticket_code,
'registration_id' => $registration_id,
'event_id' => $event_id,
'verification_hash' => hash('sha256', $ticket_code . AUTH_KEY),
'status' => 'valid',
'created_at' => current_time('mysql')
);
global $wpdb;
$wpdb->insert($wpdb->prefix . 'event_tickets', $ticket);
return $ticket_code;
}
// Generate QR code for ticket
function generate_ticket_qr($ticket_code) {
// Include verification data in QR
$qr_data = json_encode(array(
'code' => $ticket_code,
'verify' => substr(hash('sha256', $ticket_code . AUTH_KEY), 0, 8)
));
return generate_qr_code($qr_data);
}
Verify Tickets at Check-in
// Secure ticket verification for check-in
function verify_ticket($ticket_code, $qr_verify = null) {
global $wpdb;
$ticket = $wpdb->get_row($wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}event_tickets
WHERE code = %s",
$ticket_code
));
if (!$ticket) {
return array('valid' => false, 'message' => 'Ticket not found');
}
// Verify hash if QR code used
if ($qr_verify) {
$expected = substr(hash('sha256', $ticket_code . AUTH_KEY), 0, 8);
if (!hash_equals($expected, $qr_verify)) {
log_fraud_attempt($ticket_code);
return array('valid' => false, 'message' => 'Invalid ticket');
}
}
// Check ticket status
if ($ticket->status === 'used') {
return array(
'valid' => false,
'message' => 'Ticket already used',
'used_at' => $ticket->used_at
);
}
if ($ticket->status === 'cancelled') {
return array('valid' => false, 'message' => 'Ticket cancelled');
}
// Mark as used
$wpdb->update(
$wpdb->prefix . 'event_tickets',
array(
'status' => 'used',
'used_at' => current_time('mysql'),
'checked_in_by' => get_current_user_id()
),
array('code' => $ticket_code)
);
return array('valid' => true, 'message' => 'Welcome!');
}
Fraud Prevention
// Prevent ticket scalping
function prevent_ticket_scalping($order_data) {
$email = $order_data['email'];
$event_id = $order_data['event_id'];
// Limit tickets per email
$existing = count_tickets_for_email($email, $event_id);
if ($existing >= 4) {
return new WP_Error('limit_exceeded', 'Maximum 4 tickets per person.');
}
// Check for disposable emails
if (is_disposable_email($email)) {
return new WP_Error('invalid_email', 'Please use a valid email address.');
}
return $order_data;
}
// Detect suspicious patterns
function detect_fraud_patterns($ip, $email) {
// Multiple orders from same IP with different emails
$ip_orders = count_orders_from_ip($ip, HOUR_IN_SECONDS);
if ($ip_orders > 5) {
flag_for_review($ip, 'Multiple orders from same IP');
return true;
}
return false;
}
High Traffic Preparation
- Use CDN for static assets
- Implement page caching
- Set up queue system for ticket releases
- Scale server resources before on-sale
Conclusion
Event websites require robust security for registrations, payments, and ticket verification. Implement secure ticket generation, fraud prevention, and proper check-in verification to protect your events and attendees.
Written by Sarah Chen
WP Folder Shield Team