diff --git a/includes/Api/OrdersController.php b/includes/Api/OrdersController.php index 39e7b90..01e7731 100644 --- a/includes/Api/OrdersController.php +++ b/includes/Api/OrdersController.php @@ -872,8 +872,65 @@ class OrdersController { ], 'shipping' ); } - // Shipping method line (parse id:instance if provided) + // Shipping method - calculate using WooCommerce cart for accurate rates if ( $shipping_method ) { + // Initialize cart if needed + if ( ! WC()->cart ) { + wc_load_cart(); + } + if ( ! WC()->session ) { + WC()->session = new \WC_Session_Handler(); + WC()->session->init(); + } + + // Temporarily use cart to calculate shipping + WC()->cart->empty_cart(); + + // Add items to cart + foreach ( $items as $row ) { + $pid = absint( $row['product_id'] ?? 0 ); + $qty = max( 1, absint( $row['qty'] ?? 1 ) ); + if ( $pid ) { + WC()->cart->add_to_cart( $pid, $qty ); + } + } + + // Set shipping address for calculation + if ( $ship_addr ) { + WC()->customer->set_shipping_country( $ship_addr['country'] ?? '' ); + WC()->customer->set_shipping_state( $ship_addr['state'] ?? '' ); + WC()->customer->set_shipping_postcode( $ship_addr['postcode'] ?? '' ); + WC()->customer->set_shipping_city( $ship_addr['city'] ?? '' ); + WC()->customer->set_shipping_address( $ship_addr['address_1'] ?? '' ); + } + + // Set chosen shipping method + WC()->session->set( 'chosen_shipping_methods', [ $shipping_method ] ); + + // Calculate shipping + WC()->cart->calculate_shipping(); + WC()->cart->calculate_totals(); + + // Get the calculated rate + $packages = WC()->shipping()->get_packages(); + $shipping_cost = 0; + $shipping_title = $shipping_method; + $shipping_taxes = []; + + foreach ( $packages as $package ) { + if ( isset( $package['rates'][ $shipping_method ] ) ) { + $rate = $package['rates'][ $shipping_method ]; + $shipping_cost = $rate->get_cost(); + $shipping_title = $rate->get_label(); + $shipping_taxes = $rate->get_taxes(); + break; + } + } + + // Clean up cart + WC()->cart->empty_cart(); + + // Parse method ID and instance ID $method_id = $shipping_method; $instance_id = null; if ( strpos( $shipping_method, ':' ) !== false ) { @@ -881,36 +938,7 @@ class OrdersController { $instance_id = absint( $instance_str ); } - // Get shipping method cost - $shipping_cost = 0; - $shipping_title = $method_id; - - if ( $instance_id ) { - // Get shipping zone and method instance - $zones = \WC_Shipping_Zones::get_zones(); - foreach ( $zones as $zone ) { - foreach ( $zone['shipping_methods'] as $method ) { - if ( $method->id === $method_id && $method->instance_id == $instance_id ) { - $shipping_cost = $method->get_option( 'cost', 0 ); - $shipping_title = $method->get_title(); - break 2; - } - } - } - - // Check zone 0 (rest of the world) - if ( $shipping_cost == 0 ) { - $zone = new \WC_Shipping_Zone( 0 ); - foreach ( $zone->get_shipping_methods() as $method ) { - if ( $method->id === $method_id && $method->instance_id == $instance_id ) { - $shipping_cost = $method->get_option( 'cost', 0 ); - $shipping_title = $method->get_title(); - break; - } - } - } - } - + // Add shipping line item $ship_item = new \WC_Order_Item_Shipping(); $ship_item->set_method_id( $method_id ); if ( null !== $instance_id && method_exists( $ship_item, 'set_instance_id' ) ) { @@ -918,6 +946,12 @@ class OrdersController { } $ship_item->set_method_title( $shipping_title ); $ship_item->set_total( $shipping_cost ); + + // Set shipping taxes if available + if ( ! empty( $shipping_taxes ) ) { + $ship_item->set_taxes( [ 'total' => $shipping_taxes ] ); + } + $order->add_item( $ship_item ); }