SiamCafe.net Blog
Cybersecurity

WordPress WooCommerce Audit Trail Logging

wordpress woocommerce audit trail logging
WordPress WooCommerce Audit Trail Logging | SiamCafe Blog
2025-08-24· อ. บอม — SiamCafe.net· 1,852 คำ

WordPress WooCommerce Audit Trail Logging คืออะไร

Audit Trail Logging คือการบันทึกทุกกิจกรรมที่เกิดขึ้นในระบบอย่างละเอียด ใครทำอะไร เมื่อไหร่ จากไหน เพื่อ security compliance และ troubleshooting สำหรับ WordPress WooCommerce ซึ่งเป็น e-commerce platform ยอดนิยม audit trail สำคัญมากเพราะเกี่ยวข้องกับ orders การเงิน ข้อมูลลูกค้า และ inventory ครอบคลุม user actions, order changes, product modifications, payment events และ admin activities บทความนี้อธิบายวิธี implement audit trail logging สำหรับ WooCommerce พร้อม Python tools สำหรับวิเคราะห์ logs

Audit Trail Events

# audit_events.py — WooCommerce audit events
import json

class AuditEvents:
    EVENTS = {
        "orders": {
            "name": "Order Events",
            "events": [
                "order.created — สร้างคำสั่งซื้อใหม่",
                "order.status_changed — เปลี่ยนสถานะ (pending → processing → completed)",
                "order.refunded — คืนเงิน (จำนวน, เหตุผล, ผู้อนุมัติ)",
                "order.note_added — เพิ่มหมายเหตุ (internal/customer)",
                "order.deleted — ลบคำสั่งซื้อ (ใครลบ, เมื่อไหร่)",
                "order.edited — แก้ไขรายละเอียด (ราคา, สินค้า, ที่อยู่)",
            ],
        },
        "products": {
            "name": "Product Events",
            "events": [
                "product.created — สร้างสินค้าใหม่",
                "product.updated — แก้ไขสินค้า (ราคา, stock, description)",
                "product.deleted — ลบสินค้า",
                "product.stock_changed — stock เปลี่ยน (จาก X เป็น Y)",
                "product.price_changed — ราคาเปลี่ยน (เก่า → ใหม่)",
            ],
        },
        "users": {
            "name": "User Events",
            "events": [
                "user.login — เข้าสู่ระบบ (IP, browser, location)",
                "user.login_failed — เข้าสู่ระบบล้มเหลว",
                "user.role_changed — เปลี่ยน role (customer → shop_manager)",
                "user.profile_updated — แก้ไขโปรไฟล์",
                "user.created — สร้าง user ใหม่",
            ],
        },
        "settings": {
            "name": "Settings Events",
            "events": [
                "settings.changed — เปลี่ยนการตั้งค่า WooCommerce",
                "plugin.activated — เปิดใช้ plugin",
                "plugin.deactivated — ปิด plugin",
                "theme.switched — เปลี่ยน theme",
            ],
        },
        "payments": {
            "name": "Payment Events",
            "events": [
                "payment.received — ได้รับชำระเงิน",
                "payment.failed — ชำระเงินล้มเหลว",
                "payment.refund_initiated — เริ่มกระบวนการคืนเงิน",
                "payment.gateway_changed — เปลี่ยน payment gateway",
            ],
        },
    }

    def show_events(self):
        print("=== Audit Trail Events ===\n")
        for key, category in self.EVENTS.items():
            print(f"[{category['name']}]")
            for event in category["events"][:4]:
                print(f"  • {event}")
            print()

events = AuditEvents()
events.show_events()

WordPress Plugin Implementation

// audit_plugin.php — WooCommerce Audit Trail Plugin
// File: wp-content/plugins/wc-audit-trail/wc-audit-trail.php

/*
Plugin Name: WC Audit Trail
Description: Comprehensive audit trail logging for WooCommerce
Version: 1.0.0
*/

// Create audit log table on activation
register_activation_hook(__FILE__, function() {
    global $wpdb;
    $table = $wpdb->prefix . 'wc_audit_log';
    $charset = $wpdb->get_charset_collate();
    
    $sql = "CREATE TABLE IF NOT EXISTS $table (
        id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
        timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
        user_id BIGINT UNSIGNED,
        user_email VARCHAR(100),
        user_role VARCHAR(50),
        event_type VARCHAR(50) NOT NULL,
        object_type VARCHAR(50),
        object_id BIGINT UNSIGNED,
        action VARCHAR(50) NOT NULL,
        description TEXT,
        old_value LONGTEXT,
        new_value LONGTEXT,
        ip_address VARCHAR(45),
        user_agent TEXT,
        INDEX idx_timestamp (timestamp),
        INDEX idx_event_type (event_type),
        INDEX idx_object (object_type, object_id),
        INDEX idx_user (user_id)
    ) $charset;";
    
    require_once ABSPATH . 'wp-admin/includes/upgrade.php';
    dbDelta($sql);
});

// Core logging function
function wc_audit_log($event_type, $action, $description, $object_type = '', $object_id = 0, $old_value = '', $new_value = '') {
    global $wpdb;
    $user = wp_get_current_user();
    
    $wpdb->insert($wpdb->prefix . 'wc_audit_log', [
        'user_id'     => $user->ID,
        'user_email'  => $user->user_email,
        'user_role'   => implode(',', $user->roles),
        'event_type'  => $event_type,
        'object_type' => $object_type,
        'object_id'   => $object_id,
        'action'      => $action,
        'description' => $description,
        'old_value'   => is_array($old_value) ? json_encode($old_value) : $old_value,
        'new_value'   => is_array($new_value) ? json_encode($new_value) : $new_value,
        'ip_address'  => $_SERVER['REMOTE_ADDR'] ?? '',
        'user_agent'  => $_SERVER['HTTP_USER_AGENT'] ?? '',
    ]);
}

// Hook: Order status changed
add_action('woocommerce_order_status_changed', function($order_id, $old_status, $new_status) {
    wc_audit_log(
        'order', 'status_changed',
        "Order #$order_id status changed from $old_status to $new_status",
        'order', $order_id,
        $old_status, $new_status
    );
}, 10, 3);

// Hook: Product updated
add_action('woocommerce_update_product', function($product_id) {
    $product = wc_get_product($product_id);
    wc_audit_log(
        'product', 'updated',
        "Product '{$product->get_name()}' (#{$product_id}) updated",
        'product', $product_id
    );
});

// Hook: User login
add_action('wp_login', function($user_login, $user) {
    wc_audit_log(
        'user', 'login',
        "User '{$user_login}' logged in",
        'user', $user->ID
    );
}, 10, 2);

// Hook: Failed login
add_action('wp_login_failed', function($username) {
    wc_audit_log('user', 'login_failed', "Failed login attempt for '{$username}'");
});

Python Log Analyzer

# log_analyzer.py — Python audit log analyzer
import json

class AuditLogAnalyzer:
    CODE = """
# wc_audit_analyzer.py — Analyze WooCommerce audit logs
import mysql.connector
import pandas as pd
from datetime import datetime, timedelta
from collections import Counter

class WCAuditAnalyzer:
    def __init__(self, host, user, password, database):
        self.conn = mysql.connector.connect(
            host=host, user=user, password=password, database=database
        )
    
    def get_logs(self, days=30, event_type=None):
        query = '''
            SELECT * FROM wp_wc_audit_log
            WHERE timestamp >= %s
        '''
        params = [(datetime.now() - timedelta(days=days)).strftime('%Y-%m-%d')]
        
        if event_type:
            query += ' AND event_type = %s'
            params.append(event_type)
        
        query += ' ORDER BY timestamp DESC'
        
        df = pd.read_sql(query, self.conn, params=params)
        return df
    
    def suspicious_activities(self, days=7):
        df = self.get_logs(days)
        
        alerts = []
        
        # Failed logins > 5 per IP
        failed = df[df['action'] == 'login_failed']
        ip_counts = failed.groupby('ip_address').size()
        for ip, count in ip_counts.items():
            if count > 5:
                alerts.append({
                    'type': 'brute_force',
                    'detail': f"IP {ip}: {count} failed logins",
                    'severity': 'high',
                })
        
        # Large refunds
        refunds = df[df['action'] == 'refunded']
        for _, row in refunds.iterrows():
            if row.get('new_value') and float(row['new_value']) > 10000:
                alerts.append({
                    'type': 'large_refund',
                    'detail': f"Order #{row['object_id']}: refund {row['new_value']}",
                    'severity': 'medium',
                })
        
        # Off-hours admin activity
        df['hour'] = pd.to_datetime(df['timestamp']).dt.hour
        off_hours = df[(df['hour'] < 6) | (df['hour'] > 22)]
        admin_off = off_hours[off_hours['user_role'].str.contains('administrator', na=False)]
        if len(admin_off) > 0:
            alerts.append({
                'type': 'off_hours_admin',
                'detail': f"{len(admin_off)} admin actions outside business hours",
                'severity': 'low',
            })
        
        return alerts
    
    def generate_report(self, days=30):
        df = self.get_logs(days)
        
        return {
            'total_events': len(df),
            'unique_users': df['user_id'].nunique(),
            'events_by_type': dict(Counter(df['event_type'])),
            'actions_by_type': dict(Counter(df['action'])),
            'top_users': df['user_email'].value_counts().head(5).to_dict(),
        }

analyzer = WCAuditAnalyzer('localhost', 'root', 'password', 'wordpress')
report = analyzer.generate_report(30)
print(json.dumps(report, indent=2, default=str))
"""

    def show_code(self):
        print("=== Audit Log Analyzer ===")
        print(self.CODE[:600])

analyzer = AuditLogAnalyzer()
analyzer.show_code()

Compliance & Security

# compliance.py — Compliance requirements for audit trails
import json
import random

class ComplianceSecurity:
    STANDARDS = {
        "gdpr": {
            "name": "GDPR (EU)",
            "requirements": [
                "Log access to personal data",
                "Record data processing activities",
                "Support right to access (show logs)",
                "Retention: ลบ logs เก่าตาม policy",
            ],
        },
        "pci_dss": {
            "name": "PCI DSS (Payment Card)",
            "requirements": [
                "Log all access to cardholder data",
                "Track all admin actions",
                "Review logs daily",
                "Retain logs minimum 1 year",
            ],
        },
        "pdpa": {
            "name": "PDPA (Thailand)",
            "requirements": [
                "บันทึกการเก็บรวบรวมข้อมูลส่วนบุคคล",
                "บันทึกการเข้าถึงข้อมูลลูกค้า",
                "เก็บ logs ตาม retention policy",
                "รองรับคำขอเข้าถึงข้อมูลจากเจ้าของข้อมูล",
            ],
        },
    }

    SECURITY_PRACTICES = [
        "เก็บ audit logs แยก database — ป้องกัน attacker ลบ logs",
        "Log integrity: hash ทุก entry — detect tampering",
        "Forward logs ไป SIEM (Splunk, ELK) — centralized monitoring",
        "Encrypt sensitive data in logs (PII masking)",
        "Set retention policy: 1 ปี minimum สำหรับ PCI DSS",
        "Alert on suspicious patterns: brute force, mass changes, off-hours",
        "Read-only access to logs — admin ไม่ควรลบ/แก้ไข logs",
        "Backup audit logs แยก — ป้องกัน data loss",
    ]

    def show_standards(self):
        print("=== Compliance Standards ===\n")
        for key, std in self.STANDARDS.items():
            print(f"[{std['name']}]")
            for req in std["requirements"][:3]:
                print(f"  • {req}")
            print()

    def show_practices(self):
        print("=== Security Best Practices ===")
        for practice in self.SECURITY_PRACTICES[:6]:
            print(f"  • {practice}")

    def dashboard(self):
        print(f"\n=== Audit Dashboard (30-day) ===")
        print(f"  Total events: {random.randint(5000, 20000):,}")
        print(f"  Orders: {random.randint(500, 2000):,} events")
        print(f"  Products: {random.randint(200, 800):,} events")
        print(f"  Users: {random.randint(1000, 5000):,} events")
        print(f"  Failed logins: {random.randint(50, 300)}")
        print(f"  Suspicious: {random.randint(0, 10)} alerts")

comp = ComplianceSecurity()
comp.show_standards()
comp.show_practices()
comp.dashboard()

WooCommerce REST API Logging

# api_logging.py — Log WooCommerce REST API access
import json

class APILogging:
    CODE = """
// api-audit.php — Log REST API requests
add_filter('rest_pre_dispatch', function($result, $server, $request) {
    $route = $request->get_route();
    
    // Only log WooCommerce API calls
    if (strpos($route, '/wc/') !== false) {
        $method = $request->get_method();
        $params = $request->get_params();
        
        // Mask sensitive data
        if (isset($params['billing']['card_number'])) {
            $params['billing']['card_number'] = '****' . substr($params['billing']['card_number'], -4);
        }
        
        wc_audit_log(
            'api', strtolower($method),
            "API {$method} {$route}",
            'api', 0,
            '', json_encode($params)
        );
    }
    
    return $result;
}, 10, 3);

// Log webhook deliveries
add_action('woocommerce_webhook_delivery', function($http_args, $response, $duration, $arg, $webhook_id) {
    wc_audit_log(
        'webhook', 'delivered',
        "Webhook #{$webhook_id} delivered in {$duration}s",
        'webhook', $webhook_id,
        '', json_encode(['status' => wp_remote_retrieve_response_code($response)])
    );
}, 10, 5);
"""

    PLUGINS = {
        "wp_activity_log": {
            "name": "WP Activity Log",
            "description": "Plugin ยอดนิยมสำหรับ audit trail — รองรับ WooCommerce",
            "features": "400+ event types, email alerts, external DB, reports",
            "price": "Free / Premium $99/year",
        },
        "simple_history": {
            "name": "Simple History",
            "description": "Lightweight audit log plugin",
            "features": "User activity, plugin changes, post edits",
            "price": "Free",
        },
        "sucuri": {
            "name": "Sucuri Security",
            "description": "Security plugin with audit logging",
            "features": "File integrity, malware scan, audit logs",
            "price": "Free / Premium $199/year",
        },
    }

    def show_code(self):
        print("=== API Logging ===")
        print(self.CODE[:500])

    def show_plugins(self):
        print(f"\n=== Recommended Plugins ===")
        for key, plugin in self.PLUGINS.items():
            print(f"  [{plugin['name']}] {plugin['price']}")
            print(f"    {plugin['description']}")

api = APILogging()
api.show_code()
api.show_plugins()

FAQ - คำถามที่พบบ่อย

Q: ทำไม Audit Trail สำคัญสำหรับ WooCommerce?

A: สำคัญมากเพราะ: Security — detect unauthorized access, brute force, data theft Compliance — GDPR, PCI DSS, PDPA กำหนดให้ต้อง log Troubleshooting — ใครแก้ราคาสินค้า? ทำไม order หาย? Accountability — รู้ว่าใครทำอะไร เมื่อไหร่ ไม่มี audit trail = ตรวจจับปัญหาไม่ได้ + ไม่ผ่าน compliance

Q: ใช้ Plugin หรือ Custom development ดี?

A: Plugin (แนะนำเริ่มต้น): WP Activity Log — ครบ, รองรับ WooCommerce, มี free tier Custom development: ถ้าต้องการ specific events, integration กับ SIEM, compliance ที่ plugin ไม่ครอบคลุม แนะนำ: เริ่มจาก plugin → เพิ่ม custom hooks ถ้าต้องการมากกว่า

Q: Logs เยอะมาก database เต็มทำอย่างไร?

A: Retention policy: ลบ logs เก่ากว่า 1 ปี (หรือตาม compliance requirement) Archive: ย้าย logs เก่าไป external storage (S3, separate DB) External logging: forward ไป ELK Stack / Splunk — แยก logs ออกจาก WordPress DB Partitioning: partition table ตาม month — ลบ partition เก่าได้เร็ว

Q: ป้องกัน attacker ลบ audit logs ได้อย่างไร?

A: Forward logs ไป external system ทันที (syslog, SIEM) — attacker ลบ local ได้ แต่ external ไม่ได้ ใช้ separate database user สำหรับ audit — WordPress admin ลบไม่ได้ Immutable storage: S3 Object Lock, WORM storage Hash chain: hash ทุก entry ต่อกัน — detect ถ้ามีการลบ/แก้ไข

📖 บทความที่เกี่ยวข้อง

Apache Kafka Streams Audit Trail Loggingอ่านบทความ → BigQuery Scheduled Query Audit Trail Loggingอ่านบทความ → DNSSEC Implementation Audit Trail Loggingอ่านบทความ → Spark Structured Streaming Audit Trail Loggingอ่านบทความ → Skaffold Dev Audit Trail Loggingอ่านบทความ →

📚 ดูบทความทั้งหมด →