Home / Admin / Enable Payment on Account
Duplicate Snippet

Embed Snippet on Your Site

Enable Payment on Account

* - Adds a "Payment Methods" tab under WooCommerce > Settings.
* - Shows a matrix of User Roles (down the left) vs Active Payment Methods (across the top),
* PLUS a "Guest (not logged in)" row.
* - Lets you tick which roles (and/or guests) can use which methods.
* - Applies restrictions on checkout and order-pay.

Code Preview
php
<?php
/**
 * WooCommerce: Role-based + Guest payment methods UI + logic
 *
 * - Adds a "Payment Methods" tab under WooCommerce > Settings.
 * - Shows a matrix of User Roles (down the left) vs Active Payment Methods (across the top),
 *   PLUS a "Guest (not logged in)" row.
 * - Lets you tick which roles (and/or guests) can use which methods.
 * - Applies restrictions on checkout and order-pay.
 *
 * Behaviour rules:
 * 1) If a gateway has NO boxes ticked at all => it is available to everyone (roles + guests).
 * 2) If a gateway has at least one box ticked => it is RESTRICTED to ONLY those ticked (including guest if ticked).
 */
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}
define( 'WC_RPG_GUEST_KEY', '__guest__' );
/**
 * 1) Add new settings tab.
 */
add_filter( 'woocommerce_settings_tabs_array', function( $tabs ) {
	$tabs['wc_role_payment_gateways'] = __( 'Payment Methods', 'your-textdomain' );
	return $tabs;
}, 50 );
/**
 * Helper: get active enabled gateways.
 */
function wc_rpg_get_active_gateways() {
	if ( ! function_exists( 'WC' ) ) {
		return array();
	}
	$gateways_obj = WC_Payment_Gateways::instance();
	$gateways     = $gateways_obj->payment_gateways();
	$active = array();
	foreach ( $gateways as $gateway_id => $gateway ) {
		if ( isset( $gateway->enabled ) && 'yes' === $gateway->enabled ) {
			$active[ $gateway_id ] = $gateway;
		}
	}
	return $active;
}
/**
 * 2) Render the settings tab content.
 */
add_action( 'woocommerce_settings_tabs_wc_role_payment_gateways', function() {
	if ( ! current_user_can( 'manage_woocommerce' ) ) {
		wp_die( __( 'You do not have permission to access this page.', 'your-textdomain' ) );
	}
	$active_gateways = wc_rpg_get_active_gateways();
	// Get all roles.
	$wp_roles = wp_roles();
	$roles    = $wp_roles ? $wp_roles->roles : array();
	// Existing matrix from the DB.
	$matrix = get_option( 'wc_role_payment_gateways_matrix', array() );
	if ( ! is_array( $matrix ) ) {
		$matrix = array();
	}
	echo '<h2>' . esc_html__( 'Payment Methods – Access Control', 'your-textdomain' ) . '</h2>';
	echo '<p>' . esc_html__(
		'Tick who can use each payment method. If a payment method has no boxes ticked, it stays available to everyone (including guests).',
		'your-textdomain'
	) . '</p>';
	// Security field.
	wp_nonce_field( 'wc_role_payment_gateways_save', 'wc_role_payment_gateways_nonce' );
	if ( empty( $active_gateways ) ) {
		echo '<p><strong>' . esc_html__( 'No active payment methods found.', 'your-textdomain' ) . '</strong></p>';
		return;
	}
	echo '<table class="widefat fixed striped" style="margin-top:20px;">';
	// Header row.
	echo '<thead><tr>';
	echo '<th style="min-width:220px;">' . esc_html__( 'User Role / Guest', 'your-textdomain' ) . '</th>';
	foreach ( $active_gateways as $gateway_id => $gateway ) {
		$label = $gateway->get_title() ? $gateway->get_title() : $gateway_id;
		printf(
			'<th style="text-align:center; white-space:nowrap; padding:6px 12px;">%s<br><code style="font-size:11px;">%s</code></th>',
			esc_html( $label ),
			esc_html( $gateway_id )
		);
	}
	echo '</tr></thead><tbody>';
	// --- Guest row first ---
	echo '<tr>';
	printf(
		'<td style="font-weight:600; vertical-align:top;">%s<br><code style="font-size:11px;">%s</code></td>',
		esc_html__( 'Guest (not logged in)', 'your-textdomain' ),
		esc_html( WC_RPG_GUEST_KEY )
	);
	foreach ( $active_gateways as $gateway_id => $gateway ) {
		$is_checked = (
			isset( $matrix[ $gateway_id ], $matrix[ $gateway_id ][ WC_RPG_GUEST_KEY ] )
			&& $matrix[ $gateway_id ][ WC_RPG_GUEST_KEY ]
		) ? 'checked="checked"' : '';
		printf(
			'<td style="text-align:center; vertical-align:middle;">
				<input type="checkbox"
					name="wc_role_payment_gateways_matrix[%1$s][%2$s]"
					value="1" %3$s />
			</td>',
			esc_attr( $gateway_id ),
			esc_attr( WC_RPG_GUEST_KEY ),
			$is_checked
		);
	}
	echo '</tr>';
	// --- Role rows ---
	foreach ( $roles as $role_key => $role_data ) {
		echo '<tr>';
		printf(
			'<td style="font-weight:600; vertical-align:top;">%s<br><code style="font-size:11px;">%s</code></td>',
			esc_html( $role_data['name'] ),
			esc_html( $role_key )
		);
		foreach ( $active_gateways as $gateway_id => $gateway ) {
			$is_checked = (
				isset( $matrix[ $gateway_id ], $matrix[ $gateway_id ][ $role_key ] )
				&& $matrix[ $gateway_id ][ $role_key ]
			) ? 'checked="checked"' : '';
			printf(
				'<td style="text-align:center; vertical-align:middle;">
					<input type="checkbox"
						name="wc_role_payment_gateways_matrix[%1$s][%2$s]"
						value="1" %3$s />
				</td>',
				esc_attr( $gateway_id ),
				esc_attr( $role_key ),
				$is_checked
			);
		}
		echo '</tr>';
	}
	echo '</tbody></table>';
	echo '<p class="description" style="margin-top:10px;">' .
	     esc_html__( 'Note: Restrictions apply on frontend checkout and order-pay. In wp-admin, gateways remain available for order management.', 'your-textdomain' ) .
	     '</p>';
} );
/**
 * 3) Save the settings when "Save changes" is clicked.
 */
add_action( 'woocommerce_update_options_wc_role_payment_gateways', function() {
	if ( ! current_user_can( 'manage_woocommerce' ) ) {
		return;
	}
	if (
		empty( $_POST['wc_role_payment_gateways_nonce'] )
		|| ! wp_verify_nonce( $_POST['wc_role_payment_gateways_nonce'], 'wc_role_payment_gateways_save' )
	) {
		return;
	}
	$raw = isset( $_POST['wc_role_payment_gateways_matrix'] ) ? (array) $_POST['wc_role_payment_gateways_matrix'] : array();
	$sanitized = array();
	foreach ( $raw as $gateway_id => $roles ) {
		$gateway_id = sanitize_text_field( $gateway_id );
		if ( ! is_array( $roles ) ) {
			continue;
		}
		foreach ( $roles as $role_key => $value ) {
			$role_key = sanitize_text_field( $role_key );
			// Any truthy value => 1.
			if ( $value ) {
				if ( ! isset( $sanitized[ $gateway_id ] ) ) {
					$sanitized[ $gateway_id ] = array();
				}
				$sanitized[ $gateway_id ][ $role_key ] = 1;
			}
		}
	}
	update_option( 'wc_role_payment_gateways_matrix', $sanitized );
} );
/**
 * Helper: Get roles to use for deciding payment access.
 *
 * - Logged-in user roles if logged in.
 * - order-pay fallback: order owner's roles (even if visitor isn't logged in).
 * - If still none => treat as Guest.
 */
function wc_rpg_get_relevant_role_keys() {
	$roles = array();
	// Logged-in user first.
	if ( is_user_logged_in() ) {
		$user  = wp_get_current_user();
		$roles = (array) $user->roles;
	}
	// order-pay fallback for non-logged-in visitors paying an order.
	if ( empty( $roles ) && function_exists( 'is_wc_endpoint_url' ) && is_wc_endpoint_url( 'order-pay' ) ) {
		$order_id = absint( get_query_var( 'order-pay' ) );
		if ( $order_id ) {
			$order   = wc_get_order( $order_id );
			$user_id = $order ? (int) $order->get_user_id() : 0;
			if ( $user_id ) {
				$owner = get_user_by( 'id', $user_id );
				if ( $owner ) {
					$roles = (array) $owner->roles;
				}
			}
		}
	}
	// If still nothing => Guest.
	if ( empty( $roles ) ) {
		$roles = array( WC_RPG_GUEST_KEY );
	}
	return array_values( array_unique( $roles ) );
}
/**
 * 4) Filter available gateways based on the matrix (roles + guest).
 */
add_filter( 'woocommerce_available_payment_gateways', function( $gateways ) {
	// Don't interfere with wp-admin (creating/editing orders).
	if ( is_admin() ) {
		return $gateways;
	}
	$matrix = get_option( 'wc_role_payment_gateways_matrix', array() );
	// If no settings exist yet, do nothing.
	if ( empty( $matrix ) || ! is_array( $matrix ) ) {
		return $gateways;
	}
	$user_role_keys = wc_rpg_get_relevant_role_keys();
	foreach ( $gateways as $gateway_id => $gateway ) {
		// If gateway isn't in the matrix at all, it's unrestricted.
		if ( ! isset( $matrix[ $gateway_id ] ) || ! is_array( $matrix[ $gateway_id ] ) ) {
			continue;
		}
		// Allowed keys for this gateway (roles + guest).
		$allowed_keys = array_keys( array_filter( $matrix[ $gateway_id ] ) );
		// RULE: If NOTHING ticked for this gateway => available to everyone.
		if ( empty( $allowed_keys ) ) {
			continue;
		}
		// Otherwise restrict.
		if ( empty( array_intersect( $user_role_keys, $allowed_keys ) ) ) {
			unset( $gateways[ $gateway_id ] );
		}
	}
	return $gateways;
}, 20 );

Comments

Add a Comment