【问题标题】:Create an order programmatically with line items in Woocommerce 3+在 Woocommerce 3+ 中使用订单项以编程方式创建订单
【发布时间】:2014-12-22 06:31:30
【问题描述】:

我需要以编程方式创建 Woocommerce 订单,但是使用“旧”的 Woocommerce 使这是一个非常肮脏的过程。

我不得不手动插入所有类型的数据库记录,使用许多 update_post_meta 调用。

寻找更好的解决方案。

【问题讨论】:

    标签: php wordpress woocommerce methods orders


    【解决方案1】:

    使用最新版本的 WooCommerce 可以试试这个

    $address = array(
                'first_name' => 'Fresher',
                'last_name'  => 'StAcK OvErFloW',
                'company'    => 'stackoverflow',
                'email'      => 'test@test.com',
                'phone'      => '777-777-777-777',
                'address_1'  => '31 Main Street',
                'address_2'  => '', 
                'city'       => 'Chennai',
                'state'      => 'TN',
                'postcode'   => '12345',
                'country'    => 'IN'
            );
    
            $order = wc_create_order();
            $order->add_product( get_product( '12' ), 2 ); //(get_product with id and next is for quantity)
            $order->set_address( $address, 'billing' );
            $order->set_address( $address, 'shipping' );
            $order->add_coupon('Fresher','10','2'); // accepted param $couponcode, $couponamount,$coupon_tax
            $order->calculate_totals();
    

    使用您的函数调用上面的代码,然后它将相应地工作。

    请注意,它不适用于 2.1.12 等旧版 WooCommerce,它仅适用于 WooCommerce 2.2。

    希望对你有帮助

    【讨论】:

    • 是的,这将绕过 REST API 类。好点子。您可能不必包含任何文件来完成这项工作,对吧?更短的解决方案,还不错!我会尝试并告诉你。
    • 使用这个函数get_class_methods( $order) )看看你有order对象的时候有哪些函数可以使用是非常有帮助的!
    • 不错。我应该打电话给什么来下订单?
    • 根据我所做的这与来宾用户相关联。如何让它与当前登录的用户关联?
    • 我遇到了同样的问题。似乎是某种 API 更改,因为它之前没有与来宾用户相关联。在 calculate_totals() 之后添加以下内容以使其运行($orderId = 新创建订单的 ID,$userId = wp 的客户的用户 ID): update_post_meta( $orderId, '_customer_user', $userId );
    【解决方案2】:

    2017-2021 年适用于 WooCommerce 3 及更高版本

    Woocommerce 3 引入了 CRUD 对象,并且对 Order 项目进行了很多更改……还有一些 WC_Order 方法现在已被弃用,例如 add_coupon()

    这是一个函数,它允许以编程方式很好地创建一个订单,其中包含所有必需的数据,包括税收:

    function create_wc_order( $data ){
        $gateways = WC()->payment_gateways->get_available_payment_gateways();
        $order    = new WC_Order();
    
        // Set Billing and Shipping adresses
        foreach( array('billing_', 'shipping_') as $type ) {
            foreach ( $data['address'] as $key => $value ) {
                if( $type === 'shipping_' && in_array( $key, array( 'email', 'phone' ) ) )
                    continue;
    
                $type_key = $type.$key;
    
                if ( is_callable( array( $order, "set_{$type_key}" ) ) ) {
                    $order->{"set_{$type_key}"}( $value );
                }
            }
        }
    
        // Set other details
        $order->set_created_via( 'programatically' );
        $order->set_customer_id( $data['user_id'] );
        $order->set_currency( get_woocommerce_currency() );
        $order->set_prices_include_tax( 'yes' === get_option( 'woocommerce_prices_include_tax' ) );
        $order->set_customer_note( isset( $data['order_comments'] ) ? $data['order_comments'] : '' );
        $order->set_payment_method( isset( $gateways[ $data['payment_method'] ] ) ? $gateways[ $data['payment_method'] ] : $data['payment_method'] );
    
        $calculate_taxes_for = array(
            'country'  => $data['address']['country'],
            'state'    => $data['address']['state'],
            'postcode' => $data['address']['postcode'],
            'city'     => $data['address']['city']
        );
    
        // Line items
        foreach( $data['line_items'] as $line_item ) {
            $args = $line_item['args'];
            $product = wc_get_product( isset($args['variation_id']) && $args['variation_id'] > 0 ? $$args['variation_id'] : $args['product_id'] );
            $item_id = $order->add_product( $product, $line_item['quantity'], $line_item['args'] );
    
            $item    = $order->get_item( $item_id, false );
    
            $item->calculate_taxes($calculate_taxes_for);
            $item->save();
        }
    
        // Coupon items
        if( isset($data['coupon_items'])){
            foreach( $data['coupon_items'] as $coupon_item ) {
                $order->apply_coupon(sanitize_title($coupon_item['code']));
            }
        }
    
        // Fee items
        if( isset($data['fee_items'])){
            foreach( $data['fee_items'] as $fee_item ) {
                $item = new WC_Order_Item_Fee();
    
                $item->set_name( $fee_item['name'] );
                $item->set_total( $fee_item['total'] );
                $tax_class = isset($fee_item['tax_class']) && $fee_item['tax_class'] != 0 ? $fee_item['tax_class'] : 0;
                $item->set_tax_class( $tax_class ); // O if not taxable
    
                $item->calculate_taxes($calculate_taxes_for);
    
                $item->save();
                $order->add_item( $item );
            }
        }
    
        // Set calculated totals
        $order->calculate_totals();
            
        if( isset($data['order_status']) ) {
            // Update order status from pending to your defined status and save data
            $order->update_status($data['order_status']['status'], $data['order_status']['note']);
            $order_id = $order->get_id();
        } else {
            // Save order to database (returns the order ID)
            $order_id = $order->save();
        }
        
        // Returns the order ID
        return $order_id;
    }
    

    代码进入您的活动子主题(或活动主题)的 function.php 文件或插件文件中。


    使用示例来自数据数组:

    create_wc_order( array(
        'address' => array(
            'first_name' => 'Fresher',
            'last_name'  => 'StAcK OvErFloW',
            'company'    => 'stackoverflow',
            'email'      => 'test1@testoo.com',
            'phone'      => '777-777-777-777',
            'address_1'  => '31 Main Street',
            'address_2'  => '',
            'city'       => 'Chennai',
            'state'      => 'TN',
            'postcode'   => '12345',
            'country'    => 'IN',
        ),
        'user_id'        => '',
        'order_comments' => '',
        'payment_method' => 'bacs',
        'order_status'   => array(
            'status' => 'on-hold',
            'note'   => '',
        ),
        'line_items' => array(
            array(
                'quantity' => 1,
                'args'     => array(
                    'product_id'    => 37,
                    'variation_id'  => '',
                    'variation'     => array(),
                )
            ),
        ),
        'coupon_items' => array(
            array(
                'code'         => 'summer',
            ),
        ),
        'fee_items' => array(
            array(
                'name'      => 'Delivery',
                'total'     => 5,
                'tax_class' => 0, // Not taxable
            ),
        ),
    ) );
    

    【讨论】:

    • 您处理过吗 通知:woocommerce_order_add_product 自 3.0 版起已弃用!使用 woocommerce_new_order_item 操作代替当您调用 add_product 时?
    • @Dan 是的,但它与这个线程无关(它与你的情况有关,取决于你想要做什么)。你应该问一个新问题可能是……
    【解决方案3】:

    随着 WC 2 的新版本,它变得更好了。

    但是:

    • 我不想使用 REST API,因为我直接从我自己的 WP 插件调用。我认为卷曲到我的本地主机没有用
    • WooCommerce REST API Client Library”对我没有用,因为它在 REST API 上中继,并且不支持创建订单调用

    说实话,WooCom 的API Docs 数量有限,可能还在更新中。他们目前没有告诉我如何创建新订单,需要哪些参数等。

    无论如何,我想出了如何使用 REST API 使用的类和函数来创建带有线订单(您的产品)的订单,我想分享它!

    我创建了自己的 PHP 类:

    class WP_MyPlugin_woocommerce
    {
    
    public static function init()
    {
        // required classes to create an order
        require_once WOOCOMMERCE_API_DIR . 'class-wc-api-exception.php';
        require_once WOOCOMMERCE_API_DIR . 'class-wc-api-server.php';
        require_once WOOCOMMERCE_API_DIR . 'class-wc-api-resource.php';
        require_once WOOCOMMERCE_API_DIR . 'interface-wc-api-handler.php';
        require_once WOOCOMMERCE_API_DIR . 'class-wc-api-json-handler.php';
        require_once WOOCOMMERCE_API_DIR . 'class-wc-api-orders.php';
    }
    
    public static function create_order()
    {
        global $wp;
    
        // create order
        $server = new WC_API_Server( $wp->query_vars['wc-api-route'] );
        $order = new WC_API_Orders( $server );
    
        $order_id = $order->create_order( array
        (
            'order'             => array
            (
               'status'            => 'processing'
            ,  'customer_id'       =>  get_current_user_id()
            // ,   'order_meta'        => array
            //     (
            //        'some order meta'         => 'a value
            //     ,   some more order meta'    => 1
            //     )
            ,   'shipping_address'        => array
                (
                    'first_name'          => $firstname
                ,   'last_name'           => $lastname
                ,   'address_1'           => $address
                ,   'address_2'           => $address2
                ,   'city'                => $city
                ,   'postcode'            => $postcode
                ,   'state'               => $state
                ,   'country'             => $country
                )
    
            ,   'billing_address'        => array(..can be same as shipping )
    
            ,   'line_items'        => array
                (
                    array
                    (
                        'product_id'         => 258
                    ,   'quantity'           => 1
                    )
                )
            )
        ) );
        var_dump($order_id);
        die();
    }
    }
    

    重要:

    • “WOOCOMMERCE_API_DIR”常量指向插件目录中的“/woocommerce/includes/api/”。
    • 订单被分配给一个客户,在我的例子中是当前登录的用户。确保您的用户具有能够读取、编辑、创建和删除订单的角色。我的角色如下所示:

         $result = add_role(
          'customer'
      ,   __( 'Customer' )
      ,   array
          (
              'read'         => true
          // ,   'read_private_posts' => true
          // ,   'read_private_products' => true
          ,   'read_private_shop_orders' => true
          ,   'edit_private_shop_orders' => true
          ,   'delete_private_shop_orders' => true
          ,   'publish_shop_orders' => true
          // ,   'read_private_shop_coupons' => true
          ,   'edit_posts'   => false
          ,   'delete_posts' => false
          ,   'show_admin_bar_front' => false
          )
      );
      
    • 如果你想看店长的rights,请查看

      var_dump(get_option('wp_user_roles'));

    我的 create_order 函数很好地创建了一个订单,其中 lineitem 在 order_items 表中。

    希望我能帮到你,我花了一段时间才把它弄好。

    【讨论】:

    【解决方案4】:

    很多答案你都展示了最好的过滤器(钩子)使用。我搜索了几天,因为当我使用“init”时,它不断发出更多订单。在 2 分钟内,我收到了 30 个订单。无论如何使用此代码,将创建 1 个订单。此外,将 $product = wc_get_product('1001') 更改为您的产品 ID。参考在第 144 行:https://github.com/dipolukarov/wordpress/blob/master/wp-content/plugins/woocommerce/classes/class-wc-checkout.php

    function my_init2() {
        $order    = wc_create_order();
        $order_id = $order->get_id();
        
        $product = wc_get_product( '10001' );
        
        $address = array(
            'first_name' => 'John2',
            'last_name'  => 'Smith1',
            'email'      => 'johnsmith1@gmail.com',
        );
        //$order->date_created(2020-07-21 );
        $order->add_product( $product, 1 );
        $order->set_address( $address, 'billing' );
        $order->set_created_via( 'programatically' );
        $order->calculate_totals();
        $order->set_total( $product->get_price() );
        $order->update_status( 'wc-completed' );
        
        error_log( '$order_id: ' . $order_id );
        
    }          
    //add_action('admin_init','my_init2');
    function my_run_only_once() {
     
        if ( get_option( 'my_run_only_once_20' ) != 'completed' ) {
      my_init2();
            update_option( 'my_run_only_once_20', 'completed' );
        }
    }
    add_action( 'admin_init', 'my_run_only_once' );
    
    

    【讨论】:

      猜你喜欢
      • 2018-08-06
      • 1970-01-01
      • 2016-08-12
      • 2019-10-14
      • 2021-03-01
      • 2015-12-09
      • 2013-06-14
      • 2017-01-27
      • 2019-05-05
      相关资源
      最近更新 更多