I have create hook action
do_action('wpyoug_update_price');
add_action('wpyoug_update_price', 'wpyoug_update_woocommerce_price');
function wpyoug_update_woocommerce_price(){
global $totalshipCharge;
add_action( 'woocommerce_cart_calculate_fees', 'cp_add_custom_price' );
}
When I echo inside wpyoug_update_woocommerce_price() function it return . but add_action( 'woocommerce_cart_calculate_fees', 'cp_add_custom_price' ); is not working
function cp_add_custom_price(){
global $woocommerce;
$thiscarttotal = WC()->cart->get_cart_total();
$thiscarttotal = preg_replace('/$/', '', $thiscarttotal);
$woocommerce->cart->add_fee( __('Miscellaneous Handling Fee', 'woocommerce'), 10 );
}
// Hook before adding fees
add_action('woocommerce_cart_calculate_fees' , 'add_custom_fees');
function add_custom_fees( WC_Cart $cart ){
$fees = 0.08;
$cart->add_fee( 'Handling fee', $fees);
}
add_action( 'woocommerce_cart_calculate_fees','xa_add_surcharge' );
function xa_add_surcharge() {
global $woocommerce;
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
$surcharge = 5;
$woocommerce->cart->add_fee( 'Surcharge', $surcharge, true, '' );
}
From here
Related
I would like to hide some payment method and enable another one when I select a specified “Shipping Method" in flexible Shipping plugin form wpdesk.
I have already tried that code:
add_filter( 'woocommerce_available_payment_gateways', 'gateway_disable_shipping_326' );
function gateway_disable_shipping_326( $available_gateways ) {
global $woocommerce;
if ( !is_admin() ) {
$chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
$chosen_shipping = $chosen_methods[0];
if ( isset( $available_gateways['payment_method_cod'] ) && 0 === strpos( $chosen_shipping, 'flat_rate:6' ) ) {
unset( $available_gateways['payment_method_cod'] );
}
}
return $available_gateways;
}
and this one
function my_custom_available_payment_gateways( $gateways ) {
$chosen_shipping_rates = WC()->session->get( 'chosen_shipping_methods' );
if ( in_array( 'flat_rate:6', $chosen_shipping_rates ) ) :
unset( $gateways['payment_method_cod'] );
endif;
if ( in_array( 'flat_rate:8', $chosen_shipping_rates ) ) :
unset( $gateways['payment_method_przelewy24'] );
endif;
return $gateways;
}
add_filter( 'woocommerce_available_payment_gateways', 'my_custom_available_payment_gateways' );
The link to my website: [www.dajati.pl][1]
The following code example will enable / disable payment gateways based on chosen shipping method.
In this example, we have 3 shipping methods and 3 payment gateways. Each selected shipping method will enable only one different payment gateway.
add_filter( 'woocommerce_available_payment_gateways', 'payment_gateways_based_on_chosen_shipping_method' );
function payment_gateways_based_on_chosen_shipping_method( $available_gateways ) {
// Not in backend (admin) and Not in order pay page
if( is_admin() || is_wc_endpoint_url('order-pay') )
return $available_gateways;
// Get chosen shipping methods
$chosen_shipping_methods = (array) WC()->session->get( 'chosen_shipping_methods' );
if ( in_array( 'flat_rate:12', $chosen_shipping_methods ) )
{
unset( $gateways['bacs'] );
unset( $gateways['cod'] );
}
elseif ( in_array( 'flat_rate:14', $chosen_shipping_methods ) )
{
unset( $gateways['bacs'] );
unset( $gateways['paypal'] );
}
elseif ( in_array( 'free_shipping:10', $chosen_shipping_methods ) )
{
unset( $gateways['cod'] );
unset( $gateways['paypal'] );
}
return $gateways;
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
To be able to get the correct shipping method ID you can use your browser inspector, this way:
Since I was looking for solution to this also, and LoicTheAztec's answer were removing all payments, here is a slightly modified working solution.
add_filter( 'woocommerce_available_payment_gateways', 'payment_gateways_based_on_chosen_shipping_method' );
function payment_gateways_based_on_chosen_shipping_method( $available_gateways ) {
// Not in backend (admin) and Not in order pay page
if( is_admin() || is_wc_endpoint_url('order-pay') )
return $available_gateways;
// Get chosen shipping methods
$chosen_shipping_methods = (array) WC()->session->get( 'chosen_shipping_methods' );
if ( in_array( 'flat_rate:12', $chosen_shipping_methods ) )
{
unset( $available_gateways['bacs'] );
unset( $available_gateways['cod'] );
}
elseif ( in_array( 'flat_rate:14', $chosen_shipping_methods ) )
{
unset( $available_gateways['bacs'] );
unset( $available_gateways['paypal'] );
}
elseif ( in_array( 'free_shipping:10', $chosen_shipping_methods ) )
{
unset( $available_gateways['cod'] );
unset( $available_gateways['paypal'] );
}
return $available_gateways;
}
The only difference is that all $gateways had to be changed to $available_gateways, or vice versa.
I fonud function that rounds the total, but can't understand how to make it work only if BACS payment checked on checkout page.
add_filter( 'woocommerce_calculated_total', 'custom_calculated_total' );
function custom_calculated_total( $total ) {
$total = round( $total, 1 );
return ceil($total);
}
If someone will need, I found solution:
add_filter( 'woocommerce_calculated_total', 'custom_calculated_total' );
function custom_calculated_total( $total ) {
if( WC()->session->get( 'chosen_payment_method' ) == 'bacs' )
{
$total = round( $total, 1 );
$total = ceil( $total );
}
return $total;
}
The woocommerce_calculated_total hook is documented here:
I can add a product to cart, when a certain coupon is used via the woocommerce_applied_coupon hook and the add_to_cart() function
add_action('woocommerce_applied_coupon', 'apply_product_on_coupon');
function apply_product_on_coupon( ) {
global $woocommerce;
$coupon_id = 'mybday';
$free_product_id = 131468;
if(in_array($coupon_id, $woocommerce->cart->get_applied_coupons())){
$woocommerce->cart->add_to_cart($free_product_id, 1);
}
}
My question: is there a way to also discount it to 0 in the same callback function?
Your current code contains some mistakes or could be optimized:
global $woocommerce can be replaced by WC()
$woocommerce->cart->get_applied_coupons() is not necessary, as the coupon that have been applied is passed to the callback function.
Instead, use the last available argument in WC_Cart::add_to_cart() method, which will allow you to add any custom cart item data. Then you will be able to get that data easily from the cart object.
So you get:
function action_woocommerce_applied_coupon( $coupon_code ) {
// Settings
$product_id = 131468;
$quantity = 1;
$free_price = 0;
$coupon_codes = array( 'coupon1', 'mybday' );
// Compare
if ( in_array( $coupon_code, $coupon_codes ) ) {
// Add product to cart
WC()->cart->add_to_cart( $product_id, $quantity, 0, array(), array( 'free_price' => $free_price ) );
}
}
add_action( 'woocommerce_applied_coupon', 'action_woocommerce_applied_coupon', 10, 1 );
// Set free price from custom cart item data
function action_woocommerce_before_calculate_totals( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return;
// Loop through cart contents
foreach ( $cart->get_cart_contents() as $cart_item ) {
if ( isset( $cart_item['free_price'] ) ) {
$cart_item['data']->set_price( $cart_item['free_price'] );
}
}
}
add_action( 'woocommerce_before_calculate_totals', 'action_woocommerce_before_calculate_totals', 10, 1 );
Note: in addition to using woocommerce_applied_coupon, you must also use woocommerce_removed_coupon for when the coupon is removed, the product is removed as well
function action_woocommerce_removed_coupon( $coupon_code ) {
// Settings
$product_id = 131468;
$coupon_codes = array( 'coupon1', 'mybday' );
// Compare
if ( in_array( $coupon_code, $coupon_codes ) ) {
// Loop through cart contents
foreach ( WC()->cart->get_cart_contents() as $cart_item_key => $cart_item ) {
// When product in cart
if ( $cart_item['product_id'] == $product_id ) {
// Remove cart item
WC()->cart->remove_cart_item( $cart_item_key );
break;
}
}
}
}
add_action( 'woocommerce_removed_coupon', 'action_woocommerce_removed_coupon', 10, 1 );
I'm using Add fee to Woocommerce Shipping Class without the use of zones or flat rate answer code, that allows me add an additional 'Fee' if any product from the 'Dangerous Goods' shipping class has been added to cart.
This is great as it allows me to cover the additional costs associated to packaging/shipping, however it is also adding the 'fee' when users select 'Local Pickup' shipping option.
I would love to exclude 'Local Pickup' from the additional fee if selected.
Therefore i use:
function fees_fees_fees() {
$shippingClasses['dangerous-goods'] = ['description' => 'Dangerous Goods Fee', 'fee' => 130];
foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
$shipping_class = get_the_terms( $values['product_id'], 'product_shipping_class' );
foreach($shippingClasses as $key => $val) {
if ( isset( $shipping_class[0]->slug ) && in_array( $shipping_class[0]->slug, [$key] ) ) {
WC()->cart->add_fee( __($val['description'], 'woocommerce'), $val['fee'] ); }
}
}
}
add_action( 'woocommerce_cart_calculate_fees', 'fees_fees_fees' );
However, I'm stuck on the next step. Any adivce?
The use of WC()->cart is not necessary, as $cart is already passed to the callback function
WC()->session->get( 'chosen_shipping_methods' ) can be used to get the chosen shipping method, then it is a matter of adding an if condition
So you get:
function action_woocommerce_cart_calculate_fees( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
// Get chosen shipping method
$chosen_shipping_methods = WC()->session->get( 'chosen_shipping_methods' );
$chosen_shipping_method = substr( $chosen_shipping_methods[0], 0, strpos( $chosen_shipping_methods[0], ':' ) );
// NOT for local pickup
if ( $chosen_shipping_method != 'local_pickup' ) {
// Settings
$shipping_classes['dangerous-goods'] = [ 'description' => 'Dangerous Goods Fee', 'fee' => 130 ];
// Loop though cart items
foreach ( $cart->get_cart() as $cart_item ) {
$shipping_class = get_the_terms( $cart_item['product_id'], 'product_shipping_class' );
foreach ( $shipping_classes as $key => $val ) {
if ( isset( $shipping_class[0]->slug ) && in_array( $shipping_class[0]->slug, [$key] ) ) {
$cart->add_fee( __( $val['description'], 'woocommerce' ), $val['fee'] );
}
}
}
}
}
add_action( 'woocommerce_cart_calculate_fees', 'action_woocommerce_cart_calculate_fees', 10, 1 );
Simply add check to slug.
if ( isset( $shipping_class[0]->slug ) && in_array( $shipping_class[0]->slug, [$key] ) && $shipping_class[0]->slug != 'local_pickup') {
I need to automatically set a certain order status (different than processing) when getting a new order.
This is achieved by this function:
add_action('woocommerce_thankyou','change_order_status');
function change_order_status( $order_id ) {
if ( ! $order_id ) { return; }
$order = wc_get_order( $order_id );
if( 'processing'== $order->get_status() ) {
$order->update_status( 'wc-custom-status' );
}
}
This totally works. Now I only need this to happen when a product has a customization.
The way to customize a product is filling an input field before adding to cart. The input is attached to the item data:
// Add custom cart item data
add_filter( 'woocommerce_add_cart_item_data', 'add_custom_cart_item_data', 10, 2 );
function add_custom_cart_item_data( $cart_item_data, $product_id ){
if( isset($_POST['custom_text']) ) {
$cart_item_data['custom_text'] = sanitize_text_field( $_POST['custom_text'] );
$cart_item_data['unique_key'] = md5( microtime().rand() ); // Make each item unique
}
return $cart_item_data;
}
Then the custom text is retrieved and displayed in cart and in the order data using this:
// Display custom cart item data on cart and checkout
add_filter( 'woocommerce_get_item_data', 'display_custom_cart_item_data', 10, 2 );
function display_custom_cart_item_data( $cart_item_data, $cart_item ) {
if ( !empty( $cart_item['custom_text'] ) ){
$cart_item_data[] = array(
'name' => __('Customization', 'woocommerce'),
'value' => $cart_item['custom_text'] // Already sanitized field
);
}
return $cart_item_data;
}
// Save and display custom item data everywhere on orders and email notifications
add_action( 'woocommerce_checkout_create_order_line_item', 'add_product_custom_field_as_order_item_meta', 10, 4 );
function add_product_custom_field_as_order_item_meta( $item, $cart_item_key, $values, $order ) {
if ( isset($values['custom_text']) ) {
$item->update_meta_data('Add on', $values['custom_text'] );
}
}
I'm trying using the if ( isset($values['custom_text']) ) part as a trigger of the function to change the order status only if the product add on is set and other similar methods (like if ( !empty( $cart_item['custom_text'] ) ) but I'm not sure this is the way to go:
add_action('woocommerce_thankyou','change_order_status');
function change_order_status( $order_id ) {
if ( ! $order_id ) {return;}
$order = wc_get_order( $order_id );
if ( isset($values['custom_text']) ) {
if( 'processing'== $order->get_status() ) {
$order->update_status( 'wc-custom-status' );
}
}
}
This above does nothing. Am I anywhere near it with this approach?
EDIT: I tried this too
add_action('woocommerce_thankyou','change_order_status');
function change_order_status( $order_id ) {
if ( ! $order_id ) {return;}
$order = wc_get_order( $order_id );
foreach ( $order->get_items() as $item_id => $item ) {
$allmeta = $item->get_meta_data();
if ( isset($values['custom_text']) ) {
if( 'processing'== $order->get_status() ) {
$order->update_status( 'wc-custom-status' );
}
}
}
}
Your code contains some unnecessary steps as well as some shortcomings
For example, the woocommerce_add_cart_item_data hook contains 3 arguments versus 2
So you get:
// Add custom cart item data
function filter_add_cart_item_data( $cart_item_data, $product_id, $variation_id ) {
// Isset and NOT empty
if ( isset ( $_POST[ 'custom_text' ] ) && ! empty ( $_POST[ 'custom_text' ] ) ) {
$cart_item_data['custom_text'] = sanitize_text_field( $_POST['custom_text'] );
}
return $cart_item_data;
}
add_filter( 'woocommerce_add_cart_item_data', 'filter_add_cart_item_data', 10, 3 );
// Display custom cart item data on cart and checkout
function filter_woocommerce_get_item_data( $cart_data, $cart_item = null ) {
if ( isset ( $cart_item['custom_text'] ) ) {
$cart_data[] = array(
'name' => __( 'Customization', 'woocommerce' ),
'value' => $cart_item['custom_text']
);
}
return $cart_data;
}
add_filter( 'woocommerce_get_item_data', 'filter_woocommerce_get_item_data', 10, 2 );
// Add the information as meta data so that it can be seen as part of the order
// Save and display custom item data everywhere on orders and email notifications
function action_woocommerce_checkout_create_order_line_item( $item, $cart_item_key, $values, $order ) {
if ( isset ( $values['custom_text'] ) ) {
$item->update_meta_data( 'custom_text', $values['custom_text'] );
}
}
add_action( 'woocommerce_checkout_create_order_line_item', 'action_woocommerce_checkout_create_order_line_item', 10, 4 );
// On thankyou page
function action_woocommerce_thankyou( $order_id ) {
// Get $order object
$order = wc_get_order( $order_id );
// Is a WC_Order
if ( is_a( $order, 'WC_Order' ) ) {
// Only when the current order status is 'processing'
if ( $order->get_status() == 'processing' ) {
// Loop trough
foreach ( $order->get_items() as $item ) {
// Get meta
$value = $item->get_meta( 'custom_text' );
// NOT empty
if ( ! empty ( $value ) ) {
// Update status (change to desired status)
$order->update_status( 'cancelled' );
// Stop loop
break;
}
}
}
}
}
add_action( 'woocommerce_thankyou', 'action_woocommerce_thankyou', 10, 1 );
Currently it is just checking if the value exists, to compare it effectively
Change
// NOT empty
if ( ! empty ( $value ) ) {
// Update status
$order->update_status( 'cancelled' );
// Stop loop
break;
}
To
// Compare
if ( $value == 'some value' ) ) {
// Update status
$order->update_status( 'cancelled' );
// Stop loop
break;
}