Вопрос или проблема
В разделе оформления заказа Woocommerce, я пытаюсь добавить флажок, который добавляет дополнительный продукт подписки. Это работает хорошо, и я воспользовался помощью здесь
Ещё одно требование заключается в том, что если в корзине есть другие товары, я хочу изменить цены на каждый продукт на основе пользовательских полей, и новые цены должны отображаться при оформлении заказа. Спасибо заранее.
Я использовал этот код, и он работает, но цена товара не изменяется на странице оплаты PayPal.
// Отобразить пользовательское поле при оформлении заказа
add_action( 'woocommerce_checkout_before_terms_and_conditions', 'custom_checkbox_checkout_field' );
function custom_checkbox_checkout_field() {
$value = WC()->session->get('add_a_product');
woocommerce_form_field( 'cb_add_product', array(
'type' => 'checkbox',
'label' => ' ' . __('Пожалуйста, отметьте здесь для получения VIP членства'),
'class' => array('form-row-wide'),
), $value == 'yes' ? true : false );
}
// jQuery Ajax запрос
add_action( 'wp_footer', 'checkout_custom_jquery_script' );
function checkout_custom_jquery_script() {
// Только страница оформления заказа
if( is_checkout() && ! is_wc_endpoint_url() ):
// Удалить "ship_different" индивидуальную сессию WC при загрузке
if( WC()->session->get('add_a_product') ){
WC()->session->__unset('add_a_product');
}
if( WC()->session->get('product_added_key') ){
WC()->session->__unset('product_added_key');
}
// Код jQuery Ajax
?>
<script type="text/javascript">
jQuery( function($){
if (typeof wc_checkout_params === 'undefined')
return false;
$('form.checkout').on( 'change', '#cb_add_product', function(){
var value = $(this).prop('checked') === true ? 'yes' : 'no';
$.ajax({
type: 'POST',
url: wc_checkout_params.ajax_url,
data: {
'action': 'add_a_product',
'add_a_product': value,
},
success: function (result) {
$('body').trigger('update_checkout');
//console.log(result);
}
});
});
});
</script>
<?php
endif;
}
// PHP обработчик Ajax-запроса WordPress
add_action( 'wp_ajax_add_a_product', 'checkout_ajax_add_a_product' );
add_action( 'wp_ajax_nopriv_add_a_product', 'checkout_ajax_add_a_product' );
function checkout_ajax_add_a_product() {
if ( isset($_POST['add_a_product']) ){
WC()->session->set('add_a_product', esc_attr($_POST['add_a_product']));
echo $_POST['add_a_product'];
}
die();
}
// Добавление или удаление бесплатного продукта
add_action( 'woocommerce_before_calculate_totals', 'adding_removing_specific_product' );
function adding_removing_specific_product( $cart ) {
if (is_admin() && !defined('DOING_AJAX'))
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
// ЗДЕСЬ ID конкретного товара
$product_id = 179;
if( WC()->session->get('add_a_product') == 'yes' && ! WC()->session->get('product_added_key') )
{
foreach ( $cart->get_cart() as $cart_item ) {
$cart_item_key = $cart->add_to_cart( $product_id );
WC()->session->set('product_added_key', $cart_item_key);
// Получить ID продукта (или вариации)
$product_id = $cart_item['data']->get_id();
// ПОЛУЧИТЬ НОВУЮ ЦЕНУ (код, который нужно заменить вашим)
$new_price = get_post_meta( $product_id, 'pro_price_extra_info', true );
// Обновлённая цена элемента корзины
$cart_item['data']->set_price( floatval( $new_price ) );
}
}
elseif( WC()->session->get('add_a_product') == 'no' && WC()->session->get('product_added_key') )
{
$cart_item_key = WC()->session->get('product_added_key');
$cart->remove_cart_item( $cart_item_key );
WC()->session->__unset('product_added_key');
}
}
Я решил свою проблему. этот код может помочь другим в будущем.
// Отобразить пользовательское поле при оформлении заказа
add_action( 'woocommerce_checkout_before_terms_and_conditions', 'custom_checkbox_checkout_field' );
function custom_checkbox_checkout_field() {
$value = WC()->session->get('add_a_product');
woocommerce_form_field( 'cb_add_product', array(
'type' => 'checkbox',
'label' => ' ' . __('Пожалуйста, отметьте здесь для получения VIP членства'),
'class' => array('form-row-wide'),
), $value == 'yes' ? true : false );
}
// jQuery Ajax запрос
add_action( 'wp_footer', 'checkout_custom_jquery_script' );
function checkout_custom_jquery_script() {
// Только страница оформления заказа
if( is_checkout() && ! is_wc_endpoint_url() ):
// Удалить "ship_different" индивидуальную сессию WC при загрузке
if( WC()->session->get('add_a_product') ){
WC()->session->__unset('add_a_product');
}
if( WC()->session->get('product_added_key') ){
WC()->session->__unset('product_added_key');
}
// Код jQuery Ajax
?>
<script type="text/javascript">
jQuery( function($){
if (typeof wc_checkout_params === 'undefined')
return false;
$('form.checkout').on( 'change', '#cb_add_product', function(){
var value = $(this).prop('checked') === true ? 'yes' : 'no';
$.ajax({
type: 'POST',
url: wc_checkout_params.ajax_url,
data: {
'action': 'add_a_product',
'add_a_product': value,
},
success: function (result) {
$('body').trigger('update_checkout');
//console.log(result);
}
});
if(value == 'no'){
window.location.reload();
}
});
});
</script>
<?php
endif;
}
// PHP обработчик Ajax-запроса WordPress
add_action( 'wp_ajax_add_a_product', 'checkout_ajax_add_a_product' );
add_action( 'wp_ajax_nopriv_add_a_product', 'checkout_ajax_add_a_product' );
function checkout_ajax_add_a_product() {
if ( isset($_POST['add_a_product']) ){
WC()->session->set('add_a_product', esc_attr($_POST['add_a_product']));
echo $_POST['add_a_product'];
}
die();
}
// Добавление или удаление бесплатного продукта
add_action( 'woocommerce_before_calculate_totals', 'adding_removing_specific_product' );
function adding_removing_specific_product( $cart ) {
if (is_admin() && !defined('DOING_AJAX'))
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
$has_sub = wcs_user_has_subscription( '', '179', 'active' );
$product_id = 179;
if( WC()->session->get('add_a_product') == 'yes' && ! WC()->session->get('product_added_key') ){
// ЗДЕСЬ ID конкретного товара
foreach ( $cart->get_cart() as $cart_item ) {
// Получить ID продукта (или вариации)
$product_idnew = $cart_item['data']->get_id();
// ПОЛУЧИТЬ НОВУЮ ЦЕНУ (код, который нужно заменить вашим)
$new_price = get_post_meta( $product_idnew, 'pro_price_extra_info', true );
$old_price = $cart_item['data']->get_price();
if($new_price == NULL){
$cart_item['data']->set_price( floatval( $old_price ) );
} else {
$cart_item['data']->set_price( floatval( $new_price ) );
}
}
$cart_item_key = $cart->add_to_cart( $product_id );
WC()->session->set('product_added_key', $cart_item_key);
} elseif( WC()->session->get('add_a_product') == 'no' && WC()->session->get('product_added_key') ) {
$cart_item_key = WC()->session->get('product_added_key');
$cart->remove_cart_item( $cart_item_key );
WC()->session->__unset('product_added_key');
}elseif ( $has_sub ) {
foreach ( $cart->get_cart() as $cart_item ) {
// Получить ID продукта (или вариации)
$product_idnew = $cart_item['data']->get_id();
// ПОЛУЧИТЬ НОВУЮ ЦЕНУ (код, который нужно заменить вашим)
$new_price = get_post_meta( $product_idnew, 'pro_price_extra_info', true );
$cart_item['data']->set_price( floatval( $new_price ) );
}
}
}
function woo_in_cart($product_id) {
global $woocommerce;
foreach($woocommerce->cart->get_cart() as $key => $val ) {
$_product = $val['data'];
if($product_id == $_product->id ) {
return true;
}
}
return false;
}
add_action( 'woocommerce_cart_loaded_from_session', 'adding_vip_product' );
function adding_vip_product( $cart ) {
$product_id = 179;
if(woo_in_cart($product_id) ) {
foreach ( $cart->get_cart() as $cart_item ) {
// Получить ID продукта (или вариации)
$product_idnew = $cart_item['data']->get_id();
// ПОЛУЧИТЬ НОВУЮ ЦЕНУ (код, который нужно заменить вашим)
$new_price = get_post_meta( $product_idnew, 'pro_price_extra_info', true );
if($new_price != 0){
$cart_item['data']->set_price( floatval( $new_price ) );
}
}
}
}
.
Ответ или решение
В WooCommerce иногда требуется дополнительная функциональность для улучшения пользовательского опыта. Одна из таких задач — добавление продукта и изменение цен на другие продукты в корзине при помощи чекбокса. Представленный ниже код решает эту задачу, предоставляя возможность добавления дополнительного подписного продукта через чекбокс на странице оформления заказа.
Функционал добавления чекбокса:
Создаются пользовательские поля на странице оформления заказа, где пользователь может выбрать дополнительный продукт. Это реализовано через действие woocommerce_checkout_before_terms_and_conditions
, чтобы добавить поле чекбокса перед условиями и положениями.
Код для отображения чекбокса:
add_action('woocommerce_checkout_before_terms_and_conditions', 'custom_checkbox_checkout_field');
function custom_checkbox_checkout_field() {
$value = WC()->session->get('add_a_product');
woocommerce_form_field('cb_add_product', array(
'type' => 'checkbox',
'label' => ' ' . __('Please check here to get VIP Membership'),
'class' => array('form-row-wide'),
), $value == 'yes' ? true : false);
}
Реализация AJAX-запроса:
Для обновления корзины в реальном времени используется jQuery и AJAX. Этот процесс происходит асинхронно, что обеспечивает удобство в использовании и быструю реакцию интерфейса.
Код для AJAX-запроса:
add_action('wp_footer', 'checkout_custom_jquery_script');
function checkout_custom_jquery_script() {
if (is_checkout() && !is_wc_endpoint_url()):
?>
<script type="text/javascript">
jQuery(function($){
if (typeof wc_checkout_params === 'undefined')
return false;
$('form.checkout').on('change', '#cb_add_product', function(){
var value = $(this).prop('checked') === true ? 'yes' : 'no';
$.ajax({
type: 'POST',
url: wc_checkout_params.ajax_url,
data: {
'action': 'add_a_product',
'add_a_product': value,
},
success: function (result) {
$('body').trigger('update_checkout');
}
});
if(value == 'no'){
window.location.reload();
}
});
});
</script>
<?php
endif;
}
Серверная обработка заявки:
При получении AJAX-запроса происходит изменение состояния сессии через функции в WooCommerce. Это позволяет добавлять или удалять продукт из корзины.
Код для обработки AJAX-запроса:
add_action('wp_ajax_add_a_product', 'checkout_ajax_add_a_product');
add_action('wp_ajax_nopriv_add_a_product', 'checkout_ajax_add_a_product');
function checkout_ajax_add_a_product() {
if (isset($_POST['add_a_product'])){
WC()->session->set('add_a_product', esc_attr($_POST['add_a_product']));
echo $_POST['add_a_product'];
}
die();
}
Работа с корзиной:
В функции woocommerce_before_calculate_totals
реализована логика добавления или удаления подписки и изменения цены других товаров в зависимости от настроек. Эту функцию хорошо тестировать на активных подписках, чтобы избежать неожиданных ситуаций при оформлении заказа.
Основные моменты котировки новых цен:
- Получение новых цен с использованием
get_post_meta
. - Обновление цен в корзине через
set_price
.
Код для обработки корзины:
add_action('woocommerce_before_calculate_totals', 'adding_removing_specific_product');
function adding_removing_specific_product($cart) {
if (is_admin() && !defined('DOING_AJAX'))
return;
if (did_action('woocommerce_before_calculate_totals') >= 2)
return;
$product_id = 179; // ID подписки
if(WC()->session->get('add_a_product') == 'yes' && !WC()->session->get('product_added_key')) {
foreach ($cart->get_cart() as $cart_item) {
$new_price = get_post_meta($cart_item['data']->get_id(), 'pro_price_extra_info', true);
$cart_item['data']->set_price(floatval($new_price));
$cart_item_key = $cart->add_to_cart($product_id);
WC()->session->set('product_added_key', $cart_item_key);
}
} elseif(WC()->session->get('add_a_product') == 'no' && WC()->session->get('product_added_key')) {
$cart_item_key = WC()->session->get('product_added_key');
$cart->remove_cart_item($cart_item_key);
WC()->session->__unset('product_added_key');
}
}
Этот код помогает не только гибко управлять пользовательским опытом, но и минимизирует риски связанных с транзакциями через платёжные сервисы, такие как PayPal. Внедрение таким образом улучшает конверсию и увеличивает вероятность подписки на продукт благодаря интуитивному пользователю интерфейсу.