Рассчитать способы/ставки доставки в рамках существующего заказа в WooCommerce

По сути, я пытаюсь воспроизвести функциональность, например, на странице корзины, где пользователь может добавить свои zip code, и он рассчитывает доступные тарифы на доставку, но я пытаюсь сделать это из бэк-энда из уже созданного заказа.

Я не смог найти способ сделать это непосредственно из экземпляра WC_Order, поэтому следующее лучшее, что у меня есть, это очистить сеанс корзины, добавить все элементы из заказа в сеанс корзины, а затем попытаться вычислить его.

Вот что у меня есть до сих пор. Я всегда застрял на том, как рассчитать ставки для всего заказа.

$order_id       = isset($_POST['order_id'])?$_POST['order_id']:0;
$country        = isset($_POST['country'])?$_POST['country']:0;
$state          = isset($_POST['state'])?$_POST['state']:0;
$postcode       = isset($_POST['postcode'])?$_POST['postcode']:0;
$city           = isset($_POST['city'])?$_POST['country']:0;
$order          = wc_get_order( $order_id );
$order_items    = $order->get_items();

// Don't know if this would save country of logged in user, or only create a temporary guest user session which is what I'd need
if ( $country != '' ) {
    WC()->customer->set_billing_location( $country, $state, $postcode, $city );
    WC()->customer->set_shipping_location( $country, $state, $postcode, $city );
} else {
    WC()->customer->set_billing_address_to_base();
    WC()->customer->set_shipping_address_to_base();
}

// Remove all current items from cart
if ( sizeof( WC()->cart->get_cart() ) > 0 ) {
    WC()->cart->empty_cart();
}

// Add all items from the order to the cart
foreach ($order_items as $order_item) {
    WC()->cart->add_to_cart($order_item['product_id'], $order_item['qty']);
}

$totals = WC()->shipping->get_packages();

// $totals returns rates but I believe it is per each "package". It's not a cumulative rate like the cart page shows.

person zen    schedule 13.03.2019    source источник
comment
Проверьте это   -  person mujuonly    schedule 19.03.2019


Ответы (3)


Итак, благодаря @mujuonly я смог это понять.

Вот как получить все рассчитанные тарифы на доставку так же, как они показаны на странице корзины.

// Post variables
$order_id   = isset($_POST['order_id'])?$_POST['order_id']:0;
$country    = isset($_POST['country'])?$_POST['country']:0;
$state      = isset($_POST['state'])?$_POST['state']:0;
$postcode   = isset($_POST['postcode'])?$_POST['postcode']:0;
$city       = isset($_POST['city'])?$_POST['city']:0;

// Order and order items
$order          = wc_get_order( $order_id );
$order_items    = $order->get_items();

// Reset shipping first
WC()->shipping()->reset_shipping();

// Set correct temporary location
if ( $country != '' ) {
    WC()->customer->set_billing_location( $country, $state, $postcode, $city );
    WC()->customer->set_shipping_location( $country, $state, $postcode, $city );
} else {
    WC()->customer->set_billing_address_to_base();
    WC()->customer->set_shipping_address_to_base();
}

// Remove all current items from cart
if ( sizeof( WC()->cart->get_cart() ) > 0 ) {
    WC()->cart->empty_cart();
}

// Add all items to cart
foreach ($order_items as $order_item) {
    WC()->cart->add_to_cart($order_item['product_id'], $order_item['qty']);
}

// Calculate shipping
$packages = WC()->cart->get_shipping_packages();
$shipping = WC()->shipping->calculate_shipping($packages);
$available_methods = WC()->shipping->get_packages();

$available_methods[0]['rates'] будут указаны все тарифы на доставку, доступные в этом месте для продуктов внутри заказа.

person zen    schedule 19.03.2019
comment
Можете ли вы отправить полный код из корзины для этого решения? - person upss1988; 23.06.2020
comment
Есть ли шанс, что вы могли бы поделиться тем, как вы это реализовали, чтобы другие могли сделать то же самое со своим сервером WC? - person inspirednz; 10.04.2021
comment
@inspirednz был реализован как плагин для управления ручными заказами в бэкенде. - person zen; 13.04.2021

Попробуйте использовать:

// Calculate totals
WC()->cart->calculate_totals();
WC()->cart->calculate_shipping();

// Retrieve the shipping total
$shipping_total = WC()->cart->get_shipping_total();

Класс WC_Cart должен иметь все методы, необходимые для воссоздания любой функциональности корзины, которая может вам понадобиться. Я предлагаю вам прочитать и ознакомиться с определением класса здесь...

https://docs.woocommerce.com/wc-apidocs/class-WC_Cart.html

person BA_Webimax    schedule 18.03.2019

Примечание: это не ответ, я не могу комментировать, поэтому пишу здесь. В моем случае есть проблема с принятым ответом:

Если покупатель уже добавил какие-то товары в корзину, они будут потеряны из-за следующей строки кода:

WC()->cart->empty_cart()

и вместо этого корзина заполняется товарами из прошлого заказа.

До сих пор кажется, что использование корзины необходимо для правильного расчета отгрузочных пакетов. Если да, то есть ли способ создать клон текущей корзины, а затем рассчитать доставку? Я не хочу влиять на исходную корзину моего клиента при выполнении этого расчета.

person Abhishek    schedule 11.11.2019
comment
Мой вопрос и ответ относятся к расчету способов доставки из серверной части WordPress. Таким образом, обычно это делают только администраторы или управляющие участники, и в этом случае очистка корзины не имеет значения, потому что она не будет опорожнять корзину пользователей, чьи способы доставки вы пытаетесь рассчитать. Он очищает корзину пользователя, вошедшего в систему. Я бы попробовал что-то вроде $cart_contents = WC()->cart->get_cart_contents(), затем WC()->cart->empty_cart() и всю остальную логику, и, наконец, WC()->cart->set_cart_contents($cart_contents). Не проверял. - person zen; 13.11.2019