How to create custom discount for the cart in woocommerce

I’m creating a Plugin in WooCommerce and have a small issue with adding custom discounts to the CART / CHECKOUT page.

How can I apply custom discount to the cart without creating coupons?
Say I want to give some discount of 5 dollars on the cart page. How can I do that?

Read More

Below is my code from the plugin file where I have used a coupon to apply discount, but I want to add another custom discount without the use of coupon.

Action Hook in the plugin file :

add_action('woocommerce_calculate_totals',array(&$this,'cart_order_total_action'));

and its function in the plugin file is :

public function cart_order_total_action(){
    if ( is_user_logged_in() ){
        global $woocommerce;
        global $current_user;
        global $wpdb;
        $u_id = $current_user->ID;
        $table_name = $wpdb->prefix."woocommerce_customer_reward_ms";
        $thetable2  = $wpdb->prefix . "woocommerce_customer_reward_cart_ms";
        $table_name3 = $wpdb->prefix."woocommerce_customer_reward_points_log_ms";
        $data       = $wpdb->get_row("SELECT * from $table_name where id=$u_id");
        $data2      = $wpdb->get_row("SELECT * from $thetable2");
        /* Order Id goes here */
        $orders=array();//order ids
        $args = array(
            'numberposts'     => -1,
            'meta_key'        => '_customer_user',
            'meta_value'      => $current_user->ID,
            'post_type'       => 'shop_order',
            'post_status'     => 'publish',
            'tax_query'=>array(
                    array(
                        'taxonomy'  =>'shop_order_status',
                        'field'     => 'slug',
                        'terms'     =>'on-hold'
                        )
            )  
        );
        $posts=get_posts($args);
        $orders=wp_list_pluck( $posts, 'ID' );
        $order = $orders[0];
        /* Order Id ends here */
        if($data){
            $user_points = $data->points;
            $points_set  = $data2->woo_pts_set;
            $coupon_code = 'wooreward_discount';
            if($user_points>=$points_set){
                // this following Code is optional and can be removed......as there is no need of if statement here
                if ( $woocommerce->cart->has_discount( $coupon_code ) ) {
                    /*$woocommerce->add_error( __('Coupon Code Already Applied.!!','woocommerce'));*/
                    return false;
                }else{
                    $woocommerce->cart->add_discount(sanitize_text_field($coupon_code));
                    $woocommerce->add_message( __('Taxco925 Reward Discount Applied.!!','woocommerce'));
                }
            }else{
                $woocommerce->add_error( __('Not Enough Taxco925 Points.!!','woocommerce'));
            }
        }else{
            $woocommerce->add_error( __('You have have not earned any Taxco925 Points yet.!!','woocommerce'));
        }
    }
}

As you can see this line $woocommerce->cart->add_discount(sanitize_text_field($coupon_code));
adds my discount to the cart. But it uses coupon in the background to do so . Is there any way I can add a custom discount without the use of coupon.

Related posts

Leave a Reply

4 comments

  1. add_action('woocommerce_checkout_order_processed','custom_disount',10,1);
    function custom_disount($order_id){
        $order = wc_get_order($order_id);
        $order_items = $order->get_items();
        foreach ($order_items as $order_item_key => $order_item) {
            $product = new WC_Product((int) $order_item['product_id']);
            $quantity = (int) $order_item['qty'];
            $discount=($product->regular_price*30)/100;  //30% disount.
            wc_update_order_item_meta($order_item_key,'_line_total',($product->regular_price*$quantity)-($discount*$quantity));
        }
    }
    
  2. You can add discount to each and every product in the cart using “woocommerce_get_discounted_price” hook.
    For Eg.:

    function filter_woocommerce_get_discounted_price( $price, $values, $instance ) { 
    //$price represents the current product price without discount
    //$values represents the product object
    //$instance represent the cart object 
    $discount = 300;    // add custom discount rule , This is just an example
    return ($price - $discount); 
    }; 
     add_filter('woocommerce_get_discounted_price','filter_woocommerce_get_discounted_price', 10, 3 ); 
    
  3. Maybe too late, but If someone have another solution tell me.

    I use something like:

    $discount = floatval(10);
    if(!empty($discount) || $discount != 0){
        $discount *= -1; // convert positive to negative fees
        $woocommerce->cart->add_fee('discount', $discount, true, '' ); // add negative fees
    }
    

    If you use paypal standard payment, you got an error because you can’t submit a product with negative pricing.

    You just need to edit the paypal woocommerce plugin to pass this value.

    But other Payment method is ok!

    Best Regards,

  4. Add fee with negative value will not produce the right total fee.
    Tax is added on the fee amount resulting in higher total fee than expected.

    You need to create a “coupon” and apply it to the cart before you create the order from the cart (it will not calculate right if you apply it on $order directly). Then recalculate the cart->total and finally create an order from the cart, after you have saved the order you can remove the “dynamic” created “coupon” if you want. You can create dynamic coupons with any dynamic $value and of any type (fixed, percent etc etc).

    This is the only way to add discounts in woo3+.
    Fee is doing it wrong when it comes to discounts. Also woo say about fee “Not use negative values here!”.

    I guessed you wanted some example?

    here….

    <?php 
    
    // this code inside wordpress and with woo3+ of course......
    // you have to figure out the rest yourself, how to implement it. but here it is...
    
    $order_data = array (
      'status' => 'on-hold' // or whatever order staus
      // can have more data if need here... 
    );
    
    // below creates a coupon with discount_type = fixed_cart, default.
    $coupon = array (
      'post_title'    => 'coupon_discount',
      'post_status'   => 'publish',
      'post_type'     => 'shop_coupon'
    );
    // can be modified with update_post_meta discount_type = percent and so on....
    
    $dynamic_discount = 20; // yes, just a number can be from another dynamic input source....
    
    $new_coupon_id = wp_insert_post( $coupon ); // add the coupon to the cart
    add_post_meta( $new_coupon_id , 'coupon_amount' , $dynamic_discount , true ); // add the "discount" value ($dynamic_discount)..... depends on discount_type... in this case fixed_cart
    
    WC()->cart->add_to_cart( 2122 , 2 ); // add products, product_id , quantity ..... can be in a loop.
    WC()->cart->add_discount( 'coupon_discount' ); // APPLY THE COUPON WITH DISCOUNT -> This is the trick....
    WC()->cart->calculate_totals(); // do some math on the "cart"
    WC()->checkout(); // yes, checkout the "cart", now with the discount....
    $order_id = WC()->checkout()->create_order( $order_data ); // basic order data, see the top in this script.. get new created order_id.
    $order = wc_get_order( $order_id ); // get the order...
    // can do more with $order here if want, but NOT any coupons... it just not work in $order as is...
    $order->calculate_totals(); // math
    WC()->cart->empty_cart(); // empty cart....
    $order->save(); // save the order...
    
    wp_delete_post( $new_coupon_id , true ); // IF you  want to delete the "dynamic" coupon created above... up 2 u, if not you will end up with a lot of coupons
    
    // sorry, a bad example, uggly code, but at least it work.... :)
    // btw, i like Pattaya, send bitcoins :)
    
    // Again, sorry for uggly code...
    ?>