跳转到主要内容

Step 4: Advanced Integration Techniques

Step 4: Advanced Integration Techniques

Handling WooCommerce Webhooks

WooCommerce webhooks can be used to receive real-time notifications about events in your WooCommerce stores:

namespace MyCompany\WooCommerce\Webhooks;

use WP_REST_Request;
use WP_REST_Response;
use Exception;

/**
 * Register webhook handlers
 */
public function register_webhook_handlers() {
    // Register webhook endpoint
    add_action('rest_api_init', function() {
        register_rest_route('mainwp-woocommerce/v1', '/webhook/(?P<website_id>\d+)', [
            'methods' => 'POST',
            'callback' => [$this, 'handle_webhook'],
            'permission_callback' => [$this, 'verify_webhook'],
        ]);
    });
}

/**
 * Verify webhook request
 * 
 * @param WP_REST_Request $request Request object
 * @return bool Whether the request is valid
 */
public function verify_webhook($request) {
    // Validate website ID
    $website_id = absint($request->get_param('website_id'));
    if ($website_id <= 0) {
        return false;
    }
    
    $signature = $request->get_header('X-WC-Webhook-Signature');
    if (empty($signature)) {
        // Log missing signature if WP_DEBUG_LOG is enabled
        if (defined('WP_DEBUG_LOG') && WP_DEBUG_LOG) {
            error_log(sprintf(
                '[MainWP WooCommerce] Missing webhook signature for website ID: %d',
                $website_id
            ));
        }
        return false;
    }
    
    // Get webhook secret for this site
    $settings = get_option('mainwp_woocommerce_settings', []);
    $site_settings = isset($settings[$website_id]) ? $settings[$website_id] : [];
    
    if (empty($site_settings['webhook_secret'])) {
        // Log missing webhook secret if WP_DEBUG_LOG is enabled
        if (defined('WP_DEBUG_LOG') && WP_DEBUG_LOG) {
            error_log(sprintf(
                '[MainWP WooCommerce] Webhook secret not configured for website ID: %d',
                $website_id
            ));
        }
        return false;
    }
    
    // Verify signature with constant-time comparison to prevent timing attacks
    $payload = $request->get_body();
    $calculated_signature = hash_hmac('sha256', $payload, $site_settings['webhook_secret']);
    
    return hash_equals($calculated_signature, $signature);
}

/**
 * Handle webhook request
 * 
 * @param WP_REST_Request $request Request object
 * @return WP_REST_Response Response object
 */
public function handle_webhook($request) {
    $website_id = absint($request->get_param('website_id'));
    $payload = json_decode($request->get_body(), true);
    
    if (!$payload || !isset($payload['topic'])) {
        return new WP_REST_Response([
            'success' => false,
            'message' => 'Invalid payload or missing topic'
        ], 400);
    }
    
    try {
        // Process webhook based on topic
        switch ($payload['topic']) {
            case 'order.created':
                $this->process_new_order($website_id, $payload['data']);
                break;
            case 'product.updated':
                $this->process_product_update($website_id, $payload['data']);
                break;
            default:
                // Log unknown topic if WP_DEBUG_LOG is enabled
                if (defined('WP_DEBUG_LOG') && WP_DEBUG_LOG) {
                    error_log(sprintf(
                        '[MainWP WooCommerce] Unknown webhook topic: %s for website ID: %d',
                        $payload['topic'],
                        $website_id
                    ));
                }
                return new WP_REST_Response([
                    'success' => false,
                    'message' => 'Unknown webhook topic'
                ], 400);
        }
        
        return new WP_REST_Response(['success' => true]);
    } catch (Exception $e) {
        // Log exception if WP_DEBUG_LOG is enabled
        if (defined('WP_DEBUG_LOG') && WP_DEBUG_LOG) {
            error_log(sprintf(
                '[MainWP WooCommerce] Webhook processing error: %s for website ID: %d',
                $e->getMessage(),
                $website_id
            ));
        }
        
        return new WP_REST_Response([
            'success' => false,
            'message' => 'Error processing webhook: ' . $e->getMessage()
        ], 500);
    }
}

/**
 * Process new order webhook
 * 
 * @param int $website_id Website ID
 * @param array $data Order data
 */
private function process_new_order($website_id, $data) {
    // Validate inputs
    $website_id = absint($website_id);
    if ($website_id <= 0 || empty($data) || !is_array($data)) {
        return;
    }
    
    // Process new order
    // For example, send notification, update dashboard, etc.
}

Implementing Background Processing

For operations that may take a long time, implement background processing:

namespace MyCompany\WooCommerce\Background;

use MainWP\Dashboard\MainWP_DB;
use MainWP\Dashboard\MainWP_Connect;
use WP_Error;
use Exception;

/**
 * Schedule background sync
 */
public function schedule_background_sync() {
    if (!wp_next_scheduled('mainwp_woocommerce_background_sync')) {
        wp_schedule_event(time(), 'hourly', 'mainwp_woocommerce_background_sync');
    }
    
    // Hook into the scheduled event
    add_action('mainwp_woocommerce_background_sync', [$this, 'do_background_sync']);
}

/**
 * Perform background sync
 */
public function do_background_sync() {
    // Get all websites with WooCommerce
    $websites = MainWP_DB::instance()->get_websites_by_plugin_name('woocommerce/woocommerce.php');
    
    foreach ($websites as $website) {
        // Skip sites without API credentials
        $api_client = $this->get_api_client($website->id);
        if (!$api_client) {
            continue;
        }
        
        // Sync products
        $this->sync_products($website->id, $api_client);
        
        // Sync orders
        $this->sync_orders($website->id, $api_client);
        
        // Sync other data as needed
    }
}

/**
 * Sync products for a site
 * 
 * @param int $website_id Website ID
 * @param WooCommerceAPIClient $api_client API client
 */
private function sync_products($website_id, $api_client) {
    // Get products from the site
    $products = $api_client->get_products(['per_page' => 100]);
    
    if (is_wp_error($products)) {
        // Log error
        return;
    }
    
    // Process products
    // For example, store in database, update inventory, etc.
}

Synchronizing Inventory Across Stores

Implement inventory synchronization across multiple stores:

namespace MyCompany\WooCommerce\Sync;

use WP_Error;

/**
 * Synchronize inventory across stores
 * 
 * @param array $website_ids Array of website IDs to sync
 * @param array $product_data Array of product IDs and stock quantities
 * @return array Results
 */
public function sync_inventory($website_ids, $product_data) {
    $results = [];
    
    foreach ($website_ids as $website_id) {
        $api_client = $this->get_api_client($website_id);
        if (!$api_client) {
            $results[$website_id] = [
                'success' => false,
                'message' => 'API credentials not configured'
            ];
            continue;
        }
        
        $product_manager = new ProductManager($api_client);
        $site_results = [];
        
        foreach ($product_data as $product_id => $stock_quantity) {
            $result = $product_manager->update_stock($product_id, $stock_quantity);
            
            $site_results[$product_id] = [
                'success' => !is_wp_error($result),
                'message' => is_wp_error($result) ? $result->get_error_message() : 'Success'
            ];
        }
        
        $results[$website_id] = $site_results;
    }
    
    return $results;
}

Common Challenges and Solutions

API Authentication Issues

If you encounter API authentication issues:

  1. Check API Keys: Ensure the Consumer Key and Consumer Secret are correct.
  2. Verify Permissions: Make sure the API keys have the necessary permissions.
  3. Check SSL: WooCommerce API requires SSL for secure connections.
namespace MyCompany\WooCommerce\Diagnostics;

use MainWP\Dashboard\MainWP_DB;
use WP_Error;

/**
 * Troubleshoot API connection
 * 
 * @param int $website_id Website ID
 * @return array Troubleshooting results
 */
public function troubleshoot_api_connection($website_id) {
    $results = [];
    
    // Check if website exists
    $website = MainWP_DB::instance()->get_website_by_id($website_id);
    if (!$website) {
        $results['website'] = 'Website not found';
        return $results;
    }
    
    // Check if WooCommerce is active
    $is_woocommerce_active = MainWP_DB::instance()->is_plugin_active_on_site($website_id, 'woocommerce/woocommerce.php');
    $results['woocommerce'] = $is_woocommerce_active ? 'Active' : 'Not active';
    
    // Check API credentials
    $settings = get_option('mainwp_woocommerce_settings', []);
    $site_settings = isset($settings[$website_id]) ? $settings[$website_id] : [];
    
    $results['api_credentials'] = (!empty($site_settings['consumer_key']) && !empty($site_settings['consumer_secret'])) ? 'Configured' : 'Not configured';
    
    // Test API connection
    if ($results['api_credentials'] === 'Configured') {
        $api_client = $this->get_api_client($website_id);
        $test_result = $api_client->get_store_info();
        
        $results['api_connection'] = !is_wp_error($test_result) ? 'Success' : 'Failed: ' . $test_result->get_error_message();
    }
    
    return $results;
}

Handling Large Product Catalogs

For stores with large product catalogs:

  1. Implement Pagination: Use pagination to retrieve products in batches.
  2. Optimize Caching: Cache product data to reduce API calls.
  3. Use Background Processing: Process large catalogs in the background.
namespace MyCompany\WooCommerce\Products;

use WP_Error;

/**
 * Get all products with pagination
 * 
 * @param int $website_id Website ID
 * @return array|WP_Error Products or error
 */
public function get_all_products($website_id) {
    $api_client = $this->get_api_client($website_id);
    if (!$api_client) {
        return new WP_Error('api_error', 'API credentials not configured');
    }
    
    $all_products = [];
    $page = 1;
    $per_page = 100;
    
    while (true) {
        $products = $api_client->get_products([
            'page' => $page,
            'per_page' => $per_page
        ]);
        
        if (is_wp_error($products)) {
            return $products;
        }
        
        if (empty($products)) {
            break;
        }
        
        $all_products = array_merge($all_products, $products);
        $page++;
    }
    
    return $all_products;
}

Managing Different WooCommerce Versions

To handle different WooCommerce versions across your network:

  1. Version Detection: Detect WooCommerce version on each site.
  2. Conditional Logic: Implement conditional logic based on version.
  3. Fallback Mechanisms: Provide fallback mechanisms for older versions.
namespace MyCompany\WooCommerce\Compatibility;

use MainWP\Dashboard\MainWP_DB;
use WP_Error;

/**
 * Get WooCommerce version for a site
 * 
 * @param int $website_id Website ID
 * @return string|WP_Error WooCommerce version or error
 */
public function get_woocommerce_version($website_id) {
    $website = MainWP_DB::instance()->get_website_by_id($website_id);
    if (!$website) {
        return new WP_Error('website_error', 'Website not found');
    }
    
    // Get plugin data from the site
    $plugins = json_decode($website->plugins, true);
    if (!$plugins) {
        return new WP_Error('plugins_error', 'Unable to get plugins data');
    }
    
    // Find WooCommerce plugin
    foreach ($plugins as $plugin) {
        if ($plugin['slug'] === 'woocommerce/woocommerce.php') {
            return $plugin['version'];
        }
    }
    
    return new WP_Error('woocommerce_error', 'WooCommerce not found');
}

/**
 * Check if WooCommerce version is compatible
 * 
 * @param string $version WooCommerce version
 * @param string $min_version Minimum required version
 * @return bool Whether the version is compatible
 */
public function is_woocommerce_compatible($version, $min_version = '3.0.0') {
    return version_compare($version, $min_version, '>=');
}

Next Steps and Resources

After implementing your WooCommerce integration, you might want to explore:

  • Advanced Reporting: Implement more advanced reporting features.
  • Custom Dashboards: Create custom dashboards for specific WooCommerce data.
  • Bulk Operations: Implement more bulk operations for managing products and orders.
  • Automated Tasks: Set up automated tasks for common WooCommerce operations.

Resources