• Skip to secondary menu
  • Skip to main content
  • Skip to primary sidebar
  • Home
  • Projects
  • Products
  • Themes
  • Tools
  • Request for Quote

Vengala Vinay

Having 12+ Years of Experience in Software Development

  • Home
  • WordPress
  • PHP
    • Codeigniter
  • Django
  • Magento
  • Selenium
  • Server
Home » Building secure B2B pricing grids with custom Cron API (wp_schedule_event) endpoints and role overrides

Building secure B2B pricing grids with custom Cron API (wp_schedule_event) endpoints and role overrides

Securing B2B Pricing Grids: Custom Cron Endpoints and Role Overrides

Developing robust B2B pricing solutions within WordPress often necessitates dynamic pricing structures that are not directly exposed to the public. This requires a secure mechanism for updating prices, potentially triggered by external events or scheduled intervals, while ensuring only authorized personnel or systems can initiate these changes. This post details a production-ready approach using custom WordPress cron events (`wp_schedule_event`) coupled with API endpoints and granular role-based access control.

Designing the API Endpoint for Price Updates

We’ll create a custom REST API endpoint that will be responsible for triggering the price update process. This endpoint will be protected, requiring specific authentication and authorization. For simplicity in this example, we’ll use a nonce and a custom capability check, but in a real-world scenario, consider OAuth2 or JWT for more sophisticated authentication.

First, let’s define the endpoint registration within your plugin’s main file or an included setup file. We’ll hook into the rest_api_init action.

Registering the REST API Endpoint

add_action( 'rest_api_init', function () {
    register_rest_route( 'my-pricing/v1', '/update-prices', array(
        'methods'  => 'POST',
        'callback' => 'my_pricing_update_prices_callback',
        'permission_callback' => function ( WP_REST_Request $request ) {
            // 1. Verify nonce for basic security
            if ( ! isset( $request['_wpnonce'] ) || ! wp_verify_nonce( $request['_wpnonce'], 'wp_rest' ) ) {
                return new WP_Error( 'rest_nonce_invalid', 'Nonce is invalid.', array( 'status' => 401 ) );
            }

            // 2. Check for a custom capability
            // We'll define 'manage_b2b_pricing' later
            if ( ! current_user_can( 'manage_b2b_pricing' ) ) {
                return new WP_Error( 'rest_forbidden', 'You do not have permission to update prices.', array( 'status' => 403 ) );
            }

            return true; // Permission granted
        },
        'args' => array(
            '_wpnonce' => array(
                'required' => true,
                'type'     => 'string',
                'description' => 'WordPress nonce for security.',
            ),
            // Add any other parameters needed for price updates, e.g., product IDs, new prices
        ),
    ) );
} );

The Callback Function for Price Updates

The callback function will be responsible for initiating the price update process. Instead of performing the update directly, it will schedule a WordPress cron event. This decouples the API request from the potentially long-running update task, preventing timeouts and allowing for more robust error handling and retries.

function my_pricing_update_prices_callback( WP_REST_Request $request ) {
    // Optional: Extract parameters from the request if needed for the cron job
    // $params = $request->get_params();

    // Schedule the cron event to run as soon as possible
    // 'my_pricing_run_updates' is the hook name
    // time() + (60 * 5) schedules it for 5 minutes from now, adjust as needed
    // 'daily' is the interval, can be 'hourly', 'twicedaily', or a custom interval
    // The third parameter is the hook name, which must be unique.
    $timestamp = time() + ( 60 * 5 ); // Schedule for 5 minutes from now
    wp_schedule_single_event( $timestamp, 'my_pricing_run_updates' );

    return new WP_REST_Response( array(
        'message' => 'Price update scheduled. Check logs for progress.',
        'scheduled_at' => date( 'Y-m-d H:i:s', $timestamp ),
    ), 202 ); // 202 Accepted
}

Implementing the Cron Event Handler

Now, we need to hook into the scheduled event and perform the actual price updates. This is where your B2B pricing logic will reside. It’s crucial to make this process idempotent and handle potential errors gracefully.

Hooking into the Scheduled Event

add_action( 'my_pricing_run_updates', 'my_pricing_perform_price_updates' );

function my_pricing_perform_price_updates() {
    // Ensure this function is only executed by the cron job, not directly.
    // A simple check can be to see if the current request is a WP-Cron request.
    if ( ! ( defined( 'DOING_CRON' ) && DOING_CRON ) ) {
        // Log this as an attempted direct execution if necessary
        error_log( 'Attempted direct execution of my_pricing_perform_price_updates.' );
        return;
    }

    // --- Your B2B Pricing Update Logic Here ---
    // This could involve:
    // 1. Fetching new pricing data from an external API.
    // 2. Iterating through products and updating their prices in the database (e.g., WooCommerce products).
    // 3. Applying complex B2B pricing rules (e.g., tiered pricing, customer-specific discounts).
    // 4. Logging the process, successes, and failures.

    // Example: Simulate an update process
    error_log( 'Starting B2B price update process...' );

    // Simulate fetching data
    $pricing_data = array(
        'SKU123' => array( 'price' => 99.99, 'tier' => 'gold' ),
        'SKU456' => array( 'price' => 149.50, 'tier' => 'platinum' ),
    );

    foreach ( $pricing_data as $sku => $data ) {
        // Find product by SKU
        $product_id = wc_get_product_id_by_sku( $sku );

        if ( $product_id ) {
            $product = wc_get_product( $product_id );
            if ( $product ) {
                // For simplicity, updating regular price. Real-world might involve custom meta for B2B.
                $product->set_regular_price( $data['price'] );
                $product->save();
                error_log( "Updated price for SKU {$sku} (Product ID: {$product_id}) to {$data['price']}." );
            } else {
                error_log( "Could not retrieve product object for SKU {$sku} (Product ID: {$product_id})." );
            }
        } else {
            error_log( "Product not found for SKU {$sku}." );
        }
    }

    error_log( 'B2B price update process finished.' );

    // --- End of Your Logic ---

    // Optional: Clear the scheduled event if it's a one-off task
    // wp_clear_scheduled_hook( 'my_pricing_run_updates' );
}

Implementing Role-Based Access Control

To restrict access to the price update API endpoint, we need to define a custom capability and assign it to specific user roles. This ensures that only authorized administrators or specific user types can trigger price updates.

Adding a Custom Capability

This should be done when your plugin is activated. We’ll use the register_activation_hook.

register_activation_hook( __FILE__, 'my_pricing_plugin_activate' );

function my_pricing_plugin_activate() {
    // Add the custom capability
    $role = get_role( 'administrator' ); // Target the administrator role
    if ( $role && ! $role->has_cap( 'manage_b2b_pricing' ) ) {
        $role->add_cap( 'manage_b2b_pricing' );
    }

    // Optionally, add it to other roles or create a new role
    // $editor_role = get_role( 'editor' );
    // if ( $editor_role && ! $editor_role->has_cap( 'manage_b2b_pricing' ) ) {
    //     $editor_role->add_cap( 'manage_b2b_pricing' );
    // }

    // Schedule the initial cron job if needed on activation
    if ( ! wp_next_scheduled( 'my_pricing_run_updates' ) ) {
        wp_schedule_event( time(), 'daily', 'my_pricing_run_updates' ); // Example: schedule daily
    }
}

Removing Capability on Deactivation

It’s good practice to clean up capabilities when the plugin is deactivated.

register_deactivation_hook( __FILE__, 'my_pricing_plugin_deactivate' );

function my_pricing_plugin_deactivate() {
    // Remove the custom capability from the administrator role
    $role = get_role( 'administrator' );
    if ( $role && $role->has_cap( 'manage_b2b_pricing' ) ) {
        $role->remove_cap( 'manage_b2b_pricing' );
    }

    // Clear any scheduled events
    wp_clear_scheduled_hook( 'my_pricing_run_updates' );
}

Triggering the API Endpoint (Example)

To trigger the API endpoint securely from an external system or a privileged internal script, you would typically use a tool like curl. You’ll need to obtain a nonce for the current user and include it in the request.

Using curl to Trigger the Update

First, you need to authenticate as a user with the manage_b2b_pricing capability. Then, you can generate a nonce and make the POST request.

To get a nonce for a specific user (e.g., user ID 1), you can use PHP:

// In a WordPress context, e.g., a custom script or admin page
$user_id = 1; // The ID of the user with 'manage_b2b_pricing' capability
$nonce = wp_create_nonce( 'wp_rest' );
$api_url = rest_url( 'my-pricing/v1/update-prices' );

echo "Nonce: " . $nonce . "\n";
echo "API URL: " . $api_url . "\n";

Then, use curl:

# Replace YOUR_WORDPRESS_URL, YOUR_USERNAME, YOUR_PASSWORD with actual values
# This example uses basic auth, which is NOT recommended for production.
# For production, use application passwords or a more secure auth method.

# Get nonce and API URL (you'd typically get these dynamically)
# For demonstration, let's assume you have them:
NONCE="your_generated_nonce_here"
API_URL="https://your-wordpress-site.com/wp-json/my-pricing/v1/update-prices"

curl -X POST \
  -H "Content-Type: application/json" \
  -d "{\"_wpnonce\": \"$NONCE\"}" \
  "$API_URL"

Important Security Note: Using basic authentication with curl as shown above is insecure for production environments. For real-world applications, consider using WordPress Application Passwords, OAuth2, or JWT for API authentication. The nonce check is a good start for internal WP REST API usage but might not be sufficient for external systems.

Advanced Considerations and Best Practices

  • Error Handling and Logging: Implement comprehensive logging within my_pricing_perform_price_updates. Log successes, failures, and any exceptions. Use WordPress’s built-in error logging or a dedicated logging library.
  • Idempotency: Ensure your price update logic can be run multiple times without unintended side effects. This is crucial if the cron job fails and is rescheduled.
  • External Data Sources: If fetching pricing from an external API, implement robust error handling, timeouts, and retry mechanisms for the external API calls. Cache external data where appropriate.
  • Concurrency: For very large sites or frequent updates, consider mechanisms to prevent multiple cron jobs from running concurrently if the previous one hasn’t finished. You can use transient API or file locking.
  • User Feedback: Provide feedback to the user who triggered the update via the REST API. This could involve updating a status in the database that can be queried via another API endpoint, or sending email notifications.
  • Custom Intervals: If you need more granular scheduling than ‘daily’, ‘hourly’, or ‘twicedaily’, you can define custom intervals using add_filter( 'cron_schedules', 'my_pricing_add_custom_cron_interval' );.
  • Security Hardening: Beyond nonces and capabilities, consider IP whitelisting for the API endpoint if it’s only ever called from specific servers.

By combining custom REST API endpoints with scheduled WordPress cron events and robust role-based access control, you can build a secure and scalable system for managing dynamic B2B pricing grids within your WordPress multisite or single-site installation.

Primary Sidebar

A little about the Author

Having 12+ Years of Experience in Software Development, Vinay is a principal software architect, senior systems engineer, and elite technical consultant. He specializes in bespoke PHP/WordPress development, high-performance Magento 2 & Shopify architectures, custom plugin/theme development from scratch, and legacy code modernization (including VB6, VB.NET, PyQt, and Crystal Reports). Known for solving complex database bottlenecks, speed optimization (Core Web Vitals), and advanced security code auditing, Vinay engineers production-ready systems designed to scale under heavy concurrent load conditions.



Chat on WhatsApp

Recent Posts

  • WordPress Development Recipe: High-efficiency server-side rendering for Gutenberg blocks using Generator functions
  • WordPress Development Recipe: Leveraging Strongly typed objects to build type-safe, auto-wired hooks
  • Debugging and Resolving complex transient validation timeouts issues during heavy concurrent database traffic
  • How to analyze and reduce CPU consumption of custom Domain-driven architecture (DDD) blocks event mediators
  • WordPress Development Recipe: Staggered database writes for high-volume custom form fields using Transients API

Categories

  • apache (1)
  • Business & Monetization (390)
  • Centos (4)
  • Comparisons & Decision Making (55)
  • Debian (2)
  • Debugging & Troubleshooting (658)
  • Desktop Applications (14)
  • DevOps (7)
  • DevOps & Cloud Scaling (962)
  • Django (1)
  • Laravel (4)
  • Migration & Architecture (192)
  • Mobile Applications (24)
  • MySQL (1)
  • Performance & Optimization (872)
  • PHP (5)
  • PHP Development (42)
  • Plugins & Themes (244)
  • Programming Languages (9)
  • Python (20)
  • Ruby on Rails (1)
  • Security & Compliance (639)
  • SEO & Growth (492)
  • Server (23)
  • Ubuntu (9)
  • VB6 & VB.NET (8)
  • Web Applications & Frontend (19)
  • Web Assembly (Wasm) (2)
  • WordPress (22)
  • WordPress Plugin Development (100)
  • WordPress Plugin Development (104)
  • WordPress Plugin Development (330)
  • WordPress Theme Development (357)

Recent Posts

  • WordPress Development Recipe: High-efficiency server-side rendering for Gutenberg blocks using Generator functions
  • WordPress Development Recipe: Leveraging Strongly typed objects to build type-safe, auto-wired hooks
  • Debugging and Resolving complex transient validation timeouts issues during heavy concurrent database traffic

Top Categories

  • DevOps & Cloud Scaling (962)
  • Performance & Optimization (872)
  • Debugging & Troubleshooting (658)
  • Security & Compliance (639)
  • SEO & Growth (492)
  • Business & Monetization (390)

Our Products

  • ERP & LMS Systems (4)
  • Directories & Marketplaces (4)
  • Healthcare Portals (3)
  • Point of Sale (POS) (2)
  • E-Commerce Engines (2)

Our Services

  • E-Commerce Development (10)
  • WordPress Development (8)
  • Python & Desktop GUI (7)
  • General Consulting (7)
  • Legacy Modernization (5)
  • Mobile App Development (4)

Copyright © 2026 · Vinay Vengala