Hace poco estaba analizando un proyecto en el que se requería que el precio de un producto de WooCommerce cambie dinámicamente pero sin usar variaciones de productos.
Generalidades
La idea es agregar un control adicional de selección de precios el cual cambiará el precio del producto dinámicamente, para lograr esto usaremos directamente código y evitaremos el uso de plugins adicionales.
Para probar este código puedes simplemente copiarlo en el archivo functions.php de tu tema hijo
Código para mostrar la selección de precio
El siguiente código crea un control de selección que se muestra en la página del producto y a través de código javascript permite cambiar dinámicamente el precio base del producto.
<?php //no copiar esta línea
// Creamos el control de selección y el cambio dinámico de precio
add_action('woocommerce_before_add_to_cart_button', 'dcms_build_select_field');
function dcms_build_select_field(){
global $product;
$options = [
"0" => 'Selecciona una opción',
"10" => 'Agrega, +10 al precio',
"20" => 'Agrega, +20 al precio',
"30" => 'Agrega, +30 al precio'
];
woocommerce_form_field('extras_product', array(
'type' => 'select',
'label' => 'Agregar al producto',
'required' => true,
'options' => $options,
),'');
$base_price = (float) wc_get_price_to_display( $product );
$currency = get_woocommerce_currency_symbol();
?>
<script>
jQuery(function($){
const base_price = <?php echo $base_price; ?>;
const currency = "<?php echo $currency; ?>";
$('#extras_product').on( 'change', function(){
new_price = currency + (Number(this.value) + base_price).toFixed(2);
$('p.price').html( new_price );
});
});
</script>
<?php
}
Al final obtendremos algo similar a lo siguiente

Código para guardar el nuevo precio en el carrito
Luego que cambiamos el precio dinámicamente en la página de producto, será necesario guardar este nuevo precio cuando se agregue este producto al carrito.
// Almacenamos el precio extra y el nuevo precio en los datos del ítem
add_filter( 'woocommerce_add_cart_item_data', 'dcms_extra_data_to_cart_item', 20, 2 );
function dcms_extra_data_to_cart_item( $cart_item_data, $product_id ){
if( ! isset($_POST['extras_product']) ) return $cart_item_data;
$extra_price = (float)$_POST['extras_product'];
if ( ! $extra_price ) return $cart_item_data;
$product = wc_get_product($product_id);
$base_price = (float) $product->get_price();
$new_price =$base_price + $extra_price;
$cart_item_data['extras_product'] = array(
'extra_price' => $extra_price,
'new_price' => (float) $new_price,
);
return $cart_item_data;
}
// Realizamos el cálculo del nuevo precio y lo asignamos a los datos de carro
add_action('woocommerce_before_calculate_totals', 'dcms_custom_cart_item_price', 20, 1);
function dcms_custom_cart_item_price( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return;
foreach ( $cart->get_cart() as $cart_item ) {
if ( isset( $cart_item['extras_product']['new_price'] ) )
$cart_item['data']->set_price( $cart_item['extras_product']['new_price'] );
}
}
Aplicando el código anterior, se mostrará el precio modificado en el carrito:

Código para mostrar datos extra en el carrito
En el carrito tenemos guardado datos adicionales del precio extra, sin embargo sería bueno reflejar que cantidad adicional se agregó, para lograr esto mostraremos ese monto adicional como parte de los datos del ítem de carrito.
// Mostramos los datos extra en los ítems del carrito
add_filter( 'woocommerce_get_item_data', 'display_custom_cart_item_data', 10, 2 );
function display_custom_cart_item_data( $cart_data, $cart_item ) {
if ( isset( $cart_item['extras_product']['new_price'] ) ){
$cart_data[] = [
'name' => 'Extras',
'value' => '+' . $cart_item['extras_product']['extra_price']
];
}
return $cart_data;
}
Ahora se mostrará el adicional como parte de los datos del producto agregado.

Código para mostrar datos extra en la orden
Cuando se realice el pedido necesitaremos saber igualmente qué cantidad extra se agregó al precio, por lo tanto guardaremos ese dato en la metadata del ítem de la orden.
// Para guardar los datos en el ítem de producto y que se muestren en las órdenes del backend
function dcms_save_new_order_item( $item_id, $item, $order_id ) {
wc_add_order_item_meta($item_id, 'Extra', $item->legacy_values['extras_product']['extra_price']);
};
add_action( 'woocommerce_new_order_item', 'dcms_save_new_order_item', 10, 3 );
Ahora se mostrará el dato adicional como parte del ítem de una orden.

Conclusión
Tal como hemos visto, puedes hacer cambios a los precios de tus productos directamente a través de código usando los Hooks de WooCommerce. Esto es especialmente útil cuando buscas algo personalizado y quieres evitar el uso de plugins adicionales.
¿Aún con dudas?, en el siguiente video se detallan los puntos anteriores.
Te debo una¡
Que bueno que te sirvió. Saludos.
Saludos, excelente tutorial. Gracias!
Una pregunta:
Como puedo guardar esos campos calculados en mi base de datos?
Gracias
Hola, supongo que te refieres a la variable $options , ya que el resto si se guarda en la BD, la variable $options tendría que tener una pantalla, a través de un plugin personalizado, para llenar estos valores y guardarlos en la BD, y luego recuperarlos y no colocar el texto directamente tal como esta en el ejemplo.
Hola, gracias por su aporte. Si yo creo un plug-in que tenga un formulario que haga de cotizador, el precio resultante se deriva de la número de pasajeros y días de estadía y seleccionar uno de 3 planes de viajes. Al final se utilizará el checkout de woocommerce. Ahora, mis dos preguntas son: debe existir esos planes como producto en woocommerce y qué Hook debo utilizar para cambiar los precios según lo seleccionado por el cliente??
Muchas gracias de antemano!
Hola, el cotizador que mencionas sería parte del cálculo de precios, por lo que estaría integrado con la lógica de este artículo, no necesitas crear más productos, con uno sólo es suficiente sólo que tienes que variar el precio de acuerdo al cotizador.
En resumen sería integrar tu formulario para que cambie el precio tal como lo hago en este artículo.
Saludos.
Sería posible que en vez de ser un SELECT con diferentes opciones, fuera un simple botón que al pulsarlo le reste un tanto por ciento (ejemplo: hacerle una rebaja del 10%)?
Cómo sería?
Gracias
Hola, las rebajas deberían ser automáticas, o con cupones de descuento. Sin embargo si quieres poner un control de botón no veo que tengas esa opción con la función woocommerce_form_field(), por lo que posiblemente tengas que construirlo directamente con HTML. El resto de la lógica sería similar. Saludos.
Saludos John, de antemano gracias por tus aportes. Excelentes!
Unas dudas:
* Como hago para que ese código actue en las paginas que muestran los listados de los productos, es decir, en la pagina de inventarios?
* Es posible, que despues de que el programa actúe, me modifique el valor del campo de precio en el producto de woocommerce?, es decir, correr el programa y colocarl los precios nuevos a todos los productos?.
* Lo otro que me pasa es que no siempre funciona el programa, si consultas a la primera, no sale el precio calculado, a la segunda vez si, y asi sucesivamente
GRACIAS Y DISCULPA LA MOLESTIA AMIGO!!.
Hola, no me queda claro a qué te refieres con página de inventario y lo de correr el programa, asumo que estas usando una funcionalidad adicional con algún plugin, en este caso la integración sería posiblemente también en el plugin. Saludos.
Hola Jhon, excelente aporte…
Tengo una duda, como le hago para que en
woocommerce_add_cart_item_data
me guarde el precio de la variación seleccionada al momento esto en un producto variable ya que con este código$product = wc_get_product($product_id); $base_price = (float) $product->get_price();
me guarda el precio de la variación seleccionada por defecto, por ejemplo en un celular el las variaciones son de 128Gb, 256Gb y 512Gb cada una con diferente precio y al añadir al carrito siempre me guarda el precio de la variación de 128Gb, que es la default y no me guarda si elijo las otras dos, no se si me explique bien, podrías ayudarmeHola, me gusto bastante el metodo para cambiar el precio al producto. Si quisiera hacer una pregunta, si no es mucha molestia. Como se tendria que hacer para que en vez de mostrar las opciones en el producto se muestre en el carrito?.
Hola, el carrito es una especie de resumen, allí no puedes cambiar el precio, al menos de forma simple. Saludos.
Mi estimado Jhon buen tutorial.
Una observación, creo que desde la versión 3+ de woocommerce se usa otro hook para esto
//======================
La nueva forma seria
//===================
Hola Enrique, gracias por el aporte, no conocía ese Hook. Espero darme un tiempo para probarlo y de ser necesario actualizaré el artículo. Saludos.
Gracias por aportar esta solución.
Habra forma de acumular dos extras más de la siguiente forma:
Digamos tengo un producto que cuesta $255 y quiero agregar un extra por $75, más otro Extra por $80, dando un total de $410. ¿Esto es posible?
Espero me de a entender
Hola, si, claro, toma como base el mismo código y realiza las modificaciones agregando extras_product1, extras_product2, etc.
Buenos días, me encanta tu trabajo. En el producto funciona perfecto, pero no consigo que se me refleje el precio ni en el carrito ni en el pedido.
Hola, el código esta preparado para mostrar esa información en el carrito y pedido, es posible que algún plugin que tengas haga conflicto, podrías probar desactivando plugins. Saludos.