Автоматически добавляйте или обновляйте пользовательскую комиссию с помощью редактирования заказов администратором в WooCommerce.

У нас есть особый случай, когда мы выставляем нашим клиентам счет на оплату после получения заказа, вместо того, чтобы заставлять их платить во время оформления заказа. Стоимость доставки рассчитывается вручную и добавляется к заказу, а затем мы добавляем комиссию кредитной карты в размере 3% от общей суммы.

Чтобы автоматизировать этот процесс, я создал скрипт, который вычисляет комиссию в размере 3% после того, как стоимость доставки была установлена ​​через серверную часть, и автоматически добавляет эту позицию в заказ. Это работает, когда мы добавим стоимость доставки и нажмем кнопку «Сохранить/пересчитать» в первый раз.

add_action( 'woocommerce_order_after_calculate_totals', "custom_order_after_calculate_totals", 10, 2);
function custom_order_after_calculate_totals($and_taxes, $order) {

    if ( did_action( 'woocommerce_order_after_calculate_totals' ) >= 2 )
    return;

    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    $percentage = 0.03;
    $total = $order->get_total();
    $surcharge = $total * $percentage;
    $feeArray = array(
        'name' => '3% CC Fee',
        'amount' =>  wc_format_decimal($surcharge),
        'taxable' => false,
        'tax_class' => ''
    );

    //Get fees
    $fees = $order->get_fees();
    if(empty($fees)){
        //Add fee
        $fee_object = (object) wp_parse_args( $feeArray );
        $order->add_fee($fee_object);
    } else {
        //Update fee
        foreach($fees as $item_id => $item_fee){
            if($item_fee->get_name() == "3% CC Fee"){
                $order->update_fee($item_id,$feeArray);
            }
        }
    }
}

Если мы случайно добавим неправильную стоимость доставки и попытаемся обновить ее, этот код снова сработает и обновит плату, однако $total не получит новую сумму заказа из обновленной стоимости доставки, поэтому плата не изменится. Как ни странно, если я пытаюсь удалить пункт сбора, рассчитывается новый сбор и добавляется обратно с правильной суммой сбора.

Кто-нибудь знает, как я могу это решить?


person ZeroNine    schedule 10.01.2021    source источник


Ответы (1)


Поскольку вы используете общую сумму заказа для расчета комиссии, а используемая вами ловушка находится внутри метода calculate_totals(), после обновления заказа вам всегда нужно будет нажимать кнопку пересчета, чтобы получить правильную общую сумму комиссии и правильный общая сумма заказа гран с правильной суммой.

Начиная с WooCommerce 3 ваш код устарел и немного устарел с некоторыми ошибками… Например, add_fee() и update_fee() устарели и заменены некоторыми другими способами.

Вместо этого используйте следующее:

add_action( 'woocommerce_order_after_calculate_totals', "custom_order_after_calculate_totals", 10, 2 );
function custom_order_after_calculate_totals( $and_taxes, $order ) {
    if ( did_action( 'woocommerce_order_after_calculate_totals' ) >= 2 )
        return;

    $percentage = 0.03; // Fee percentage

    $fee_data   = array(
        'name'       => __('3% CC Fee'),
        'amount'     => wc_format_decimal( $order->get_total() * $percentage ),
        'tax_status' => 'none',
        'tax_class'  => ''
    );

    $fee_items  = $order->get_fees(); // Get fees

    // Add fee
    if( empty($fee_items) ){
        $item = new WC_Order_Item_Fee(); // Get an empty instance object

        $item->set_name( $fee_data['name'] );
        $item->set_amount( $fee_data['amount'] );
        $item->set_tax_class($fee_data['tax_class']);
        $item->set_tax_status($fee_data['tax_status']);
        $item->set_total($fee_data['amount']);

        $order->add_item( $item );
        $item->save(); // (optional) to be sure
    }
    // Update fee
    else {
        foreach ( $fee_items as $item_id => $item ) {
            if( $item->get_name() === $fee_data['name'] ) {
                $item->set_amount($fee_data['amount']);
                $item->set_tax_class($fee_data['tax_class']);
                $item->set_tax_status($fee_data['tax_status']);
                $item->set_total($fee_data['amount']);
                $item->save();
            }
        }
    }
}

Код находится в файле functions.php активной дочерней темы (или активной темы). Проверено и работает.

После обновления заказа и после нажатия кнопки пересчета (чтобы получить правильную сумму заказов) как автоматически добавленная, так и обновленная плата будут работать хорошо.

Связанный: Добавить комиссию к заказу программно в Woocommerce 3


Обновить

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

add_action( 'woocommerce_order_after_calculate_totals', "custom_order_after_calculate_totals", 10, 2 );
function custom_order_after_calculate_totals( $and_taxes, $order ) {
    if ( did_action( 'woocommerce_order_after_calculate_totals' ) >= 2 )
        return;

    $percentage = 0.03; // Fee percentage

    $fee_data   = array(
        'name'       => __('3% CC Fee'),
        'amount'     => wc_format_decimal( $order->get_total() * $percentage ),
        'tax_status' => 'none',
        'tax_class'  => ''
    );

    $fee_items  = $order->get_fees(); // Get fees

    // Add fee
    if( empty($fee_items) ){
        $item = new WC_Order_Item_Fee(); // Get an empty instance object

        $item->set_name( $fee_data['name'] );
        $item->set_amount( $fee_data['amount'] );
        $item->set_tax_class($fee_data['tax_class']);
        $item->set_tax_status($fee_data['tax_status']);
        $item->set_total($fee_data['amount']);

        $order->add_item( $item );
        $item->save(); // (optional) to be sure
    }
    // Update fee
    else {
        foreach ( $fee_items as $item_id => $item ) {
            if( $item->get_name() === $fee_data['name'] ) {
                $item->remove_item( $item_id ); // Remove the item

                $item = new WC_Order_Item_Fee(); // Get an empty instance object

                $item->set_name( $fee_data['name'] );
                $item->set_amount( $fee_data['amount'] );
                $item->set_tax_class($fee_data['tax_class']);
                $item->set_tax_status($fee_data['tax_status']);
                $item->set_total($fee_data['amount']);

                $order->add_item( $item );
                $item->save(); // (optional) to be sure
            }
        }
    }
}
person LoicTheAztec    schedule 10.01.2021
comment
Я видел, что эти старые методы устарели, но не мог понять, как сделать это обновленным способом, поэтому спасибо вам за это и за объяснение хука. Я обновил код, но проблема осталась. Я обновляю стоимость доставки и нажимаю Сохранить. Затем нажмите Обновить. Затем нажмите «Пересчитать». Плата остается прежней. Единственный способ обновить плату — удалить плату и позволить ей автоматически восстановиться. - person ZeroNine; 10.01.2021
comment
@ZeroNine Извините, но у меня нет такого поведения с кодом, который я предоставил, используя последнюю версию WooCommerce в теме Storefront. Так что есть еще кое-что, что создает проблемы в вашем случае. Это может быть плагин, ваша тема или другой код, созданный вами. - person LoicTheAztec; 10.01.2021
comment
@ZeroNine Я добавил для вас обновление, которое удаляет элемент для обновления и добавляет обновленный элемент… Попробуйте. Если этот ответ отвечает на ваш вопрос, вы можете принять ответ, и если вам нравится/хотите, вы также можете проголосуйте и за ответ, спасибо. - person LoicTheAztec; 10.01.2021