Anular métodos de pago para productos específicos o categorías en WooCommerce

He estado trabajando en una nueva funcionalidad para tiendas online con WooCommerce, me he encontrado con la necesidad de excluir ciertos métodos de pago para unos determinados productos o unas categorías específicas.

Este tutorial puede ser el inicio de un plugin con muchas posibilidades, extensible y donde podremos incorporar múltimples funcionalidades.

En este caso queremos que ciertos productos no se puedan pagar por transferencia bancaria o con PayPal. Es un caso un tanto especial que te puedes encontrar si gestionas tiendas online de clientes.

Para lo cual voy a plantear un sistema donde añadir y eliminar fácilmente productos o categorías desde una página de opciones de WordPress donde añadiremos algunos campos personalizados. El objetivo final es obtener dos Arrays, uno con los Ids de los productos y otro con los slugs de las categorías.

Investigación previa

Primero he creado un snippet de código para consultar todos lo métodos de pago activados en WooCommerce para el proyecto que necesito. Quiero que me muestre en pantalla esta información. ¡Importante! este proceso lo puedes utilizar para extraer otros contenidos de la base de datos de WooCommerce, solo tendrás que adaptarlo según la información que necesites.

Te explico en que va a consistir el siguiente snippet: Mediante un condicional le vamos a indicar que muestre a los administradores del sitio con current_user_can('manage_options') los métodos de pago disponibles y activos actualmente, para lo que utilizaré la función get_available_payment_gateways().

¿dónde quiero que muestre el resultado? después del footer en la página del carrito o en la pagina finalizar compra o checkout utilizando is_cart() y is_checkout().

Pon el siguiente código en el archivo functions de tu tema en funcionamiento, o en un plugin personalizado. Es un código de usar, detectar los métodos y luego borrarlo.

add_action('wp_footer', 'list_available_payment_gateways', 100);

function list_available_payment_gateways() {
    // Solo se ejecuta si WooCommerce está activo, en páginas específicas y el usuario es administrador
    if (
        current_user_can('manage_options') && // Verifica si el usuario es administrador
        function_exists('is_cart') && function_exists('is_checkout') && 
        (is_cart() || is_checkout())
    ) {
        // Asegurarse de que el objeto de pasarelas de pago esté disponible
        if (class_exists('WC_Payment_Gateways') && WC()->payment_gateways) {
            $available_gateways = WC()->payment_gateways->get_available_payment_gateways();
            echo '<pre>';
            print_r(array_keys($available_gateways)); // Muestra las claves de los métodos de pago
            echo '</pre>';
        } else {
            echo '<pre>No se encontraron métodos de pago disponibles o WooCommerce no está cargado correctamente.</pre>';
        }
    }
}

¡Enhorabuena! si tienes un rol de administrador, podrás ir a la página de carrito o finalizar compra (Checkout) y ver algo como esto.

Resultado con todos los métodos de pago activados en WooCommerce

La imagen anterior muestra los métodos activados en otro cliente de WooCommerce que gestiono. Es un ejemplo para que veas como el snippet que hemos creado nos ofrece toda la información que necesitamos y se puede utilizar para cualquier tienda online.

La siguiente imagen muestra los 3 métodos permitidos en la tienda online del cliente con el que estoy trabajando actualmente (redsys, paypal y transferencia bancaria).

Datos extraídos de mi cliente

Una vez extraemos la información necesaria, procedemos a crear un sistema efectivo, ampliable y fácil de modificar o de incorporar nuevos métodos de pago. ¿Cómo hacemos todo esto?

Comenzamos:

Añadiremos una Página de opciones con sus campos personalizados, esto lo podemos realizar con el plugin Advanced Custom Field PRO (ACF) o puedes crearla mediante código. Algo que también te recomiendo para practicar y ver las posibilidades que eso tiene a futuro.

Utilizaremos estos campos personalizados para manejar la información y tener el 100% del control de las funciones que vamos a desarrollar.

Campos necesarios:

Creamos un primer campo Repeater para introducir los métodos de pago (Los que hemos sacado con el snippet anterior, escogeremos los que queremos excluir)

Creamos un segundo campo objeto de publicación (extraeremos en un array solo el ID de cada producto)

Creamos otro campo dinámico de selección de categorías de productos (Obtendremos un array con los Slugs)

¿Cómo programar el campo dinámico de categorías de producto con ACF?

Necesitamos un campo «selección» dinámico en ACF con todas las categorías de producto de WooCommerce.

Crearemos el siguiente Snippet que pondrémos en el plugin personalizado o en el archivo functions del tema en funcionamiento. (Tema Hijo)

Esta función utiliza get_terms() para localizar todas las categorías correspondientes a la taxonomía de WooCommerce «product_cat».

Introduce las categorías en un array que vamos a recorrer una a una y poder listarlas dentro de las opciones del campo utilizando $field[‘choices’].

También comprueba que las categorías no estén vacías y por último a través del filtro ‘acf/load_field/name=nombre_de_campo_select’ inyectamos el listado como opciones para el campo..

function acf_product_categories_field( $field ) {
    // Obtener todas las categorías de productos
    $product_categories = get_terms( array(
        'taxonomy' => 'product_cat',
        'hide_empty' => false,
    ) );

    // Verificar si se obtuvieron las categorías y si no hay errores
    if ( !empty( $product_categories ) && !is_wp_error( $product_categories ) ) {
        // Inicializar el array de opciones
        $field['choices'] = array();

        // Loop a través de las categorías y asignarlas como opciones
        foreach ( $product_categories as $category ) {
            $field['choices'][ $category->term_id ] = $category->name;
        }
    } else {
        // Si no se encontraron categorías, muestra un mensaje de error
        $field['choices'] = array( 'error' => 'No se encontraron categorías de productos.' );
    }

    return $field;
}
add_filter( 'acf/load_field/name=categorias_de_producto', 'acf_product_categories_field' );

¿Cómo ha quedado la página de opciones?

Observa que ahora podemos añadir métodos de pago, excluir productos individuales o excluir categorías enteras.

Snippet para excluir productos

add_filter('woocommerce_available_payment_gateways', 'filter_payment_gateways_for_products');

function filter_payment_gateways_for_products($available_gateways) {
    // Asegurarse de que WooCommerce está disponible
    if (is_admin() || !WC()->cart) {
        return $available_gateways; // No aplicar cambios en el administrador o si el carrito no está disponible
    }

    // Obtén los IDs de productos restringidos desde el campo ACF
    $productos = get_field('productos', 'option'); // Sustituye 'productos' y 'option' si tienen otro nombre o configuración

    if (!$productos) {
        return $available_gateways; // Si no hay productos configurados, no aplicar restricciones
    }

    // Verifica si alguno de los productos está en el carrito
    $product_in_cart = false;
    foreach (WC()->cart->get_cart() as $cart_item) {
        if (in_array($cart_item['product_id'], $productos)) {
            $product_in_cart = true;
            break;
        }
    }

    // Si alguno de los productos está en el carrito, obtén los métodos de pago restringidos desde el repeater de ACF
    if ($product_in_cart) {
        if (have_rows('metodos_de_pago', 'option')) {
            while (have_rows('metodos_de_pago', 'option')) {
                the_row();
                $metodo_de_pago = get_sub_field('metodo_de_pago');
                if ($metodo_de_pago && isset($available_gateways[$metodo_de_pago])) {
                    unset($available_gateways[$metodo_de_pago]); // Elimina el método de pago de la lista
                }
            }
        }
    }

    return $available_gateways;
}

Explicación del código:

  • Usamos get_field('productos', 'option') para recuperar los IDs de los productos configurados en ACF.
  • Comprobamos si algún producto del carrito coincide con los IDs obtenidos.
  • Si hay un producto restringido en el carrito, iteramos sobre el repeater de ACF (metodos_de_pago).
  • Eliminamos los métodos de pago correspondientes de $available_gateways.
  • Si no hay productos ni métodos de pago configurados, no aplicamos restricciones.
  • Asegúrate de que los nombres de los campos de ACF (productos y metodos_de_pago) sean correctos.
  • Los valores del repeater deben coincidir exactamente con los slugs de los métodos de pago disponibles en WooCommerce. (Información que hemos extraído anteriormente)
add_filter('woocommerce_available_payment_gateways', 'filter_payment_gateways_for_categories');

function filter_payment_gateways_for_categories($available_gateways) {
    // Asegurarse de que WooCommerce está disponible
    if (is_admin() || !WC()->cart) {
        return $available_gateways; // No aplicar cambios en el administrador o si el carrito no está disponible
    }

    // Obtén las categorías restringidas desde ACF
    $restricted_categories = get_field('categorias_de_producto', 'option'); // Sustituye 'categorias_de_producto' y 'option' si tienen otro nombre o configuración

    if (!$restricted_categories) {
        return $available_gateways; // Si no hay categorías configuradas, no aplicar restricciones
    }

    // Verifica si hay productos en el carrito que pertenezcan a alguna de las categorías restringidas
    $category_in_cart = false;

    foreach (WC()->cart->get_cart() as $cart_item) {
        $product_id = $cart_item['product_id'];

        // Verifica si el producto pertenece a alguna de las categorías restringidas
        if (has_term($restricted_categories, 'product_cat', $product_id)) {
            $category_in_cart = true;
            break;
        }
    }

    // Si hay un producto de las categorías restringidas, obtén los métodos de pago desde el repeater de ACF
    if ($category_in_cart) {
        if (have_rows('metodos_de_pago', 'option')) {
            while (have_rows('metodos_de_pago', 'option')) {
                the_row();
                $metodo_de_pago = get_sub_field('metodo_de_pago');
                if ($metodo_de_pago && isset($available_gateways[$metodo_de_pago])) {
                    unset($available_gateways[$metodo_de_pago]); // Elimina el método de pago de la lista
                }
            }
        }
    }

    return $available_gateways;
}

Explicación del código:

  • Usamos get_field('categorias_de_producto', 'option') para recuperar las categorías (slugs) configuradas en el campo ACF.
  • Iteramos sobre los productos en el carrito utilizando WC()->cart->get_cart().
  • Para cada producto, verificamos si pertenece a una de las categorías restringidas utilizando has_term().
  • Si encontramos un producto en una categoría restringida, iteramos sobre el repeater de ACF (metodos_de_pago).
  • Eliminamos los métodos de pago configurados en el repeater (metodo_de_pago) de la lista $available_gateways.
  • Si no se configuran categorías o métodos de pago en ACF, no se aplicarán restricciones.
  • Asegúrate de que categorias_de_producto y metodos_de_pago coincidan con los nombres exactos configurados en tu instalación de ACF.
  • El código evita problemas en el backend gracias a (is_admin) o si WooCommerce no está inicializado correctamente.

¿Necesitas un desarrollo web en WordPress a medida?

Me especializo en desarrollar sitios webs avanzados, programando soluciones personalizadas para proyectos web.

Productos y categorías sin restricciones

Productos y categorías con restricciones

¿Cómo avanzar con este proyecto?

  • Programa un sistema mejorado donde se puedan hacer distintas reglas, por ejemplo con un REPEATER con todas las funciones. Es decir que se puedan controlar distintos bloques de productos o categorías en base a los métodos de pago excluidos.
  • Da estilo corporativo a la pagina de opciones.
  • Crea esa página de opciones y sus campos personalizados con funciones nativas de WordPress.

Si crees que le falta algo o quieres sugerir ideas para añadir al plugin, por favor, deja un comentario.

Si has llegado hasta el final ¡Enhorabuena! espero que hayas aprendido nuevas funciones de WordPress y WooCommerce y te sirva para desarrollar un plugin personalizado para tus clientes.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *