I'm trying to add estimated delivery times to orders on the checkout page, under the shipping price within WooCommerce.
I have worked out how to do this, such as:
add_action( 'woocommerce_after_shipping_rate', 'blm_action_after_shipping_rate', 20, 2 );
function blm_action_after_shipping_rate ( $method, $index ) {
if( is_cart() ) {
return; // Exit on cart page
}
// Use $method->method_id in here to check delivery option
}
Now, to be able to estimate the days (unfortunately the shipping API doesn't return this data) I need to find out the shipping country and shipping state/province in here - is there a way to do that?
The shipping rates are calculated from customer shipping location.
So you asked for the customer shipping country and state that you can get from WC_Customer object using dedicated methods as follows:
add_action( 'woocommerce_after_shipping_rate', 'blm_action_after_shipping_rate', 20, 2 );
function blm_action_after_shipping_rate ( $method, $index ) {
if( is_cart() ) {
return; // Exit on cart page
}
$shipping_country = WC()->customer->get_shipping_country();
$shipping_state = WC()->customer->get_shipping_state();
// Testing output
echo '<br><small>Country code:' . $shipping_country . ' | State code: ' . $shipping_state . '</small>';
}
Code goes in function.php file of the active child theme (or active theme). Tested and works.
If customer change of country and state, the data is refreshed and the new country and state are set in WC_Customer Object.
Related
I would like to set a message to specific shipping class in Woocommerce checkout page.
I tried using:
add_action( 'woocommerce_review_order_before_order_total', 'cart_items_shipping_class_message', 20, 1 );
function cart_items_shipping_class_message( $cart ){
$shipping_class_id = 14; // Your shipping class Id
// Loop through cart items
foreach( WC()->cart->get_cart() as $cart_item ){
// Check cart items for specific shipping class, displaying a notice
//if( $cart_item['data']->get_shipping_class_id() == $shipping_class_id ){
var_dump($cart_item['data']->get_shipping_class_id());
echo "Do poznámky k objednávce napište adresu Zásilkovny nebo ZBoxu, kam chcete objednávku doručit.";
//break;
//}
}
}
But when I try to var_dump selected shipping class, it always returns me int(0).
I have used something similar to: Cart Message for a Specific Shipping Class in WooCommerce, because It did not work for me.
The Cart Message for a Specific Shipping Class in WooCommerce answer still works on last woocommerce version.
Your question code works and display the shipping class Id… So there is something else that is making trouble.
Be sure that a cart item has the required shipping class set for it.
Try following to display a message in checkout based for specific shipping class slug:
add_action( 'woocommerce_review_order_before_order_total', 'checkout_shipping_class_message' );
function checkout_shipping_class_message(){
// Here your shipping class slugs in the array
$shipping_classes = array('truck');
// Here your shipping message
$message = __("Please add some shipping details in order notes field.", "woocommerce");
// Loop through cart items
foreach( WC()->cart->get_cart() as $cart_item ){
$shipping_class = $cart_item['data']->get_shipping_class();
// echo '<pre>' . print_r($shipping_class, true) . '</pre>'; // Uncomment for testing
// Check cart items for specific shipping class, displaying a message
if( in_array($shipping_class, $shipping_classes ) ){
echo '<tr class="shipping-note">
<td colspan="2"><strong>'.__("Note", "woocommerce").':</strong> '.$message.'</td>
</tr>';
break;
}
}
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.
Prefacing this question, I know that there might be other ways to accomplish the goal, but I'm trying to understand how Woocommerce works a bit better, so the situation is I have a plugin that can change the cost of shipping depending on the products in the cart, but I want to change the name of the shipping fee depending on the cost.
From what I found in the HTML the current structure of the shipping method looks like this:
<td data-title="Shipping">
<ul id="shipping_method" class="shipping__list woocommerce-shipping-methods">
<li class="shipping__list_item">
<input type="hidden" name="shipping_method[0]" data-index="0" id="shipping_method_0_flat_rate24" value="flat_rate:24" class="shipping_method" /><label class="shipping__list_label" for="shipping_method_0_flat_rate24">Flat Rate Shipping Fee: <span class="woocommerce-Price-amount amount"><bdi><span class="woocommerce-Price-currencySymbol">$</span>10.00</bdi></span></label>
</li>
</ul>
I'm attempting to create a function for the functions.php file of my Wordpress theme, I looked up some code on google and found a similar function involving "$available_shipping_methods" but I wasn't too sure how to use that variable so what I currently have is this:
add_filter('woocommerce_package_rates', 'wc_shipping_rate_rename', 100, 2)
function wc_shipping_rate_rename($rates, $package){
//Checking if the shipping rate exists
if ( isset( $rates['flat_rate:24'] ) ) {
//Getting the rate
$ship_cost = $rates['flat_rate:24']->cost;
if ( $ship_cost == 10) {
$rates['flat_rate:24'] -> 'Subsidized shipping fee:';
}
if ( $ship_cost == 100) {
$rates['flat_rate:24'] -> 'Flat rate shipping fee:';
}
}
return $rates;
}
The goal would be change the part in the HTML that says "Flat Rate Shipping Fee:" depending on the cost of the shipping fee. Any help would be really appreciated.
For a specific shipping rate Id, to change the shipping rate displayed label based on its cost use:
add_filter('woocommerce_package_rates', 'custom_shipping_rate_label_based_on_cost', 100, 2)
function custom_shipping_rate_label_based_on_cost( $rates, $package ){
// Here your targeted shipping rate Id
$targeted_rate_id = 'flat_rate:24';
// Loop through available shipping rates
foreach ( $rates as $rate_key => $rate ) {
// Targetting specific rate Id
if( $targeted_rate_id === $rate_key ) {
$rate_cost = $rate->cost;
if ( $rate_cost < 100 ) {
$rate_label = __('Subsidized shipping fee');
}
elseif ( $rate_cost >= 100 ) {
$rate_label = __('Flat rate shipping fee');
}
if ( isset($rate_label) ) {
$rates[$rate_key]->label = $rate_label;
}
}
}
return $rates;
}
Code goes in functions.php file of your active child theme (or active theme). It should works.
Clearing shipping caches:
You will need to empty your cart, to clear cached shipping data
Or In shipping settings, you can disable / save any shipping method, then enable back / save.
Here's what I want to do:
If customer selects Canada as shipping country and there's a specific product in cart, checkout should not happen and an error message should generate informing customer of why checkout didn't happen.
My research:
Add or remove woocommerce error messages has code to generate WooCommerce error messages. I asked a question yesterday that gave me codes to check if certain product is in cart and if shipping country is set to Canada Remove Canada from country list when specific products are in cart on Woocommerce I am not sure which filter/action I must hook my code to so it runs whenever "Place Order" is clicked on checkout page.
Update:
So I tried combining the two codes I have listed in my research but it didn't work. Any help if I need to approach this differently will be really appreciated
Product IDs are 15631 & 12616
This can be done using the action hook woocommerce_check_cart_items through this custom function:
add_action( 'woocommerce_check_cart_items', 'products_not_shipable_in_canada' );
function products_not_shipable_in_canada() {
// Only on checkout page (allowing customer to change the country in cart shipping calculator)
if( ! is_checkout() ) return;
// Set your products
$products = array(15631, 12616);
// Get customer country
$country = WC()->session->get('customer')['shipping_country'];
if( empty($country) ){
$country = WC()->session->get('customer')['billing_country'];
}
// For CANADA
if( $country == 'CA' ){
// Loop through cart items
foreach( WC()->cart->get_cart() as $item ){
// IF product is in cart
if( in_array( $item['product_id'], $products ) ){
// Avoid checkout and display an error notice
wc_add_notice( sprintf(
__("The product %s can't be shipped to Canada, sorry.", "woocommerce" ),
'"' . $item['data']->get_name() . '"'
), 'error' );
break; // Stop the loop
}
}
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
Related: Set minimum allowed weight for a specific country in WooCommerce
I am trying to update the shipping cost after the address is entered. When the client starts typing the address, and autocomplete function helps the client find the street name, building, floor, and side.
Once the address is entered JavaScript calculates the distance and the price.
Then the price is via AJAX send to shipment.php
It is my goal to have shipment update the shipping cost accordingly.
I have tried:
include '../../../../wp-load.php';
add_action( 'woocommerce_flat_rate_shipping_add_rate','add_another_custom_flat_rate', 10, 2 );
function add_another_custom_flat_rate( $method, $rate ) {
$new_rate = $rate;
$new_rate['cost'] = 50; // Update the cost to 50
$method->add_rate( $new_rate );
}
But without luck.
I have also following this guide and added another shipping method: Tuts
https://code.tutsplus.com/tutorials/create-a-custom-shipping-method-for-woocommerce--cms-26098
But once again, I cannot update the price once the address is entered.
I think that You don't need Query ajax to update the price directly for this calculated shipping cost and you don't need a custom shipping method as in your code or linked tutorial.
THERE IS THREE STEPS:
1) In your existing Ajax driven PHP function, you will set the calculated price in a custom WC_Session attribute where $shipping_cost variable will be the collected value of the calculated shipping cost passed via JS Ajax:
WC()->session->set( 'shipping_calculated_cost', $shipping_cost );
Then in jQuery Ajax "on success" event you will update checkout with the following:
$('body').trigger('update_checkout');
That will refresh checkout data…
2) In the custom function hooked in woocommerce_package_rates filer hook, you will get the session value of the calculated shipping cost…
IMPORTANT: In WooCommerce settings > shipping, you will set the "flat rate" cost to 1…
In The function code you will set the default price for this flat rate (that will be used when the shipping cost calculation doesn't exist yet):
add_filter('woocommerce_package_rates', 'update_shipping_costs_based_on_cart_session_custom_data', 10, 2);
function update_shipping_costs_based_on_cart_session_custom_data( $rates, $package ){
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return $rates;
// SET HERE the default cost (when "calculated cost" is not yet defined)
$cost = '50';
// Get Shipping rate calculated cost (if it exists)
$calculated_cost = WC()->session->get( 'shipping_calculated_cost');
// Iterating though Shipping Methods
foreach ( $rates as $rate_key => $rate_values ) {
$method_id = $rate_values->method_id;
$rate_id = $rate_values->id;
// For "Flat rate" Shipping" Method only
if ( 'flat_rate' === $method_id ) {
if( ! empty( $calculated_cost ) ) {
$cost = $calculated_cost;
}
// Set the rate cost
$rates[$rate_id]->cost = number_format($rates[$rate_id]->cost * $cost, 2);
// Taxes rate cost (if enabled)
foreach ($rates[$rate_id]->taxes as $key => $tax){
if( $rates[$rate_id]->taxes[$key] > 0 ){ // set the new tax cost
$taxes[$key] = number_format( $rates[$rate_id]->taxes[$key] * $cost, 2 );
$has_taxes = true;
} else {
$has_taxes = false;
}
}
if( $has_taxes )
$rates[$rate_id]->taxes = $taxes;
}
}
return $rates;
}
Code goes in function.php file of your active child theme (or active theme) or in any plugin file.
3) Refresh the shipping caches (needed sometimes):
First empty your cart.
This code is already saved on your function.php file.
Go in a shipping zone settings and disable one "flat rate" (for example) and "save". Then re-enable that "flat rate" and "save". You are done and you can test it.
This should work for you,
If you have many different "flat rates" by shipping zones, you will need to make some changes in my code, if the default cost is different for each…
I have a woocommerce website and I have set 2 shipping methods:
Flat Rate
Local pickup
I would like to set the "Flat rate" shipping method as default (selected) in the cart or checkout page.
1) You can use the following code (to set "flat rate" shipping method as default) In cart page:
add_action( 'woocommerce_before_cart', 'set_default_chosen_shipping_method', 5 );
function set_default_chosen_shipping_method(){
//
if( count( WC()->session->get('shipping_for_package_0')['rates'] ) > 0 ){
foreach( WC()->session->get('shipping_for_package_0')['rates'] as $rate_id =>$rate)
if($rate->method_id == 'flat_rate'){
$default_rate_id = array( $rate_id );
break;
}
WC()->session->set('chosen_shipping_methods', $default_rate_id );
}
}
Code goes in function.php file of your active child theme (active theme or in any plugin file).
Tested and Works in WooCommerce 3+
2) You can also reorder the shipping rates in your shipping zones settings (but it doesn't really works as the last chosen shipping method take the hand).
You could use the following code to set 'any' shipping method as default.
function reset_default_shipping_method( $method, $available_methods ) {
$default_method = 'wf_fedex_woocommerce_shipping:FEDEX_GROUND'; //provide the service name here
if( array_key_exists($method, $available_methods ) )
return $default_method;
else
return $method;
}
Let's say, you're using a Carrier shipping plugin like WooCommerce FedEx Shipping Plugin. You can fetch the value Id (shown below) and paste it under the '$default_method' in the above code.
You will have to copy and paste the code in WordPress Dashboard->Appearance–>Editor–>functions.php of your theme.
Hope that helped. :)
copy the value Id from here