为 WooCommerce 购物车中的每个项目创建单独的订单

问题描述:

我基本上需要能够为购物车中的每件商品创建多个订单,但保留默认的结帐流程.

I basically need to be able to create multiple orders for every item in the cart but retain the default checkout process.

对于用户来说,看起来他们正在结账多个项目,但在后端,它会创建多个订单.我找到了一篇文章,其中几乎与我需要做的事情相关.

To the user, it would look like they are checking out with multiple items but in the backend, it would create multiple orders. I found an article which pretty much relates what I need to do.

我假设我需要删除点击立即付款按钮时触发的操作,以防止自动创建订单并手动创建订单.我可以使用以下过滤器访问购物车信息,这可能是一个起点?

I would assume I would need to remove the action that is triggered when clicking the pay now button, preventing the order from being created automatically and create the orders manually. I can access the cart information using the following filter, perhaps this would be a starting point?

add_filter( 'woocommerce_checkout_create_order', 'wp_handle_multiple_orders', 10, 1 );
function wp_handle_multiple_orders( $order ) {
global $woocommerce;
print_r(count(WC()->cart->get_cart()));

// Handle creation of multiple orders

}

或者我可能会进入 checkout_process :

Or perhaps I hook into the checkout_process:

add_action( 'woocommerce_checkout_process', 'wp_handle_multiple_orders' ) );

我知道这个过程并不理想,有很多不同的事情需要考虑,但希望有一种替代方法可以实现这一目标.任何链接将不胜感激!

I am aware this process isn't ideal and there are many different things to consider but hopefully, there is an alternative way of achieving this. Any links would be appreciated!

这个答案包含:

  • 仅保留原始订单中的 1 个产品,从此订单中删除其他产品.
  • 将已移除的产品(每个单独)按新顺序放置.
  • 通过添加到代码中的注释标签进行解释,如果需要,可以轻松地进一步扩展代码
function action_woocommerce_checkout_order_processed( $order_id, $posted_data, $order ) {   
    // Get order currency
    $order_currency = $order->get_currency();

    // Get order payment method
    $order_payment_gateway = $order->get_payment_method();
    
    // Address
    $order_address = array(
        'first_name' => $order->get_billing_first_name(),
        'last_name'  => $order->get_billing_last_name(),
        'email'      => $order->get_billing_email(),
        'phone'      => $order->get_billing_phone(),
        'address_1'  => $order->get_billing_address_1(),
        'address_2'  => $order->get_billing_address_2(),
        'city'       => $order->get_billing_city(),
        'state'      => $order->get_billing_state(),
        'postcode'   => $order->get_billing_postcode(),
        'country'    => $order->get_billing_country()
    );

    // Shipping
    $order_shipping = array(
        'first_name' => $order->get_shipping_first_name(),
        'last_name'  => $order->get_shipping_last_name(),
        'address_1'  => $order->get_shipping_address_1(),
        'address_2'  => $order->get_shipping_address_2(),
        'city'       => $order->get_shipping_city(),
        'state'      => $order->get_shipping_state(),
        'postcode'   => $order->get_shipping_postcode(),
        'country'    => $order->get_shipping_country()
    );
    
    // Counter
    $counter = 1;

    // Loop through order items
    foreach ( $order->get_items() as $item_id => $item ) {
        // From the 2nd product
        if ( $counter >= 2 ) {
            // Get the WC_Product Object
            $product = $item->get_product();
            
            // Get product quantity
            $product_quantity = $item->get_quantity();
            
            // Create new order
            $new_order = wc_create_order();
            
            // Add product to new order
            $new_order->add_product( $product, $product_quantity );
            
            // Set addresses
            $new_order->set_address( $order_address, 'billing' );
            $new_order->set_address( $order_shipping, 'shipping' );

            // Set the correct currency and payment gateway
            $new_order->set_currency( $order_currency );
            $new_order->set_payment_method( $order_payment_gateway );

            // Calculate totals
            $new_order->calculate_totals();

            // Set order note with original ID
            $new_order->add_order_note( 'Automated order. Created from the original order ID: ' . $order_id );
            
            // Set correct status
            $new_order->update_status( 'processing' );

            // Delete product from original order
            $order->remove_item( $item_id );
        }
        
        // Counter = counter + 1
        $counter++;
    }
    
    // Re-calculate & save
    $order->calculate_totals();
    $order->save();
}
add_action( 'woocommerce_checkout_order_processed', 'action_woocommerce_checkout_order_processed', 10, 3 );