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:
Dwindi Ramadhana
2026-01-08 10:01:06 +07:00
parent ab0eb3ab28
commit 068fbe3a26

View File

@@ -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 ) {