Best Practices

WordPress Security for E-commerce: Beyond WooCommerce Best Practices

Comprehensive e-commerce security covering Easy Digital Downloads, Shopify integrations, custom stores, and PCI compliance essentials.

S
Sarah Chen
9 min read
2,203 views
Comprehensive WordPress e-commerce security guide

E-commerce security extends beyond any single plugin. This guide covers universal security practices for WordPress online stores, regardless of the platform used.

E-commerce Security Fundamentals

All online stores must address:

  • Payment data protection and PCI compliance
  • Customer account security
  • Order and transaction integrity
  • Inventory and pricing protection
  • Fraud detection and prevention

Payment Security Essentials

Never store card data locally:

// Use tokenization for all payments
function process_secure_payment($order_id, $payment_token) {
    // Never process raw card numbers
    if (isset($_POST['card_number'])) {
        log_security_violation('Raw card data submitted');
        return new WP_Error('security', 'Invalid payment method');
    }

    // Validate token format
    if (!preg_match('/^tok_[a-zA-Z0-9]+$/', $payment_token)) {
        return new WP_Error('invalid_token', 'Invalid payment token');
    }

    // Process with payment provider
    $result = process_tokenized_payment(
        $payment_token,
        get_order_total($order_id),
        get_order_currency($order_id)
    );

    // Log transaction (without sensitive data)
    log_transaction(array(
        'order_id' => $order_id,
        'status' => $result['status'],
        'transaction_id' => $result['id'],
        'amount' => $result['amount'],
        // Never log card numbers or CVV
    ));

    return $result;
}

Order Integrity Protection

Prevent order manipulation:

function validate_order_submission($order_data) {
    // Recalculate totals server-side
    $calculated_total = 0;

    foreach ($order_data['items'] as $item) {
        $product = get_product($item['product_id']);

        if (!$product || !$product['in_stock']) {
            return new WP_Error('invalid_product', 'Product not available');
        }

        // Use database price, not submitted price
        $price = $product['price'];

        // Apply valid discounts only
        if (!empty($item['discount_code'])) {
            $discount = validate_discount_code($item['discount_code'], $item['product_id']);
            if ($discount) {
                $price = apply_discount($price, $discount);
            }
        }

        $calculated_total += $price * intval($item['quantity']);
    }

    // Add shipping
    $shipping = calculate_shipping(
        $order_data['shipping_address'],
        $order_data['shipping_method']
    );
    $calculated_total += $shipping;

    // Add taxes
    $tax = calculate_tax($calculated_total, $order_data['billing_address']);
    $calculated_total += $tax;

    // Compare with submitted total
    if (abs($calculated_total - $order_data['total']) > 0.01) {
        log_security_event(array(
            'type' => 'price_manipulation',
            'submitted' => $order_data['total'],
            'calculated' => $calculated_total,
            'ip' => $_SERVER['REMOTE_ADDR'],
        ));

        // Use calculated total regardless
        $order_data['total'] = $calculated_total;
    }

    return $order_data;
}

Customer Account Protection

Secure customer accounts and data:

// Require re-authentication for sensitive actions
function protect_account_actions() {
    $sensitive_actions = array(
        'change_email',
        'change_password',
        'update_payment_method',
        'view_order_history',
        'download_invoice',
    );

    $action = $_POST['action'] ?? $_GET['action'] ?? '';

    if (in_array($action, $sensitive_actions)) {
        $last_auth = get_user_meta(get_current_user_id(), 'last_password_entry', true);

        // Require password every 15 minutes
        if (!$last_auth || (time() - $last_auth) > 900) {
            wp_redirect(add_query_arg('reauth', 1, wp_login_url()));
            exit;
        }
    }
}
add_action('init', 'protect_account_actions');

// Protect customer data in exports
function sanitize_customer_export($customer_data) {
    // Mask payment information
    if (isset($customer_data['payment_methods'])) {
        foreach ($customer_data['payment_methods'] as &$method) {
            $method['card_number'] = '**** **** **** ' . substr($method['card_last4'], -4);
            unset($method['card_last4']);
        }
    }

    // Remove sensitive metadata
    unset($customer_data['password_hash']);
    unset($customer_data['security_questions']);

    return $customer_data;
}

Inventory Security

Protect inventory and pricing data:

// Log all inventory changes
add_action('update_post_meta', function($meta_id, $post_id, $meta_key, $meta_value) {
    $inventory_keys = array('_stock', '_price', '_sale_price', '_stock_status');

    if (!in_array($meta_key, $inventory_keys)) {
        return;
    }

    $old_value = get_post_meta($post_id, $meta_key, true);

    global $wpdb;
    $wpdb->insert('inventory_audit_log', array(
        'product_id' => $post_id,
        'field' => $meta_key,
        'old_value' => $old_value,
        'new_value' => $meta_value,
        'changed_by' => get_current_user_id(),
        'changed_at' => current_time('mysql'),
        'ip_address' => $_SERVER['REMOTE_ADDR'] ?? 'CLI',
    ));

    // Alert on significant changes
    if ($meta_key === '_price') {
        $change_percent = abs(($meta_value - $old_value) / $old_value * 100);

        if ($change_percent > 25) {
            wp_mail(
                get_option('admin_email'),
                'Large price change detected',
                sprintf(
                    'Product %d price changed from %s to %s (%.1f%%)',
                    $post_id, $old_value, $meta_value, $change_percent
                )
            );
        }
    }
}, 10, 4);

Fraud Detection

Implement basic fraud scoring:

function calculate_fraud_score($order) {
    $score = 0;
    $flags = array();

    // Check billing/shipping mismatch
    if ($order['billing_address'] !== $order['shipping_address']) {
        $score += 10;
        $flags[] = 'Address mismatch';
    }

    // Check for high-risk countries
    $high_risk_countries = array('XX', 'YY'); // Configure as needed
    if (in_array($order['billing_country'], $high_risk_countries)) {
        $score += 20;
        $flags[] = 'High-risk country';
    }

    // Check order velocity
    $recent_orders = get_orders_by_email($order['email'], '-24 hours');
    if (count($recent_orders) > 3) {
        $score += 25;
        $flags[] = 'Multiple orders in 24h';
    }

    // Check for disposable email
    if (is_disposable_email($order['email'])) {
        $score += 30;
        $flags[] = 'Disposable email';
    }

    // Check IP reputation
    $ip_risk = check_ip_reputation($order['ip_address']);
    if ($ip_risk > 50) {
        $score += 20;
        $flags[] = 'Risky IP address';
    }

    // Check for proxy/VPN
    if (is_proxy_ip($order['ip_address'])) {
        $score += 15;
        $flags[] = 'Proxy/VPN detected';
    }

    return array(
        'score' => $score,
        'flags' => $flags,
        'action' => $score > 50 ? 'review' : ($score > 30 ? 'flag' : 'approve'),
    );
}

Digital Product Protection

Secure downloadable products:

function generate_secure_download_link($product_id, $order_id, $user_id) {
    // Verify purchase
    if (!user_purchased_product($user_id, $product_id, $order_id)) {
        return new WP_Error('not_purchased', 'Product not purchased');
    }

    // Check download limits
    $downloads = get_download_count($order_id, $product_id);
    $limit = get_download_limit($product_id);

    if ($limit > 0 && $downloads >= $limit) {
        return new WP_Error('limit_exceeded', 'Download limit reached');
    }

    // Generate signed URL
    $expires = time() + 3600; // 1 hour
    $data = array(
        'product' => $product_id,
        'order' => $order_id,
        'user' => $user_id,
        'expires' => $expires,
    );

    $signature = hash_hmac('sha256', json_encode($data), wp_salt('auth'));

    return add_query_arg(array(
        'download' => base64_encode(json_encode($data)),
        'sig' => $signature,
    ), home_url('/download/'));
}

function serve_download($download_data, $signature) {
    $data = json_decode(base64_decode($download_data), true);

    // Verify signature
    $expected = hash_hmac('sha256', json_encode($data), wp_salt('auth'));

    if (!hash_equals($expected, $signature)) {
        wp_die('Invalid download link');
    }

    // Check expiration
    if ($data['expires'] < time()) {
        wp_die('Download link expired');
    }

    // Log download
    log_download($data['product'], $data['order'], $data['user']);

    // Serve file
    $file_path = get_product_file_path($data['product']);
    serve_file_download($file_path);
}

Conclusion

E-commerce security requires payment protection, order validation, customer account security, inventory monitoring, fraud detection, and secure digital delivery. Regular security audits ensure ongoing protection of your store and customers.

Share:
S
Written by Sarah Chen

WP Folder Shield Team

Related Articles

Automated vs Manual WordPress Malware Scanning: Which is Better?
Automated vs Manual WordPress Malware Scanning: Which is Better?

Compare automated and manual WordPress malware scanning approaches. Learn when to use each method...

January 17, 2026
Preventing WordPress Malware: 10 Essential Security Practices
Preventing WordPress Malware: 10 Essential Security Practices

Learn 10 essential security practices to prevent WordPress malware infections. Protect your site...

January 13, 2026
WordPress Directory Browsing: Why and How to Disable It
WordPress Directory Browsing: Why and How to Disable It

Learn why WordPress directory browsing is a security risk and how to disable it. Prevent attackers...

January 12, 2026

Ready to Secure Your WordPress Site?

Get complete protection with WP Folder Shield.

Get Started