【问题标题】:Set a discounted cart item price that is reflected on Orders in Woocommerce 3设置反映在 Woocommerce 3 中的订单上的折扣购物车商品价格
【发布时间】:2018-08-28 11:16:13
【问题描述】:

我在我的 functions.php 中使用此代码对我的产品应用 10% 的折扣,从购物车中的第二个开始:

function add_discount_price_percent( $cart_object ) {

    global $woocommerce;

    $pdtcnt=0;

    foreach ($woocommerce->cart->get_cart() as $cart_item_key => $cart_item) {
        $pdtcnt++;

        $oldprice = 0;
        $newprice = 0;


        if($pdtcnt>1) { // from second product

            $oldprice = $cart_item['data']->price; //original product price      

            // echo "$oldprice<br />";

            $newprice = $oldprice*0.9; //discounted price
            $cart_item['data']->set_sale_price($newprice);
            $cart_item['data']->set_price($newprice);
            $cart_item['data']->set_regular_price($oldprice);

        }     
    }

    WC()->cart->calculate_totals();

}


add_action( 'woocommerce_before_cart', 'add_discount_price_percent', 1);

add_action( 'woocommerce_before_checkout_form', 'add_discount_price_percent', 99 );

价格在购物车和结帐页面中都正确显示,但是当我使用 PayPal 沙盒测试我的付款时,我看到并且必须支付全价,因为折扣被忽略了。

如果我在提交按钮之前回显折扣价格,我会得到正确的价格:

function echo_discount_before_checkout_submit() {

    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    foreach ( WC()->cart->get_cart() as $key => $value ) {
        echo $value['data']->price . "<br />";
    }

}
add_action( 'woocommerce_review_order_before_submit', 'echo_discount_before_checkout_submit', 99 );

如何向 PayPal 发送正确的折扣价格?

编辑:@LoisTheAtzec 的回复非常好,但如果数量超过 2,即使是第一个产品,我也需要 10% 的折扣:我正在尝试此代码,但我无法获得正确的值。

// If it is the first product and quantity is over 1
if ($count === 1 && $cart_item['quantity'] >= 2) {

        // get unit price
        $unit_price = $cart_item['data']->get_price();

        // get quantity to discount (total - 1)
        $discounted_quantity = $cart_item['quantity'] - 1;

        // get total discount amount (on total quantity - 1) 
        $discounted_amount = ($unit_price * $discounted_quantity) * 0.9;

        // add first non discounted price to total discount amount
        $total_discounted_price = $unit_price + $discounted_amount;

        // distribute discount over total quantity and get new unit price 
        $distributed_unit_discount = $total_discounted_price / $cart_item['quantity'];

        // set new unit price
        $cart_item['data']->set_price($distributed_unit_discount);
    }

2018 年 9 月 6 日更新

我在登录用户时遇到了一个奇怪的行为,可能取决于插件之间的一些冲突或我使用的主题 (Avada):折扣应用了两次,所以我不得不阻止此代码添加到我的函数中:

// Set the discounted price on 2nd item and
add_action('woocommerce_before_calculate_totals', 'add_discount_percentage_on_2nd_item', 999, 1);  

function add_discount_percentage_on_2nd_item($cart) {
    if (is_admin() && !defined('DOING_AJAX'))
        return;

if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
    return; 

希望对你有帮助。

【问题讨论】:

    标签: wordpress woocommerce checkout orders discount


    【解决方案1】:

    在购物车对象中,唯一可以真正改变并产生影响的是有效价格
    更改购物车商品中的常规价格或促销价格无效。

    尝试以下操作,这将改变第二个购物车及以后的价格,并且数据将正确传递到 Paypal:

    // Calculate and save as custom cart item data the discounted price
    add_filter('woocommerce_add_cart_item_data', 'add_custom_cart_item_data', 20, 3);
    
    function add_custom_cart_item_data($cart_item_data, $product_id, $variation_id) {
        // HERE set the percentage rate to be applied to get the new price
        $percentage = 10; // 10%
    
        $_product_id = $variation_id > 0 ? $variation_id : $product_id;
    
        $product = wc_get_product($_product_id); // The WC_Product Object
        $base_price = (float) $product->get_price(); // Get the product active price
    
        // Save the calculated discounted price as custom cart item data
        $cart_item_data['discounted_price'] = $base_price * ( 100 - $percentage ) / 100;
    
        return $cart_item_data;
    }
    
    // Set the discounted price on 2nd item and
    add_action('woocommerce_before_calculate_totals', 'add_discount_percentage_on_2nd_item', 20, 1);
    function add_discount_percentage_on_2nd_item($cart) {
        if ( is_admin() && ! defined( 'DOING_AJAX' ) )
            return;
    
        if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
            return;
    
        $count = 0;
    
        // Loop through cart items
        foreach($cart->get_cart() as $cart_item) {
            $count++; // Increasing
    
            // On 2nd cart item or more set the calculated discounted price
            if ($count >= 2 && isset($cart_item['discounted_price']))
                $cart_item['data']->set_price($cart_item['discounted_price']);
        }
    }
    

    代码进入活动子主题(或活动主题)的 function.php 文件中。经过测试并且可以工作。


    附加 - 如果购物车内容数超过 2,则所有商品均可享受折扣。

    您将使用与上面相同的第一个挂钩函数代码。
    您将使用以下内容替换第二个挂钩函数:

    // Set a discounted price on cart items when cart content count is over 2
    add_action('woocommerce_before_calculate_totals', 'add_discount_percentage_on_2nd_item', 20, 1);
    function add_discount_percentage_on_2nd_item($cart) {
        if ( is_admin() && ! defined( 'DOING_AJAX' ) )
            return;
    
        if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
            return;
    
        // Get the total items count
        $total_count = $cart->get_cart_contents_count();
    
        // if total count is below 2 we exit
        if( $total_count < 2 ) 
            return; // Exit
    
        // Loop through cart items
        foreach($cart->get_cart() as $cart_item) {
    
            // Set the calculated discounted price
            if (isset($cart_item['discounted_price']))
                $cart_item['data']->set_price($cart_item['discounted_price']);
        }
    }
    

    代码进入活动子主题(或活动主题)的 function.php 文件中。它应该可以工作。


    加法2

    • 只有第一个购物车商品是全价的,下一个数量的第一个商品打折)
    • 所有蝾螈购物车商品都打折。

    代码:

    // Calculate and save as custom cart item data the discounted price
    add_filter('woocommerce_add_cart_item_data', 'add_custom_cart_item_data', 20, 3);
    
    function add_custom_cart_item_data($cart_item_data, $product_id, $variation_id) {
        // HERE set the percentage rate to be applied to get the new price
        $percentage = 10; // 10%
    
        $_product_id = $variation_id > 0 ? $variation_id : $product_id;
    
        $product = wc_get_product($_product_id); // The WC_Product Object
        $base_price = (float) $product->get_price(); // Get the product active price
    
        // Save the normal active product price as custom cart item data
        $cart_item_data['normal_price'] = $base_price;
    
        // Save the calculated discounted price as custom cart item data
        $cart_item_data['discounted_price'] = $base_price * ( 100 - $percentage ) / 100;
    
        return $cart_item_data;
    }
    
    // Set the discounted price on 2nd item and
    add_action('woocommerce_before_calculate_totals', 'add_discount_percentage_on_2nd_item', 20, 1);
    
    function add_discount_percentage_on_2nd_item($cart) {
        if (is_admin() && !defined('DOING_AJAX'))
            return;
    
        if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
            return; 
    
        // Initializing variables
        $count = 0;
        $first_item = true
    
        // Loop through cart items
        foreach($cart->get_cart() as $cart_item) {
            // 1. First cart item
            if ( isset($cart_item['discounted_price']) && isset($cart_item['normal_price']) && $first_item ){
                if( $cart_item['quantity'] > 1 ){
                    $normal_price   = (float) $cart_item['normal_price'];
                    $discount_price = (float) $cart_item['discounted_price'];
                    $quantity       = (int) $cart_item['quantity'];
    
                    // The first item is at full price and others at discounted price
                    $cart_item['data']->set_price( $normal_price + ( $discount_price * ($quantity - 1) ) );
                }
                $first_item = false; // We switch it to false as it is the first cart item
            }
            // 2. All next items (at discounted price
            elseif ( isset($cart_item['discounted_price']) && ! $first_item ){
                // Set the discounted price
                $cart_item['data']->set_price($cart_item['discounted_price']);
            }
        }
    }
    

    代码进入活动子主题(或活动主题)的 function.php 文件中。它应该可以工作。

    【讨论】:

    • 几乎!我需要保持第一个价格不打折,而其他价格必须打折……这就是为什么我创建了包含在我编辑的问题中的复杂代码。我知道这是一团糟,但客户请求也很复杂。
    • 如果我能更好地解释一下:假设我的购物车中有 2 件产品产品 A - 30 美元产品 B - 100 美元。我有 3 个产品 A1 个产品 B。我的客户需要应用此单价:$30、$27、$27(适用于 产品 A)和 $90(适用于 产品 B )。希望它有助于澄清问题。我的代码,不知道为什么,不能正常工作。提前感谢您的帮助。
    • @YuriRefolo 我在最后(最后一次)再次添加了一些代码。它应该可以按照您的客户的要求工作。
    • 更新:发现一个错误。如果用户登录,则应用两次折扣;如果是客人,折扣适用。我尝试在函数外部设置一个全局计数器,但它不起作用。有什么想法吗?
    • @YuriRefolo 抱歉,我没有这种行为……所以还有其他东西干扰了该代码。我在这两种情况下都测试了这段代码。我有很多类似的答案,我为客户使用类似的代码......所以没有错误。
    【解决方案2】:

    支付网关接受“regular_price”并且您已通过旧价格。
    尝试用新的价格变量设置regular_price,也许它可以工作。

    //update _regular_price
    $wpdb->update( 
        $wpdb->postmeta, 
        array( 'meta_value' => $default_product_price ), 
        array( 'meta_key' => '_regular_price' )
    );

    或者按照上面的代码更新数据库中的价格。这肯定会对你有所帮助。

    【讨论】:

    • 还是一样的价格?
    • 是的,一样不打折
    猜你喜欢
    • 1970-01-01
    • 2019-01-31
    • 2019-06-28
    • 2019-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-24
    • 2019-02-06
    相关资源
    最近更新 更多