2

I'm working on a custom plugin that processes order data & sends it to another Web application.

I hook in to order processing using WooCommerce's woocommerce_checkout_order_processed hook, so, I get the order id as an argument & hence can easily obtain WC_Order.

The problem I got stuck with is the following:
I want to calculate some data based on the shipping method chosen by the customer, but I need more data than just the shipping method name in order to perform the calculation.

A simplified version of what I want to achieve is essentially something very similar to:

$order = wc_get_order($order_id);

$is_express_shipping = strpos($order->get_shipping_method(), 'Express') !== false;

But the whole problem is that the shipping method name does not contain (and in fact, it should not) any hint regarding whether it is an express shipping method or not, so, the only option is to pass some additional information about the shipping method through.

I've tried to add a custom shipping method as described in this question & in its accepted answer, so, I added the desired data into shipping method settings like this:

enter image description here

But it looks like WooCommerce doesn't expect custom shipping classes to register custom fields or at least, I didn't figure out how to get the Launch Simple Shipping's "Shipping Mode" property from within the order object (it does not appear anywhere within $order->get_shipping_methods() output).

Here is the full code of the custom shipping class in case if needed. It's a copy-paste from the previously mentioned question + a new field.

function launch_shipping_method() {
    if (!class_exists('Launch_Shipping_Method')) {

        class Launch_Shipping_Method extends WC_Shipping_Method {

            public function __construct( $instance_id = 0 ) {
                $this->id = 'launch_shipping';
                $this->instance_id          = absint( $instance_id );
                $this->method_title         = __('Launch Simple Shipping', 'launch_shipping');
                $this->method_description   = __('Custom Simple Shipping Method', 'launch_shipping');
                $this->supports             = array(
                    'shipping-zones',
                    'instance-settings',
                    'instance-settings-modal',
                );

                $this->init();
            }

            /**
                * Initialize Launch Simple Shipping.
                */
            public function init() {
                // Load the settings.
                $this->init_form_fields();
                $this->init_settings();

                // Define user set variables.
                $this->title    = isset($this->settings['title']) ? $this->settings['title'] : __('Launch Shipping', 'launch_shipping');
                $this->shipping_mode    = isset($this->settings['shipping_mode']) ? $this->settings['shipping_mode'] : __('Launch Shipping', 'launch_shipping');

                add_action('woocommerce_update_options_shipping_' . $this->id, array($this, 'process_admin_options'));
            }

            /**
                * Init form fields.
                */
            public function init_form_fields() {
                $this->form_fields = array(
                    'title'      => array(
                        'title'         => __( 'Title', 'launch_shipping' ),
                        'type'          => 'text',
                        'description'   => __( 'This controls the title which the user sees during checkout.', 'launch_shipping' ),
                        'default'       => $this->method_title,
                        'desc_tip'      => true,
                    ),
                    'shipping_mode'      => array(
                        'title'         => __( 'Shipping Mode', 'launch_shipping' ),
                        'type'          => 'select',
                        'default'       => 'Standard',
                        'options' => [
                            'Standard' => 'Standard',
                            'Express' => 'Express',
                        ],
                    )
                );
            }

            /**
                * Get setting form fields for instances of this shipping method within zones.
                *
                * @return array
                */
            public function get_instance_form_fields() {
                return parent::get_instance_form_fields();
            }

            /**
                * Always return shipping method is available
                *
                * @param array $package Shipping package.
                * @return bool
                */
            public function is_available( $package ) {
                $is_available = true;
                return apply_filters( 'woocommerce_shipping_' . $this->id . '_is_available', $is_available, $package, $this );
            }

            /**
                * Free shipping rate applied for this method.
                *
                * @uses WC_Shipping_Method::add_rate()
                *
                * @param array $package Shipping package.
                */
            public function calculate_shipping( $package = array() ) {
                $this->add_rate(
                    array(
                        'label'   => $this->title,
                        'cost'    => 0,
                        'taxes'   => false,
                        'package' => $package,
                        'shipping_mode' => $this->shipping_mode,
                    )
                );
            }
        }
    }
}
add_action('woocommerce_shipping_init', 'Launch_Shipping_Method');

function add_launch_shipping_method($methods) {
    $methods['launch_shipping'] = 'launch_shipping_method';
    return $methods;
}

add_filter('woocommerce_shipping_methods', 'add_launch_shipping_method');

Is there a way to somehow pass additional data about the chosen shipping method into WC_Order object or somehow obtain it having WC_Order at hand?

Igor Bykov
  • 2,532
  • 3
  • 11
  • 19
  • Check this answer - [How to get custom shipping method packages from WooCommerce](https://stackoverflow.com/questions/65965961/how-to-get-custom-shipping-method-packages-from-woocommerce) and this [Add a shipping to an order programmatically in Woocommerce 3](https://stackoverflow.com/questions/53671945/add-a-shipping-to-an-order-programmatically-in-woocommerce-3) – Bhautik Jun 07 '21 at 20:13
  • @Bhautik Thank you for the info! [This one is probably the closest to what I need](https://stackoverflow.com/a/46106700/9430588), however, it only outputs some ids + tax & price but no custom fields, while putting the unrelated data into tax/price fields only because they are available out of the box seems like a nonoptimal solution to me. – Igor Bykov Jun 07 '21 at 20:24
  • What kinda custom fields are you trying to get? - Check this one too - [Extra carrier field for shipping methods in WooCommerce cart and checkout](https://stackoverflow.com/questions/63191513/extra-carrier-field-for-shipping-methods-in-woocommerce-cart-and-checkout) – Bhautik Jun 07 '21 at 20:27
  • @Bhautik Ideally, I'd like to be able to get the `shipping_mode`'s value set in my custom shipping method from `$order->get_shipping_methods()` output or from somewhere else. – Igor Bykov Jun 07 '21 at 20:32
  • Did you try to search `shipping mode` in the database? so that you can find out even they are saving custom data to order? – Bhautik Jun 07 '21 at 20:35
  • @Bhautik yes, I did. However, I'm pretty unsure about where to search. I read in an answer (that I will not be able to find now) that settings are stored in `wp_options` (with keys like `woocommerce_*_instance_*_settings`), but they are stored based on some instances which don't make the thing clearer, unfortunately. – Igor Bykov Jun 07 '21 at 20:45
  • What do you think about this ? At checkout use `woocommerce_after_checkout_validation` to figure out if what shipping is selected and store it the woocommerce session `->` when the user has successfully paid use `woocommerce_thankyou` to check if session has your data and save it inside the order using `$order->update_meta_data( 'custom_data', 'value' );`. @IgorBykov – bhanu Jun 07 '21 at 21:16
  • And its quite simple to get the data using `$order->get_meta( 'custom_data' )` which you can use to fetch data that you want. Let me know if you think this is vaible solution or not, and if you would like help writing this code. !! @IgorBykov – bhanu Jun 07 '21 at 21:19
  • @Bhanu Unfortunately `woocommerce_after_checkout_validation` does not provide any way to get the desired info. – Igor Bykov Jun 09 '21 at 17:56

0 Answers0