Anonymous
Динамические комиссии, рассчитываемые на основе пользовательских полей оформления заказа в WooCommerce.
Сообщение
Anonymous » 29 дек 2025, 16:09
У меня есть магазин WooCommerce, специализирующийся на аренде пляжного инвентаря. Я добавил раскрывающееся меню на страницу оформления заказа, где покупатель может выбрать доставку заказа или возможность забрать его самостоятельно. Если они выберут вариант доставки, к общей сумме корзины будет добавлена плата в размере 10 долларов США, указанная как «Сбор за доставку». Если они выберут самовывоз, появится второй раскрывающийся список, в котором они смогут выбрать место получения. Я хочу добавить для клиентов возможность покупать холодные напитки на странице оформления заказа, если они выбирают определенное место выдачи (Kamini's Kitchen), список которых должен появиться, когда они выберут это место выдачи. Я написал так, чтобы для каждого напитка появлялись галочки и количество, которое можно выбрать. Когда напиток добавляется, его следует добавить в корзину под своим собственным названием, а указанную цену следует добавить к общей сумме (умноженной на множитель). Наконец, выбранные варианты напитков должны появиться в электронных письмах с заказами и в административной панели.
Вот моя попытка кода, основанная на этой ветке ответов:
Код: Выделить всё
// Utility function: Get Delivery or Pickup options
function get_delivery_or_pickup_options() {
return array(
'' => esc_html__( 'Select an option', 'woocommerce' ),
'delivery' => esc_html__( 'Delivery Service', 'woocommerce' ),
'pickup' => esc_html__( 'Pickup', 'woocommerce' )
);
}
// Utility function: Get pickup location options
function get_pickup_location_options() {
return array(
'' => esc_html__( 'Select an option', 'woocommerce' ),
'main_office' => esc_html__( 'Pavia 20F - Main Office', 'woocommerce' ),
'kaminis_kitchen' => esc_html__( "Kamini's Kitchen (Baby Beach)", 'woocommerce' )
);
}
add_action( 'woocommerce_before_order_notes', 'add_delivery_or_pickup_fields', 10 );
function add_delivery_or_pickup_fields( $checkout ) {
// Existing dropdowns...
woocommerce_form_field( 'delivery_or_pickup', array(
'type' => 'select',
'class' => array('form-row-wide'),
'label' => esc_html__( 'Delivery or Pickup?', 'woocommerce' ),
'required' => true,
'options' => get_delivery_or_pickup_options(),
), $checkout->get_value('delivery_or_pickup') );
woocommerce_form_field('pickup_location', array(
'type' => 'select',
'class' => array('form-row-wide'),
'label' => esc_html__( 'Select pickup location:', 'woocommerce' ),
'required' => true,
'options' => get_pickup_location_options(),
), $checkout->get_value('pickup_location'));
// Drinks Section - Hidden by default, displayed by JS if pickup_location == kaminis_kitchen
echo '';
echo '' . esc_html__('If you’re renting a beach cooler, you have the option to pre-purchase drinks here and have the cooler loaded up with ice and drinks when picking it up', 'woocommerce') . '';
$drink_items = array(
'bag_of_ice' => array('Bag of Ice', 4.00),
'chill' => array('Chill', 5.00),
'balashi' => array('Balashi', 5.00),
'magic_mango' => array('Magic Mango', 5.00),
'amstel_bright' => array('Amstel Bright', 6.00),
'budweiser' => array('Budweiser', 5.00),
'bud_light' => array('Bud Light', 5.00),
'corona' => array('Corona', 6.00),
'heineken' => array('Heineken', 5.00),
'presidente' => array('Presidente', 5.00),
'modelo' => array('Modelo', 5.00),
'polar' => array('Polar', 4.00),
'guinness' => array('Guinness', 7.00),
'coke' => array('Coke', 3.00),
'coke_zero' => array('Coke Zero', 3.00),
'sprite' => array('Sprite', 3.00),
'sprite_zero' => array('Sprite Zero', 3.00),
'gingerale' => array('Gingerale', 3.00),
'fuze_tea' => array('Fuze Tea', 3.00),
'club_soda' => array('Club Soda', 3.00),
'tonic_water' => array('Tonic Water', 3.00),
'fanta_cherry' => array('Fanta Cherry', 3.00),
'fanta_grape' => array('Fanta Grape', 3.00),
'fanta_orange' => array('Fanta Orange', 3.00),
'bottled_water' => array('Bottled Water', 2.57),
);
foreach ( $drink_items as $key => $item ) {
echo '
' . esc_html($item[0]) . ' ($' . number_format($item[1], 2) . ') ';
echo '
';
}
echo '';
}
// JavaScript to toggle visibility of the pickup location dropdown and update delivery fee
add_action( 'woocommerce_checkout_init', 'add_delivery_or_pickup_js_script' );
function add_delivery_or_pickup_js_script() {
wc_enqueue_js("
const pickupField = $('#pickup_location_field');
const drinkOptions = $('#drink_options_section');
function toggleDrinkOptions() {
if ($('#pickup_location').val() === 'kaminis_kitchen') {
drinkOptions.show();
} else {
drinkOptions.hide();
}
}
if ($('#delivery_or_pickup').val() !== 'pickup') {
pickupField.hide();
drinkOptions.hide();
}
$(document.body).on('change', '#delivery_or_pickup', function() {
const val = $(this).val();
val === 'pickup' ? pickupField.show() : pickupField.hide();
$.post(wc_checkout_params.ajax_url, {
action: 'save_delivery_or_pickup_to_session',
delivery_or_pickup: val
}, function() {
$(document.body).trigger('update_checkout');
});
});
$(document.body).on('change', '#pickup_location', function() {
toggleDrinkOptions();
$(document.body).trigger('update_checkout');
});
// Send drink selections via AJAX
function updateDrinkSessionData() {
const selectedDrinks = {};
$('#drink_options_section input[type=checkbox]:checked').each(function() {
const key = $(this).attr('name').replace('drinks[', '').replace(']', '');
const qty = $('#drink_qty_' + key).val() || 1;
selectedDrinks[key] = qty;
});
$.post(wc_checkout_params.ajax_url, {
action: 'save_drink_options_to_session',
drinks: selectedDrinks
}, function() {
$(document.body).trigger('update_checkout');
});
}
$(document.body).on('change', '#drink_options_section input', updateDrinkSessionData);
toggleDrinkOptions();
");
}
// Ajax request: Save selection to WooCommerce session
add_action('wp_ajax_save_delivery_or_pickup_to_session', 'save_delivery_or_pickup_to_session');
add_action('wp_ajax_nopriv_save_delivery_or_pickup_to_session', 'save_delivery_or_pickup_to_session');
function save_delivery_or_pickup_to_session() {
if ( isset($_POST['delivery_or_pickup']) ) {
WC()->session->set('delivery_or_pickup', sanitize_text_field($_POST['delivery_or_pickup']));
}
wp_die();
}
// Add delivery fee if "Delivery Service" is selected
add_action( 'woocommerce_cart_calculate_fees', 'add_delivery_option_fee_based_on_session' );
function add_delivery_option_fee_based_on_session( $cart ) {
if (is_admin() && !defined('DOING_AJAX')) return;
if ( is_checkout() && WC()->session->get('delivery_or_pickup') === 'delivery' ) {
$delivery_fee = 10;
$cart->add_fee( esc_html__( 'Delivery Fee', 'woocommerce' ), $delivery_fee );
}
}
// Save drink selection to WooCommerce session
add_filter('woocommerce_checkout_posted_data', 'capture_drink_data_during_ajax');
function capture_drink_data_during_ajax( $data ) {
if ( isset($_POST['drinks']) && isset($_POST['drink_qty']) ) {
$data['drinks'] = $_POST['drinks'];
$data['drink_qty'] = $_POST['drink_qty'];
}
return $data;
}
add_action('wp_ajax_save_drink_options_to_session', 'save_drink_options_to_session');
add_action('wp_ajax_nopriv_save_drink_options_to_session', 'save_drink_options_to_session');
function save_drink_options_to_session() {
$drinks = isset($_POST['drinks']) ? $_POST['drinks'] : array();
$sanitized = array();
foreach ($drinks as $drink => $qty) {
$drink = sanitize_key($drink);
$qty = max(1, intval($qty));
$sanitized[$drink] = $qty;
}
WC()->session->set('drink_data', $sanitized);
wp_die();
}
add_action('woocommerce_cart_calculate_fees', 'add_drink_fee_via_ajax', 20, 1);
function add_drink_fee_via_ajax($cart) {
if (is_admin() && !defined('DOING_AJAX')) return;
$pickup_location = isset($_POST['pickup_location']) ? sanitize_text_field($_POST['pickup_location']) : WC()->session->get('pickup_location');
if ($pickup_location !== 'kaminis_kitchen') return;
$drink_data = WC()->session->get('drink_data', []);
if (empty($drink_data)) return;
$prices = array(
'bag_of_ice' => 4.00, 'chill' => 5.00, 'balashi' => 5.00, 'magic_mango' => 5.00,
'amstel_bright' => 6.00, 'budweiser' => 5.00, 'bud_light' => 5.00, 'corona' => 6.00,
'heineken' => 5.00, 'presidente' => 5.00, 'modelo' => 5.00, 'polar' => 4.00, 'guinness' => 7.00,
'coke' => 3.00, 'coke_zero' => 3.00, 'sprite' => 3.00, 'sprite_zero' => 3.00,
'gingerale' => 3.00, 'fuze_tea' => 3.00, 'club_soda' => 3.00, 'tonic_water' => 3.00,
'fanta_cherry' => 3.00, 'fanta_grape' => 3.00, 'fanta_orange' => 3.00, 'bottled_water' => 2.57,
);
$total = 0;
foreach ($drink_data as $drink => $qty) {
if (isset($prices[$drink])) {
$total += $prices[$drink] * $qty;
}
}
if ($total > 0) {
$cart->add_fee(__('Drink Options', 'woocommerce'), $total);
}
}
add_action('woocommerce_checkout_order_processed', function () {
WC()->session->__unset('drink_data');
}, 10, 1);
// Validate custom shipping options
add_action( 'woocommerce_after_checkout_validation', 'delivery_or_pickup_validation', 20, 2 );
function delivery_or_pickup_validation( $data, $errors ) {
// Delivery or Pickup validation
if ( isset($_POST['delivery_or_pickup']) && empty($_POST['delivery_or_pickup']) ) {
$errors->add( 'delivery_or_pickup', esc_html__( 'You must choose between "Delivery" or "Pickup" option.', 'woocommerce' ), 'error' );
}
// Pickup location validation
elseif ( isset($_POST['delivery_or_pickup']) && $_POST['delivery_or_pickup'] === 'pickup'
&& isset($_POST['pickup_location']) && empty($_POST['pickup_location']) ) {
$errors->add( 'pickup_location', esc_html__( 'You must choose a pickup location.', 'woocommerce' ), 'error' );
}
}
// Save custom chosen shipping option details as order metadata
add_action( 'woocommerce_checkout_create_order', 'save_delivery_or_pickup_as_order_metadata', 10 );
function save_delivery_or_pickup_as_order_metadata( $order ) {
if ( isset($_POST['delivery_or_pickup']) && !empty($_POST['delivery_or_pickup']) ) {
$order->add_meta_data('_delivery_or_pickup', esc_attr($_POST['delivery_or_pickup']), true );
}
if ( isset($_POST['pickup_location']) && !empty($_POST['pickup_location']) ) {
$order->add_meta_data('_pickup_location', esc_attr($_POST['pickup_location']), true);
}
// Remove the WC Session Variable
if ( WC()->session->__isset('delivery_or_pickup') ) {
WC()->session->__unset('delivery_or_pickup');
}
}
add_action( 'woocommerce_checkout_create_order', 'save_drinks_to_order_meta', 20, 1 );
function save_drinks_to_order_meta( $order ) {
if ( isset($_POST['drinks']) ) {
$items = array(
'bag_of_ice' => 'Bag of Ice', 'chill' => 'Chill', 'balashi' => 'Balashi', 'magic_mango' => 'Magic Mango',
'amstel_bright' => 'Amstel Bright', 'budweiser' => 'Budweiser', 'bud_light' => 'Bud Light',
'corona' => 'Corona', 'heineken' => 'Heineken', 'presidente' => 'Presidente',
'modelo' => 'Modelo', 'polar' => 'Polar', 'guinness' => 'Guinness', 'coke' => 'Coke',
'coke_zero' => 'Coke Zero', 'sprite' => 'Sprite', 'sprite_zero' => 'Sprite Zero',
'gingerale' => 'Gingerale', 'fuze_tea' => 'Fuze Tea', 'club_soda' => 'Club Soda',
'tonic_water' => 'Tonic Water', 'fanta_cherry' => 'Fanta Cherry', 'fanta_grape' => 'Fanta Grape',
'fanta_orange' => 'Fanta Orange', 'bottled_water' => 'Bottled Water'
);
$drinks_ordered = array();
foreach ($_POST['drinks'] as $key => $val) {
$qty = intval($_POST['drink_qty'][$key] ?? 1);
if ($qty > 0 && isset($items[$key])) {
$drinks_ordered[] = $items[$key] . ' x' . $qty;
}
}
if ( !empty($drinks_ordered) ) {
$order->add_meta_data('_drink_options', implode(', ', $drinks_ordered));
}
}
}
// Update custom chosen shipping option details as USER metadata (useful for next checkout)
add_action( 'woocommerce_checkout_update_customer', 'save_delivery_or_pickup_as_user_metadata', 10 );
function save_delivery_or_pickup_as_user_metadata( $customer ) {
if ( isset($_POST['delivery_or_pickup']) && !empty($_POST['delivery_or_pickup']) ) {
$customer->update_meta_data('delivery_or_pickup', esc_attr($_POST['delivery_or_pickup']));
}
if ( isset($_POST['pickup_location']) && !empty($_POST['pickup_location']) ) {
$customer->update_meta_data('pickup_location', esc_attr($_POST['pickup_location']));
}
}
// Display chosen custom shipping option details in the admin panel under shipping address
add_action( 'woocommerce_admin_order_data_after_shipping_address', 'display_delivery_or_pickup_meta_in_admin_order', 10 );
function display_delivery_or_pickup_meta_in_admin_order( $order ) {
// Delivery or Pickup
if ( $value = $order->get_meta('_delivery_or_pickup') ) {
$options = get_delivery_or_pickup_options();
printf( '
[b]%s:[/b] %s', esc_html__('Shipping', 'woocommerce' ), $options[$value] );
// Pickup location
if ( $value = $order->get_meta('_pickup_location') ) {
$options = get_pickup_location_options();
printf( '
[b]%s:[/b] %s', esc_html__('Location', 'woocommerce' ), $options[$value] );
}
echo '
';
}
}
// Display chosen custom shipping option details in order total lines (customer orders and email notifications)
add_filter( 'woocommerce_get_order_item_totals', 'insert_custom_line_order_item_totals', 10, 3 );
function insert_custom_line_order_item_totals( $total_rows, $order, $tax_display ){
$shipping = $order->get_meta('_delivery_or_pickup');
$options1 = get_delivery_or_pickup_options();
$location = $order->get_meta('_pickup_location');
$options2 = get_pickup_location_options();
$key_target = array_key_exists('discount', $total_rows) ? 'discount' : 'cart_subtotal';
$new_total_rows = array();
// Loop through total rows
foreach( $total_rows as $key => $value ){
$new_total_rows[$key] = $total_rows[$key];
if( 'cart_subtotal' === $key ) {
$new_total_rows['shipping2'] = array(
'label' => esc_html__('Shipping option:'),
'value' => $options1[$shipping],
);
if ( $location ) {
$new_total_rows['location'] = array(
'label' => esc_html__('Pickup location:'),
'value' => $options2[$location],
);
$new_total_rows['drink_options'] = array(
'label' => esc_html__('Drink Options:'),
'value' => esc_html($order->get_meta('_drink_options')),
);
}
}
}
return $new_total_rows;
}
Но когда клиент выбирает дополнительный напиток из списка, дополнительная соответствующая комиссия не добавляется: касса обновляется, но ничего не добавляется. Здесь часть «напитки» работает не так, как задумано. В моем коде я определил массив всех напитков с названием метки и стоимостью для каждого варианта, и этот список вариантов напитков отображается условно в зависимости от выбранного места получения с помощью JavaScript. Здесь я застрял на той части, где выбранные параметры должны динамически добавляться в корзину через AJAX.
Подробнее здесь:
https://stackoverflow.com/questions/796 ... oocommerce
1767013789
Anonymous
У меня есть магазин WooCommerce, специализирующийся на аренде пляжного инвентаря. Я добавил раскрывающееся меню на страницу оформления заказа, где покупатель может выбрать доставку заказа или возможность забрать его самостоятельно. Если они выберут вариант доставки, к общей сумме корзины будет добавлена плата в размере 10 долларов США, указанная как «Сбор за доставку». Если они выберут самовывоз, появится второй раскрывающийся список, в котором они смогут выбрать место получения. Я хочу добавить для клиентов возможность покупать холодные напитки на странице оформления заказа, если они выбирают определенное место выдачи (Kamini's Kitchen), список которых должен появиться, когда они выберут это место выдачи. Я написал так, чтобы для каждого напитка появлялись галочки и количество, которое можно выбрать. Когда напиток добавляется, его следует добавить в корзину под своим собственным названием, а указанную цену следует добавить к общей сумме (умноженной на множитель). Наконец, выбранные варианты напитков должны появиться в электронных письмах с заказами и в административной панели. Вот моя попытка кода, основанная на этой ветке ответов: [code]// Utility function: Get Delivery or Pickup options function get_delivery_or_pickup_options() { return array( '' => esc_html__( 'Select an option', 'woocommerce' ), 'delivery' => esc_html__( 'Delivery Service', 'woocommerce' ), 'pickup' => esc_html__( 'Pickup', 'woocommerce' ) ); } // Utility function: Get pickup location options function get_pickup_location_options() { return array( '' => esc_html__( 'Select an option', 'woocommerce' ), 'main_office' => esc_html__( 'Pavia 20F - Main Office', 'woocommerce' ), 'kaminis_kitchen' => esc_html__( "Kamini's Kitchen (Baby Beach)", 'woocommerce' ) ); } add_action( 'woocommerce_before_order_notes', 'add_delivery_or_pickup_fields', 10 ); function add_delivery_or_pickup_fields( $checkout ) { // Existing dropdowns... woocommerce_form_field( 'delivery_or_pickup', array( 'type' => 'select', 'class' => array('form-row-wide'), 'label' => esc_html__( 'Delivery or Pickup?', 'woocommerce' ), 'required' => true, 'options' => get_delivery_or_pickup_options(), ), $checkout->get_value('delivery_or_pickup') ); woocommerce_form_field('pickup_location', array( 'type' => 'select', 'class' => array('form-row-wide'), 'label' => esc_html__( 'Select pickup location:', 'woocommerce' ), 'required' => true, 'options' => get_pickup_location_options(), ), $checkout->get_value('pickup_location')); // Drinks Section - Hidden by default, displayed by JS if pickup_location == kaminis_kitchen echo ''; echo '' . esc_html__('If you’re renting a beach cooler, you have the option to pre-purchase drinks here and have the cooler loaded up with ice and drinks when picking it up', 'woocommerce') . ''; $drink_items = array( 'bag_of_ice' => array('Bag of Ice', 4.00), 'chill' => array('Chill', 5.00), 'balashi' => array('Balashi', 5.00), 'magic_mango' => array('Magic Mango', 5.00), 'amstel_bright' => array('Amstel Bright', 6.00), 'budweiser' => array('Budweiser', 5.00), 'bud_light' => array('Bud Light', 5.00), 'corona' => array('Corona', 6.00), 'heineken' => array('Heineken', 5.00), 'presidente' => array('Presidente', 5.00), 'modelo' => array('Modelo', 5.00), 'polar' => array('Polar', 4.00), 'guinness' => array('Guinness', 7.00), 'coke' => array('Coke', 3.00), 'coke_zero' => array('Coke Zero', 3.00), 'sprite' => array('Sprite', 3.00), 'sprite_zero' => array('Sprite Zero', 3.00), 'gingerale' => array('Gingerale', 3.00), 'fuze_tea' => array('Fuze Tea', 3.00), 'club_soda' => array('Club Soda', 3.00), 'tonic_water' => array('Tonic Water', 3.00), 'fanta_cherry' => array('Fanta Cherry', 3.00), 'fanta_grape' => array('Fanta Grape', 3.00), 'fanta_orange' => array('Fanta Orange', 3.00), 'bottled_water' => array('Bottled Water', 2.57), ); foreach ( $drink_items as $key => $item ) { echo ' ' . esc_html($item[0]) . ' ($' . number_format($item[1], 2) . ') '; echo ' '; } echo ''; } // JavaScript to toggle visibility of the pickup location dropdown and update delivery fee add_action( 'woocommerce_checkout_init', 'add_delivery_or_pickup_js_script' ); function add_delivery_or_pickup_js_script() { wc_enqueue_js(" const pickupField = $('#pickup_location_field'); const drinkOptions = $('#drink_options_section'); function toggleDrinkOptions() { if ($('#pickup_location').val() === 'kaminis_kitchen') { drinkOptions.show(); } else { drinkOptions.hide(); } } if ($('#delivery_or_pickup').val() !== 'pickup') { pickupField.hide(); drinkOptions.hide(); } $(document.body).on('change', '#delivery_or_pickup', function() { const val = $(this).val(); val === 'pickup' ? pickupField.show() : pickupField.hide(); $.post(wc_checkout_params.ajax_url, { action: 'save_delivery_or_pickup_to_session', delivery_or_pickup: val }, function() { $(document.body).trigger('update_checkout'); }); }); $(document.body).on('change', '#pickup_location', function() { toggleDrinkOptions(); $(document.body).trigger('update_checkout'); }); // Send drink selections via AJAX function updateDrinkSessionData() { const selectedDrinks = {}; $('#drink_options_section input[type=checkbox]:checked').each(function() { const key = $(this).attr('name').replace('drinks[', '').replace(']', ''); const qty = $('#drink_qty_' + key).val() || 1; selectedDrinks[key] = qty; }); $.post(wc_checkout_params.ajax_url, { action: 'save_drink_options_to_session', drinks: selectedDrinks }, function() { $(document.body).trigger('update_checkout'); }); } $(document.body).on('change', '#drink_options_section input', updateDrinkSessionData); toggleDrinkOptions(); "); } // Ajax request: Save selection to WooCommerce session add_action('wp_ajax_save_delivery_or_pickup_to_session', 'save_delivery_or_pickup_to_session'); add_action('wp_ajax_nopriv_save_delivery_or_pickup_to_session', 'save_delivery_or_pickup_to_session'); function save_delivery_or_pickup_to_session() { if ( isset($_POST['delivery_or_pickup']) ) { WC()->session->set('delivery_or_pickup', sanitize_text_field($_POST['delivery_or_pickup'])); } wp_die(); } // Add delivery fee if "Delivery Service" is selected add_action( 'woocommerce_cart_calculate_fees', 'add_delivery_option_fee_based_on_session' ); function add_delivery_option_fee_based_on_session( $cart ) { if (is_admin() && !defined('DOING_AJAX')) return; if ( is_checkout() && WC()->session->get('delivery_or_pickup') === 'delivery' ) { $delivery_fee = 10; $cart->add_fee( esc_html__( 'Delivery Fee', 'woocommerce' ), $delivery_fee ); } } // Save drink selection to WooCommerce session add_filter('woocommerce_checkout_posted_data', 'capture_drink_data_during_ajax'); function capture_drink_data_during_ajax( $data ) { if ( isset($_POST['drinks']) && isset($_POST['drink_qty']) ) { $data['drinks'] = $_POST['drinks']; $data['drink_qty'] = $_POST['drink_qty']; } return $data; } add_action('wp_ajax_save_drink_options_to_session', 'save_drink_options_to_session'); add_action('wp_ajax_nopriv_save_drink_options_to_session', 'save_drink_options_to_session'); function save_drink_options_to_session() { $drinks = isset($_POST['drinks']) ? $_POST['drinks'] : array(); $sanitized = array(); foreach ($drinks as $drink => $qty) { $drink = sanitize_key($drink); $qty = max(1, intval($qty)); $sanitized[$drink] = $qty; } WC()->session->set('drink_data', $sanitized); wp_die(); } add_action('woocommerce_cart_calculate_fees', 'add_drink_fee_via_ajax', 20, 1); function add_drink_fee_via_ajax($cart) { if (is_admin() && !defined('DOING_AJAX')) return; $pickup_location = isset($_POST['pickup_location']) ? sanitize_text_field($_POST['pickup_location']) : WC()->session->get('pickup_location'); if ($pickup_location !== 'kaminis_kitchen') return; $drink_data = WC()->session->get('drink_data', []); if (empty($drink_data)) return; $prices = array( 'bag_of_ice' => 4.00, 'chill' => 5.00, 'balashi' => 5.00, 'magic_mango' => 5.00, 'amstel_bright' => 6.00, 'budweiser' => 5.00, 'bud_light' => 5.00, 'corona' => 6.00, 'heineken' => 5.00, 'presidente' => 5.00, 'modelo' => 5.00, 'polar' => 4.00, 'guinness' => 7.00, 'coke' => 3.00, 'coke_zero' => 3.00, 'sprite' => 3.00, 'sprite_zero' => 3.00, 'gingerale' => 3.00, 'fuze_tea' => 3.00, 'club_soda' => 3.00, 'tonic_water' => 3.00, 'fanta_cherry' => 3.00, 'fanta_grape' => 3.00, 'fanta_orange' => 3.00, 'bottled_water' => 2.57, ); $total = 0; foreach ($drink_data as $drink => $qty) { if (isset($prices[$drink])) { $total += $prices[$drink] * $qty; } } if ($total > 0) { $cart->add_fee(__('Drink Options', 'woocommerce'), $total); } } add_action('woocommerce_checkout_order_processed', function () { WC()->session->__unset('drink_data'); }, 10, 1); // Validate custom shipping options add_action( 'woocommerce_after_checkout_validation', 'delivery_or_pickup_validation', 20, 2 ); function delivery_or_pickup_validation( $data, $errors ) { // Delivery or Pickup validation if ( isset($_POST['delivery_or_pickup']) && empty($_POST['delivery_or_pickup']) ) { $errors->add( 'delivery_or_pickup', esc_html__( 'You must choose between "Delivery" or "Pickup" option.', 'woocommerce' ), 'error' ); } // Pickup location validation elseif ( isset($_POST['delivery_or_pickup']) && $_POST['delivery_or_pickup'] === 'pickup' && isset($_POST['pickup_location']) && empty($_POST['pickup_location']) ) { $errors->add( 'pickup_location', esc_html__( 'You must choose a pickup location.', 'woocommerce' ), 'error' ); } } // Save custom chosen shipping option details as order metadata add_action( 'woocommerce_checkout_create_order', 'save_delivery_or_pickup_as_order_metadata', 10 ); function save_delivery_or_pickup_as_order_metadata( $order ) { if ( isset($_POST['delivery_or_pickup']) && !empty($_POST['delivery_or_pickup']) ) { $order->add_meta_data('_delivery_or_pickup', esc_attr($_POST['delivery_or_pickup']), true ); } if ( isset($_POST['pickup_location']) && !empty($_POST['pickup_location']) ) { $order->add_meta_data('_pickup_location', esc_attr($_POST['pickup_location']), true); } // Remove the WC Session Variable if ( WC()->session->__isset('delivery_or_pickup') ) { WC()->session->__unset('delivery_or_pickup'); } } add_action( 'woocommerce_checkout_create_order', 'save_drinks_to_order_meta', 20, 1 ); function save_drinks_to_order_meta( $order ) { if ( isset($_POST['drinks']) ) { $items = array( 'bag_of_ice' => 'Bag of Ice', 'chill' => 'Chill', 'balashi' => 'Balashi', 'magic_mango' => 'Magic Mango', 'amstel_bright' => 'Amstel Bright', 'budweiser' => 'Budweiser', 'bud_light' => 'Bud Light', 'corona' => 'Corona', 'heineken' => 'Heineken', 'presidente' => 'Presidente', 'modelo' => 'Modelo', 'polar' => 'Polar', 'guinness' => 'Guinness', 'coke' => 'Coke', 'coke_zero' => 'Coke Zero', 'sprite' => 'Sprite', 'sprite_zero' => 'Sprite Zero', 'gingerale' => 'Gingerale', 'fuze_tea' => 'Fuze Tea', 'club_soda' => 'Club Soda', 'tonic_water' => 'Tonic Water', 'fanta_cherry' => 'Fanta Cherry', 'fanta_grape' => 'Fanta Grape', 'fanta_orange' => 'Fanta Orange', 'bottled_water' => 'Bottled Water' ); $drinks_ordered = array(); foreach ($_POST['drinks'] as $key => $val) { $qty = intval($_POST['drink_qty'][$key] ?? 1); if ($qty > 0 && isset($items[$key])) { $drinks_ordered[] = $items[$key] . ' x' . $qty; } } if ( !empty($drinks_ordered) ) { $order->add_meta_data('_drink_options', implode(', ', $drinks_ordered)); } } } // Update custom chosen shipping option details as USER metadata (useful for next checkout) add_action( 'woocommerce_checkout_update_customer', 'save_delivery_or_pickup_as_user_metadata', 10 ); function save_delivery_or_pickup_as_user_metadata( $customer ) { if ( isset($_POST['delivery_or_pickup']) && !empty($_POST['delivery_or_pickup']) ) { $customer->update_meta_data('delivery_or_pickup', esc_attr($_POST['delivery_or_pickup'])); } if ( isset($_POST['pickup_location']) && !empty($_POST['pickup_location']) ) { $customer->update_meta_data('pickup_location', esc_attr($_POST['pickup_location'])); } } // Display chosen custom shipping option details in the admin panel under shipping address add_action( 'woocommerce_admin_order_data_after_shipping_address', 'display_delivery_or_pickup_meta_in_admin_order', 10 ); function display_delivery_or_pickup_meta_in_admin_order( $order ) { // Delivery or Pickup if ( $value = $order->get_meta('_delivery_or_pickup') ) { $options = get_delivery_or_pickup_options(); printf( ' [b]%s:[/b] %s', esc_html__('Shipping', 'woocommerce' ), $options[$value] ); // Pickup location if ( $value = $order->get_meta('_pickup_location') ) { $options = get_pickup_location_options(); printf( ' [b]%s:[/b] %s', esc_html__('Location', 'woocommerce' ), $options[$value] ); } echo ' '; } } // Display chosen custom shipping option details in order total lines (customer orders and email notifications) add_filter( 'woocommerce_get_order_item_totals', 'insert_custom_line_order_item_totals', 10, 3 ); function insert_custom_line_order_item_totals( $total_rows, $order, $tax_display ){ $shipping = $order->get_meta('_delivery_or_pickup'); $options1 = get_delivery_or_pickup_options(); $location = $order->get_meta('_pickup_location'); $options2 = get_pickup_location_options(); $key_target = array_key_exists('discount', $total_rows) ? 'discount' : 'cart_subtotal'; $new_total_rows = array(); // Loop through total rows foreach( $total_rows as $key => $value ){ $new_total_rows[$key] = $total_rows[$key]; if( 'cart_subtotal' === $key ) { $new_total_rows['shipping2'] = array( 'label' => esc_html__('Shipping option:'), 'value' => $options1[$shipping], ); if ( $location ) { $new_total_rows['location'] = array( 'label' => esc_html__('Pickup location:'), 'value' => $options2[$location], ); $new_total_rows['drink_options'] = array( 'label' => esc_html__('Drink Options:'), 'value' => esc_html($order->get_meta('_drink_options')), ); } } } return $new_total_rows; } [/code] Но когда клиент выбирает дополнительный напиток из списка, дополнительная соответствующая комиссия не добавляется: касса обновляется, но ничего не добавляется. Здесь часть «напитки» работает не так, как задумано. В моем коде я определил массив всех напитков с названием метки и стоимостью для каждого варианта, и этот список вариантов напитков отображается условно в зависимости от выбранного места получения с помощью JavaScript. Здесь я застрял на той части, где выбранные параметры должны динамически добавляться в корзину через AJAX. Подробнее здесь: [url]https://stackoverflow.com/questions/79639683/dynamic-fees-calculated-from-custom-checkout-fields-in-woocommerce[/url]