WordPress Security for Booking and Appointment Websites
Secure your booking or appointment WordPress site with payment protection, calendar security, and customer data safeguards.
Introduction
Booking and appointment websites handle sensitive customer data including contact information, payment details, and personal schedules. These sites require robust security to protect both business operations and customer privacy.
Security Challenges for Booking Sites
Appointment platforms face specific vulnerabilities:
- Payment fraud - Stolen cards used for fake bookings
- Booking spam - Bots filling calendars with fake appointments
- Data exposure - Customer information in booking confirmations
- Calendar manipulation - Unauthorized schedule changes
- Deposit theft - Attackers intercepting payments
- API abuse - Exploiting booking API endpoints
Protecting Booking Forms
Secure the booking process against abuse:
Rate Limiting and Bot Protection
// Rate limit booking submissions
function rate_limit_bookings() {
$ip = $_SERVER['REMOTE_ADDR'];
$key = 'booking_rate_' . md5($ip);
$submissions = get_transient($key) ?: 0;
if ($submissions >= 5) {
wp_die('Too many booking attempts. Please try again later.');
}
set_transient($key, $submissions + 1, HOUR_IN_SECONDS);
}
add_action('wpfs_before_booking_submit', 'rate_limit_bookings');
// Honeypot field for bot detection
function add_booking_honeypot($form) {
$form .= '';
return $form;
}
add_filter('booking_form_html', 'add_booking_honeypot');
// Check honeypot on submission
function check_booking_honeypot() {
if (!empty($_POST['website_url'])) {
// Bot detected
error_log('Bot booking attempt from: ' . $_SERVER['REMOTE_ADDR']);
wp_die('Booking failed.');
}
}
add_action('wpfs_before_booking_submit', 'check_booking_honeypot');
Customer Data Protection
Safeguard personal information in bookings:
Encrypt Sensitive Data
// Encrypt customer phone numbers and notes
function encrypt_booking_data($data) {
$key = defined('WPFS_ENCRYPTION_KEY') ? WPFS_ENCRYPTION_KEY : AUTH_KEY;
$sensitive_fields = array('phone', 'notes', 'medical_info');
foreach ($sensitive_fields as $field) {
if (isset($data[$field]) && !empty($data[$field])) {
$iv = openssl_random_pseudo_bytes(16);
$encrypted = openssl_encrypt(
$data[$field],
'AES-256-CBC',
$key,
0,
$iv
);
$data[$field] = base64_encode($iv . $encrypted);
$data[$field . '_encrypted'] = true;
}
}
return $data;
}
// Decrypt for authorized access
function decrypt_booking_field($encrypted_value) {
$key = defined('WPFS_ENCRYPTION_KEY') ? WPFS_ENCRYPTION_KEY : AUTH_KEY;
$data = base64_decode($encrypted_value);
$iv = substr($data, 0, 16);
$encrypted = substr($data, 16);
return openssl_decrypt($encrypted, 'AES-256-CBC', $key, 0, $iv);
}
Payment Security
Protect deposits and payment processing:
Secure Payment Handling
// Validate payment before confirming booking
function validate_booking_payment($booking_id) {
$booking = get_booking($booking_id);
// Verify payment with processor
$payment_id = $booking['payment_id'];
$stripe = new StripeStripeClient(STRIPE_SECRET_KEY);
try {
$payment = $stripe->paymentIntents->retrieve($payment_id);
if ($payment->status !== 'succeeded') {
update_booking_status($booking_id, 'payment_failed');
return false;
}
// Verify amount matches
if ($payment->amount !== $booking['deposit_amount']) {
error_log("Payment amount mismatch for booking {$booking_id}");
return false;
}
return true;
} catch (Exception $e) {
error_log("Payment verification failed: " . $e->getMessage());
return false;
}
}
// Prevent duplicate bookings
function prevent_duplicate_bookings($customer_email, $service_id, $datetime) {
global $wpdb;
$existing = $wpdb->get_var($wpdb->prepare("
SELECT COUNT(*)
FROM {$wpdb->prefix}bookings
WHERE customer_email = %s
AND service_id = %d
AND booking_datetime = %s
AND status != 'cancelled'
", $customer_email, $service_id, $datetime));
return $existing > 0;
}
Calendar Access Control
Restrict who can view and modify schedules:
// Role-based calendar access
function check_calendar_access($user_id, $action, $calendar_id = null) {
$user = get_userdata($user_id);
// Define permissions
$permissions = array(
'administrator' => array('view', 'edit', 'delete', 'export'),
'booking_manager' => array('view', 'edit'),
'staff' => array('view'),
);
foreach ($user->roles as $role) {
if (isset($permissions[$role]) && in_array($action, $permissions[$role])) {
return true;
}
}
return false;
}
// Log calendar modifications
add_action('booking_modified', function($booking_id, $old_data, $new_data) {
global $wpdb;
$wpdb->insert($wpdb->prefix . 'booking_audit_log', array(
'booking_id' => $booking_id,
'user_id' => get_current_user_id(),
'action' => 'modified',
'old_datetime' => $old_data['datetime'],
'new_datetime' => $new_data['datetime'],
'ip_address' => $_SERVER['REMOTE_ADDR'],
'created_at' => current_time('mysql'),
));
}, 10, 3);
Confirmation Email Security
Protect information in booking confirmations:
- Never include full payment details in emails
- Use masked phone numbers in confirmations
- Include secure links instead of sensitive data
- Implement email verification for new customers
API Security for Booking Integrations
// Secure booking API endpoint
add_action('rest_api_init', function() {
register_rest_route('bookings/v1', '/availability', array(
'methods' => 'GET',
'callback' => 'get_booking_availability',
'permission_callback' => function() {
// Verify API key
$api_key = $_SERVER['HTTP_X_API_KEY'] ?? '';
return verify_booking_api_key($api_key);
},
));
});
function verify_booking_api_key($key) {
$valid_keys = get_option('wpfs_booking_api_keys', array());
return in_array(hash('sha256', $key), $valid_keys);
}
Conclusion
Booking websites must protect customer data, prevent spam bookings, and secure payment processing. Implement encryption, rate limiting, and proper access controls to build customer trust and protect your business.
Written by Sarah Chen
WP Folder Shield Team