• 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 WordPress Settings API endpoints and role overrides

Building secure B2B pricing grids with custom WordPress Settings API endpoints and role overrides

Leveraging WordPress Settings API for Secure B2B Pricing Grids

Enterprise-grade B2B pricing often necessitates dynamic, role-specific price adjustments that go beyond standard WooCommerce product variations. Implementing such a system within WordPress requires a robust, secure, and extensible architecture. This post details how to build a custom pricing grid solution using the WordPress Settings API, coupled with granular role-based access control, to manage and display bespoke pricing for different client tiers.

Designing the Settings Structure with Settings API

The WordPress Settings API provides a structured way to register settings, sections, and fields, ensuring data is properly saved, sanitized, and displayed. For a B2B pricing grid, we’ll define a custom setting group to hold our pricing data. This data will likely be a complex array, mapping product IDs or SKUs to different pricing tiers, which in turn are associated with specific user roles.

We’ll use a single option to store the entire pricing grid configuration. This simplifies management and reduces database overhead compared to individual options for each product/role combination. The structure will be an associative array where keys represent product identifiers and values are arrays of role-specific prices.

Registering the Custom Setting

The core of this implementation lies in registering a custom option group and its associated fields. We’ll hook into the `admin_init` action to perform these registrations.

add_action( 'admin_init', 'b2b_pricing_register_settings' );

function b2b_pricing_register_settings() {
    // Register a new setting for our pricing grid data.
    // 'b2b_pricing_grid_data' is the option name.
    // 'b2b_pricing_sanitize_grid_data' is the sanitization callback.
    register_setting(
        'b2b_pricing_options_group', // Option group
        'b2b_pricing_grid_data',     // Option name
        'b2b_pricing_sanitize_grid_data' // Sanitization callback
    );

    // Add a new section to the settings page.
    add_settings_section(
        'b2b_pricing_section',                 // Section ID
        __( 'B2B Pricing Grid Configuration', 'b2b-pricing' ), // Section title
        'b2b_pricing_section_callback',        // Callback function to display section description
        'b2b_pricing_settings'                 // Page slug where this section will appear
    );

    // Add a field for the pricing grid.
    // This field will contain a textarea for JSON input or a more complex UI.
    add_settings_field(
        'b2b_pricing_grid_field',              // Field ID
        __( 'Pricing Grid Data (JSON)', 'b2b-pricing' ), // Field title
        'b2b_pricing_grid_field_callback',     // Callback function to render the field
        'b2b_pricing_settings',                // Page slug
        'b2b_pricing_section'                  // Section ID
    );
}

// Callback function for the section description.
function b2b_pricing_section_callback() {
    echo '

' . __( 'Enter your B2B pricing data in JSON format. The structure should map product IDs to role-specific prices.', 'b2b-pricing' ) . '

'; echo '

' . __( 'Example structure: {"123": {"wholesale_customer": 10.50, "distributor": 8.75}, "456": {"wholesale_customer": 25.00}}', 'b2b-pricing' ) . '

'; } // Callback function to render the pricing grid field. function b2b_pricing_grid_field_callback() { $pricing_data = get_option( 'b2b_pricing_grid_data', array() ); $json_data = json_encode( $pricing_data, JSON_PRETTY_PRINT ); ?>

$role_prices ) { if ( ! is_numeric( $product_id ) ) { continue; // Skip if product ID is not numeric } $sanitized_role_prices = array(); if ( is_array( $role_prices ) ) { foreach ( $role_prices as $role_slug => $price ) { // Ensure role slug is a string and price is a valid float. if ( is_string( $role_slug ) && is_numeric( $price ) ) { $sanitized_role_prices[sanitize_key( $role_slug )] = (float) $price; } } } if ( ! empty( $sanitized_role_prices ) ) { $sanitized_data[$product_id] = $sanitized_role_prices; } } return $sanitized_data; }

Creating the Settings Page

To make the settings accessible, we need to register a menu page. This is typically done using the `admin_menu` action.

add_action( 'admin_menu', 'b2b_pricing_add_admin_menu' );

function b2b_pricing_add_admin_menu() {
    add_options_page(
        __( 'B2B Pricing Settings', 'b2b-pricing' ), // Page title
        __( 'B2B Pricing', 'b2b-pricing' ),          // Menu title
        'manage_options',                           // Capability required to access
        'b2b_pricing_settings',                     // Menu slug
        'b2b_pricing_options_page_html'             // Callback function to render the page content
    );
}

function b2b_pricing_options_page_html() {
    // Check user capabilities
    if ( ! current_user_can( 'manage_options' ) ) {
        return;
    }
    ?>
    

Implementing Role-Based Price Overrides

Once the pricing data is stored, we need a mechanism to retrieve and apply these custom prices based on the currently logged-in user's role. This involves hooking into WooCommerce's price display and cart/checkout processes.

Retrieving Custom Prices

A helper function can abstract the logic for fetching the correct price for a given product and user role.

/**
 * Get the custom price for a product based on the current user's role.
 *
 * @param int $product_id The ID of the product.
 * @return float|null The custom price if found, otherwise null.
 */
function b2b_pricing_get_custom_price( $product_id ) {
    if ( ! is_user_logged_in() ) {
        return null;
    }

    $pricing_data = get_option( 'b2b_pricing_grid_data', array() );
    if ( empty( $pricing_data ) || ! isset( $pricing_data[$product_id] ) ) {
        return null;
    }

    $user = wp_get_current_user();
    $user_roles = (array) $user->roles;

    // Prioritize roles if a specific order is needed, or simply iterate.
    // For simplicity, we'll take the first matching role found.
    foreach ( $user_roles as $role ) {
        if ( isset( $pricing_data[$product_id][$role] ) ) {
            return (float) $pricing_data[$product_id][$role];
        }
    }

    return null; // No custom price found for any of the user's roles
}

Applying Prices to WooCommerce Products

We can use WooCommerce hooks to override the default prices. The `woocommerce_product_get_price`, `woocommerce_product_get_regular_price`, and `woocommerce_product_get_sale_price` filters are prime candidates.

// Override the regular price
add_filter( 'woocommerce_product_get_regular_price', 'b2b_pricing_override_product_price', 10, 2 );
// Override the sale price (if applicable)
add_filter( 'woocommerce_product_get_sale_price', 'b2b_pricing_override_product_price', 10, 2 );
// Override the displayed price (for single product pages, archives, etc.)
add_filter( 'woocommerce_product_get_price', 'b2b_pricing_override_product_price', 10, 2 );

function b2b_pricing_override_product_price( $price, $product ) {
    if ( ! $product instanceof WC_Product ) {
        return $price;
    }

    $product_id = $product->get_id();
    $custom_price = b2b_pricing_get_custom_price( $product_id );

    if ( $custom_price !== null ) {
        // Ensure we are returning a string as expected by WooCommerce filters
        return (string) $custom_price;
    }

    return $price; // Return original price if no custom price is found
}

// Also handle variations if applicable
add_filter( 'woocommerce_product_variation_get_regular_price', 'b2b_pricing_override_variation_price', 10, 2 );
add_filter( 'woocommerce_product_variation_get_sale_price', 'b2b_pricing_override_variation_price', 10, 2 );
add_filter( 'woocommerce_product_variation_get_price', 'b2b_pricing_override_variation_price', 10, 2 );

function b2b_pricing_override_variation_price( $price, $variation ) {
    if ( ! $variation instanceof WC_Product_Variation ) {
        return $price;
    }

    $product_id = $variation->get_parent_id(); // Get parent product ID for variation
    $custom_price = b2b_pricing_get_custom_price( $product_id );

    // For variations, we might want to check if the variation itself has a role-specific price,
    // or if the parent product's role-specific price should apply to all variations.
    // This example assumes the parent product's role price applies to all variations.
    // A more complex system might involve mapping variation IDs to pricing data.

    if ( $custom_price !== null ) {
        return (string) $custom_price;
    }

    return $price;
}

Securing Access to Pricing Settings

The `add_options_page` function already includes a `manage_options` capability check, which is typically reserved for Administrators. For more granular control, you could:

  • Create a custom user role (e.g., "Pricing Manager") with specific capabilities.
  • Modify the `add_options_page` capability argument to target this custom role.
  • Implement checks within the `b2b_pricing_get_custom_price` function to ensure only authorized users can *see* B2B pricing, even if they aren't administrators managing the settings. This might involve checking for specific roles or custom meta on the user object.

For instance, to restrict viewing B2B prices to users with the 'wholesale_customer' role:

function b2b_pricing_get_custom_price( $product_id ) {
    // Restrict access to B2B pricing display to logged-in users with specific roles
    if ( ! is_user_logged_in() ) {
        return null;
    }

    $user = wp_get_current_user();
    $allowed_roles_for_viewing = array( 'wholesale_customer', 'distributor', 'administrator' ); // Example roles

    $has_view_access = false;
    foreach ( $user->roles as $role ) {
        if ( in_array( $role, $allowed_roles_for_viewing ) ) {
            $has_view_access = true;
            break;
        }
    }

    if ( ! $has_view_access ) {
        return null; // User cannot see B2B prices
    }

    $pricing_data = get_option( 'b2b_pricing_grid_data', array() );
    if ( empty( $pricing_data ) || ! isset( $pricing_data[$product_id] ) ) {
        return null;
    }

    // Now, find the specific price for the user's role
    $user_roles = (array) $user->roles;
    foreach ( $user_roles as $role ) {
        if ( isset( $pricing_data[$product_id][$role] ) ) {
            return (float) $pricing_data[$product_id][$role];
        }
    }

    return null;
}

Advanced Considerations and Enhancements

This foundational implementation can be extended significantly:

  • UI Improvements: Replace the JSON textarea with a more user-friendly interface using JavaScript (e.g., React, Vue) to dynamically add/edit products and role prices. This would involve custom AJAX endpoints for saving data.
  • Product Identification: Instead of relying solely on numeric product IDs, consider using SKUs or custom product meta fields for more robust identification, especially in complex catalogs.
  • Role Prioritization: If users can have multiple roles, implement a priority system for which role's price takes precedence.
  • Tiered Pricing: Extend the data structure to support quantity-based tiered pricing within each role.
  • Caching: For performance, implement transient caching for pricing data, especially if the pricing grid is large and frequently accessed.
  • Order Processing: Ensure that prices applied during checkout are correctly reflected in order totals and line items. WooCommerce hooks like `woocommerce_checkout_create_order_line_item` might be necessary.
  • API Access: For headless implementations or integrations, expose this pricing logic via a REST API endpoint, ensuring proper authentication and authorization.

By combining the WordPress Settings API with WooCommerce hooks and robust role management, you can construct a powerful and secure system for managing complex B2B pricing structures, tailored to the specific needs of enterprise clients.

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

  • Reducing database query bloat in Sage Roots modern environments layouts using custom lazy loaders
  • Performance Optimization: Tuning PHP-FPM and opcache pools for high-concurrency Firebase Realtime DB handlers
  • Reducing Largest Contentful Paint (LCP) by optimizing custom script enqueuing structures in legacy plugins
  • How to implement native Redis caching layers for high-volume custom taxonomy queries in Carbon Fields custom wrappers
  • Building secure B2B pricing grids with custom REST API Controllers endpoints and role overrides

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 (48)
  • 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 (182)
  • WordPress Plugin Development (197)
  • WordPress Plugin Development (330)
  • WordPress Theme Development (357)

Recent Posts

  • Reducing database query bloat in Sage Roots modern environments layouts using custom lazy loaders
  • Performance Optimization: Tuning PHP-FPM and opcache pools for high-concurrency Firebase Realtime DB handlers
  • Reducing Largest Contentful Paint (LCP) by optimizing custom script enqueuing structures in legacy plugins

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