fix(api): add fallback and debug to calculate_shipping
When WC packages array is empty, manually calculate rates by: 1. Get zone matching the shipping address 2. Call get_rates_for_package() on each method 3. Or fallback to method title/cost for simple methods like Free Shipping Also added debug info to response to help diagnose issues.
This commit is contained in:
@@ -1503,14 +1503,14 @@ class OrdersController {
|
||||
|
||||
// Get available shipping packages and rates
|
||||
$packages = WC()->shipping()->get_packages();
|
||||
$methods = [];
|
||||
$rates = [];
|
||||
|
||||
foreach ( $packages as $package_key => $package ) {
|
||||
$rates = $package['rates'] ?? [];
|
||||
$package_rates = $package['rates'] ?? [];
|
||||
|
||||
foreach ( $rates as $rate_id => $rate ) {
|
||||
foreach ( $package_rates as $rate_id => $rate ) {
|
||||
/** @var \WC_Shipping_Rate $rate */
|
||||
$methods[] = [
|
||||
$rates[] = [
|
||||
'id' => $rate_id,
|
||||
'method_id' => $rate->get_method_id(),
|
||||
'instance_id' => $rate->get_instance_id(),
|
||||
@@ -1522,12 +1522,65 @@ class OrdersController {
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: If no rates from packages, manually calculate from matching zone
|
||||
if ( empty( $rates ) && ! empty( $shipping['country'] ) ) {
|
||||
$package = [
|
||||
'destination' => [
|
||||
'country' => $shipping['country'] ?? '',
|
||||
'state' => $shipping['state'] ?? '',
|
||||
'postcode' => $shipping['postcode'] ?? '',
|
||||
'city' => $shipping['city'] ?? '',
|
||||
],
|
||||
'contents' => WC()->cart->get_cart(),
|
||||
'contents_cost' => WC()->cart->get_subtotal(),
|
||||
'applied_coupons' => WC()->cart->get_applied_coupons(),
|
||||
'user' => [ 'ID' => get_current_user_id() ],
|
||||
];
|
||||
|
||||
$zone = \WC_Shipping_Zones::get_zone_matching_package( $package );
|
||||
if ( $zone ) {
|
||||
foreach ( $zone->get_shipping_methods( true ) as $method ) {
|
||||
if ( method_exists( $method, 'get_rates_for_package' ) ) {
|
||||
$method_rates = $method->get_rates_for_package( $package );
|
||||
foreach ( $method_rates as $rate_id => $rate ) {
|
||||
$rates[] = [
|
||||
'id' => $rate_id,
|
||||
'method_id' => $rate->get_method_id(),
|
||||
'instance_id' => $rate->get_instance_id(),
|
||||
'label' => $rate->get_label(),
|
||||
'cost' => (float) $rate->get_cost(),
|
||||
'taxes' => $rate->get_taxes(),
|
||||
'meta_data' => $rate->get_meta_data(),
|
||||
];
|
||||
}
|
||||
} else {
|
||||
// Fallback for methods without get_rates_for_package (like Free Shipping)
|
||||
$method_id = $method->id . ':' . $method->instance_id;
|
||||
$rates[] = [
|
||||
'id' => $method_id,
|
||||
'method_id' => $method->id,
|
||||
'instance_id' => $method->instance_id,
|
||||
'label' => $method->get_title(),
|
||||
'cost' => $method->id === 'free_shipping' ? 0 : (float) ($method->cost ?? 0),
|
||||
'taxes' => [],
|
||||
'meta_data' => [],
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up
|
||||
WC()->cart->empty_cart();
|
||||
|
||||
return new \WP_REST_Response( [
|
||||
'methods' => $methods,
|
||||
'has_methods' => ! empty( $methods ),
|
||||
'methods' => $rates, // Keep as 'methods' for frontend compatibility
|
||||
'has_methods' => ! empty( $rates ),
|
||||
'debug' => [
|
||||
'packages_count' => count( $packages ),
|
||||
'cart_items_count' => count( WC()->cart->get_cart() ),
|
||||
'address' => $shipping,
|
||||
],
|
||||
], 200 );
|
||||
|
||||
} catch ( \Throwable $e ) {
|
||||
|
||||
Reference in New Issue
Block a user