I'm creating a custom shipping calculator for my WooCommerce store. I need to collect some extra form data from the user to calculate the shipping properly.
I have the form fields added to woocommerce_checkout_after_customer_details
. I can probably get this into the cart page without much trouble once I figure out the checkout page functionality, so let's focus on this.
I have a class extending WC_Shipping_Method
with a calculate_shipping
method a la this tutorial.
In that method, I want to use the extra form data (plus the destination) to calculate the shipping for that customer. Right now I just have this adding a dummy rate, which shows up.
I also created a custom cart-shipping.php
file to not show any inputs for the available method in the order review cart, just the label and cost. Since the picking happens in my custom form, having options here is unnecessary.
calculate_shipping
method?Have tried
Named the final options in my custom form shipping_method_*
which triggers the wc-ajax=update_order_review
call... which inits my custom shipping method class, but does not appear to ever call the calculate_shipping
method anyhow. The only time this method seems to be called is when I'm actually adding a product to the order.
Also tried
Defined all of my possible delivery options and added them in calculate_shipping like $this->add_rate( $rate );
. I think then I can somehow select one (force the user into one) when the cart updates via update_order_review
ajax call? Again, the set option should be determined by these fields the user interacts with on the checkout form. But I haven't figured out how to set the shipping on that action yet.
Just go to any field in the Edit Section. You can find there a Required Field option. Simply mark or unmark this checkbox. This way you can set default WooCommerce fields as not required.
calculate_shipping()
is not always calledFirst off, you should know that the calculate_shipping()
method of your shipping method class will only be called when the shipping rates are calculated for the first time (in the current WooCommerce session), each time after a product is added to the cart, and whenever the shipping address is changed — from the cart or checkout page.
But of course, a plugin or custom code can programmatically call the method (or re-calculate the rates) at any times. However, the default behavior is as follows:
Rates are stored in the session based on the package hash to avoid re-calculation every page load.
And the calculate_shipping()
method is executed by the WC_Shipping
class through its calculate_shipping_for_package()
method. In fact, the above quote was taken from the description of WC_Shipping::calculate_shipping_for_package()
which calls WC_Shipping_Method::get_rates_for_package()
and eventually the calculate_shipping()
method in your own class.
calculate_shipping()
methodSo if you have this in the checkout form:
<input type="text" name="my_field"...>
Then you can get the submitted (POST
ed) value using either the $_POST
superglobal or the WC_Checkout::get_value()
method:
$_POST['my_field']
WC()->checkout->get_value( 'my_field' )
It's as simple as that. :)
To ensure calculate_shipping is called
Run something similar to the following to clear out the session information, which will indicate that calculation still needs to be done. Be aware that if you do this on every page, it will mean that the shipping is constantly being recalculated when it doesn't need to be.
$packages = WC()->cart->get_shipping_packages();
foreach( $packages as $package_key => $package ) {
$session_key = 'shipping_for_package_'.$package_key;
$stored_rates = WC()->session->__unset( $session_key );
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With