Conditional add fees to cart

2019-04-25 19:06发布

We have a website that sells computer parts, There's a section in this website called "Assemble your PC" that allows users to choose parts( mainboard - cpu - ram ,etc. ) and pay the price and get their assembled product, everything works just fine, but it needs an option to add an "assembly fee" to cart. This fee should be added only if user goes trough the "Assemble your PC" wizard process. I'm using this code but it adds it to all carts , i mean it's not conditional.

public function calculate_fees( $fees ){
    global $woocommerce;

    $cart_subtotal   = $woocommerce->cart->subtotal;
    $additional_fee = 0; // Additional fee
    $additional_fee_text = __('Assembling fee : ', 'dornaweb');

    if( $_POST['assembly_fee'] === 'flat_assembly_rate' ){
        $additional_fee = intval( dw_option('flat_assembly_rate') ) ?: 0; // flat assembly fee
        $additional_fee_text .= __(' ( assembly, no warranty )', 'dornaweb');
    } elseif( $_POST['assembly_fee'] === 'percentage_assembly_fee' ) {
        $additional_fee = dw_option('percentage_assembly_fee') ? ( ( intval( dw_option('percentage_assembly_fee') ) / 100 ) * $cart_subtotal ) : 0; // percentage assembly fee
        $additional_fee_text .= __(' ( assembly + one year warranty )', 'dornaweb');
    }

    $woocommerce->cart->add_fee( $additional_fee_text, intval( $additional_fee ), 1 );
}

and on the constructor :

add_action( 'woocommerce_cart_calculate_fees', array( $this, 'calculate_fees' ) );

Let me explain a little more about this wizard ( Assemble your PC ) : We have 3 steps in this section,

  • step 1 : user chooses Main board, Ram, Cpu, etc. from existing products.
  • step 2 : sees the list and can change quantity of some products( like Ram )
  • step 3 : user sees the final list with some options that can
    choose in the bottom of the page for assembling fee ( 1. no assembly, just buys the list 2. assembling with one year warranty 3. assembling with no warranty ) and when they hit "submit" , all chosen products get added to cart, this is where we need to add that fee, so this fee should be added only if customer uses this progress.

I also tried adding fees while i add products to cart but it doesn't work this way, when i go to cart page , there's no additional fee in this way

    /* User chooses list of products ( mainboard, ram, ... ) and can  choose quantity of each product 
and also can choose whether he/she wants to get an assembled computer
or just wants to buy the products individually,
then when he/she hits submit products get added to cart all together
in this step assembling fee should be added and calculated in cart total */
if( !empty( $_POST['action'] ) && $_POST['action'] == 'add' ){
      /**
       * Add each product to cart based on user choice
       */
      foreach( $_POST['products'] as $product_id => $data ) {
            WC()->cart->add_to_cart( $product_id, $data['qty'] );
      }

      /**
       * Add additional fees
       */
      WC()->cart->add_fee( 'Assembling fee', 10 ); // 10 is an example , the fee differs depending on user choice ( no assemble:0, assemlby+warranty:5% of the cart subtotal, assembly+no warranty: a flat fee eg. 20$ )
      WC()->cart->calculate_fees();

      /**
       * Redirect to cart
       */
      wp_safe_redirect( WC()->cart->get_cart_url() );
}

1条回答
对你真心纯属浪费
2楼-- · 2019-04-25 19:50

This worked for me, in case some one has the same issue : I set some sessions when products are added to cart, and when the cart gets paid or emptied, I unset those sessions.

if( !empty( $_POST['action'] ) && $_POST['action'] == 'add' ){
   /**
    * Add each product to cart based on user choice
    */
   foreach( $_POST['products'] as $product_id => $data ) {
        WC()->cart->add_to_cart( $product_id, $data['qty'] );
   }

   /**
    * We set sessions after products added to cart
   */
   WC()->session->set( 'MY_SESSION', 'My_value' );

   /**
    * Redirect to cart
    */
   wp_safe_redirect( WC()->cart->get_cart_url() );
}

Now when the customer is redirected to another page( in this case , cart page ) , We can determine his/her cart's additional fee based on that session

function dw_calculate_fees( $cart_object ){
    global $woocommerce;
    if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
    if( ! WC()->session->MY_SESSION ) return;

    $cart_subtotal   = $woocommerce->cart->subtotal;
    $additional_fee = null;

    if( WC()->session->MY_SESSION === 'example_a' ){
        $additional_fee = 1;
    } elseif( WC()->session->MY_SESSION === 'example_b' ) {
        $additional_fee = 2;
    } else{
        $additional_fee = 0;
    }

    if( ! is_null( $additional_fee ) ) {
        $woocommerce->cart->add_fee( 'Additional fee ', intval( $additional_fee ), 1 );
    }
}
add_action( 'woocommerce_cart_calculate_fees', 'dw_calculate_fees' );

and we need to unset those sessions when the cart is paid or gets emptied :

add_action( 'woocommerce_cart_emptied', 'dw_unset_fee_session' );
function dw_unset_fee_session(){
    unset( WC()->session->MY_SESSION );
}

This worked for me, please share with me, if something is wrong about it.

查看更多
登录 后发表回答