简体   繁体   English

Wordpress(Woocommerce扩展) - 以编程方式创建新订单

[英]Wordpress (Woocommerce extension) - Create new order programmatically

I want to create a new order programmatically. 我想以编程方式创建新订单。

Workflow is simple: After submitting simple form, user will be created and along with that, a new order. 工作流程很简单:提交简单表单后,将创建用户以及新订单。

I managed to create a new user and user_id is returned, now I need to assign a new order all in one step. 我设法创建了一个新用户并返回了user_id,现在我需要一步一步地分配一个新订单。

How can I accomplish this? 我怎么能做到这一点?

Here's how I programmatically create my orders. 这是我以编程方式创建订单的方式。 I largely followed WC_Checkout::create_order() from @pavel's suggestion above. 我很大程度上遵循上面@ pavel建议的WC_Checkout :: create_order()。 This is directly from a plugin I'm writing so you'll have to adjust where the source data comes form. 这是直接来自我正在编写的插件,因此您必须调整源数据的来源。

// build order data
$order_data = array(
    'post_name'     => 'order-' . date_format($order_date, 'M-d-Y-hi-a'), //'order-jun-19-2014-0648-pm'
    'post_type'     => 'shop_order',
    'post_title'    => 'Order – ' . date_format($order_date, 'F d, Y @ h:i A'), //'June 19, 2014 @ 07:19 PM'
    'post_status'   => 'wc-completed',
    'ping_status'   => 'closed',
    'post_excerpt'  => $order->note,
    'post_author'   => $account->user_id,
    'post_password' => uniqid( 'order_' ),   // Protects the post just in case
    'post_date'     => date_format($order_date, 'Y-m-d H:i:s e'), //'order-jun-19-2014-0648-pm'
    'comment_status' => 'open'
);

// create order
$order_id = wp_insert_post( $order_data, true );

if ( is_wp_error( $order_id ) ) {

    $order->errors = $order_id;

} else {

    $order->imported = true;

    // add a bunch of meta data
    add_post_meta($order_id, 'transaction_id', $order->transaction_id, true); 
    add_post_meta($order_id, '_payment_method_title', 'Import', true);
    add_post_meta($order_id, '_order_total', $order->gross, true);
    add_post_meta($order_id, '_customer_user', $account->user_id, true);
    add_post_meta($order_id, '_completed_date', date_format( $order_date, 'Y-m-d H:i:s e'), true);
    add_post_meta($order_id, '_order_currency', $order->currency, true);
    add_post_meta($order_id, '_paid_date', date_format( $order_date, 'Y-m-d H:i:s e'), true);

    // billing info
    add_post_meta($order_id, '_billing_address_1', $order->address_line_1, true);
    add_post_meta($order_id, '_billing_address_2', $order->address_line_2, true);
    add_post_meta($order_id, '_billing_city', $order->city, true);
    add_post_meta($order_id, '_billing_state', $order->state, true);
    add_post_meta($order_id, '_billing_postcode', $order->zip, true);
    add_post_meta($order_id, '_billing_country', $order->country, true);
    add_post_meta($order_id, '_billing_email', $order->from_email, true);
    add_post_meta($order_id, '_billing_first_name', $order->first_name, true);
    add_post_meta($order_id, '_billing_last_name', $order->last_name, true);
    add_post_meta($order_id, '_billing_phone', $order->phone, true);

    // get product by item_id
    $product = get_product_by_sku( $order->item_id );

    if( $product ) {

        // add item
        $item_id = wc_add_order_item( $order_id, array(
            'order_item_name'       => $product->get_title(),
            'order_item_type'       => 'line_item'
        ) );

        if ( $item_id ) {

            // add item meta data
            wc_add_order_item_meta( $item_id, '_qty', 1 ); 
            wc_add_order_item_meta( $item_id, '_tax_class', $product->get_tax_class() );
            wc_add_order_item_meta( $item_id, '_product_id', $product->ID );
            wc_add_order_item_meta( $item_id, '_variation_id', '' );
            wc_add_order_item_meta( $item_id, '_line_subtotal', wc_format_decimal( $order->gross ) );
            wc_add_order_item_meta( $item_id, '_line_total', wc_format_decimal( $order->gross ) );
            wc_add_order_item_meta( $item_id, '_line_tax', wc_format_decimal( 0 ) );
            wc_add_order_item_meta( $item_id, '_line_subtotal_tax', wc_format_decimal( 0 ) );

        }

        // set order status as completed
        wp_set_object_terms( $order_id, 'completed', 'shop_order_status' );

        // if downloadable 
        if( $product->is_downloadable() ) {

            // add downloadable permission for each file
            $download_files = $product->get_files();
            foreach ( $download_files as $download_id => $file ) {
                wc_downloadable_file_permission( $download_id, $product->id, new WC_Order( $order_id ) );
            }

        }

    } else {

        $order->errors = 'Product SKU (' . $order->$item_id . ') not found.';
    }
}


function get_product_by_sku( $sku ) {

    global $wpdb;

    $product_id = $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key='_sku' AND meta_value='%s' LIMIT 1", $sku ) );

    if ( $product_id ) return new WC_Product( $product_id );

    return null;
}

Order Class 订单类

The is the interim class I use to store the orders before importing into WordPress / WooCommerce. 这是我用于在导入WordPress / WooCommerce之前存储订单的临时类。

class ImportOrder
{
    // public vars
    public $date;
    public $time;
    public $time_zone;
    public $first_name;
    public $middle_name;
    public $last_name;
    public $type;
    public $status;
    public $currency;
    public $gross;
    public $fee;
    public $net;
    public $note;
    public $to_email;
    public $from_email;
    public $transaction_id;
    public $counterparty_status;
    public $address_status;
    public $item_title;
    public $item_id;
    public $address_line_1;
    public $address_line_2;
    public $city;
    public $state;
    public $zip;
    public $country;
    public $phone;
    public $imported;
    public $errors;
}

Add Order 添加订单

The data here is imported from a PayPal CSV download of historical transactions. 此处的数据是从历史交易的PayPal CSV下载中导入的。 The $row variable represents one row in the CSV. $ row变量表示CSV中的一行。 You can adjust this to suit your needs. 您可以根据自己的需要进行调整。

function add_import_order( $row ) {

    // create new order
    $order = new ImportOrder();

    // done this before?
    $order->exists = order_exists( $row[PayPalCols::TRANSACTION_ID] );

    // add a bunch of fields
    $order->date = $row[PayPalCols::DATE];
    $order->time = $row[PayPalCols::TIME];
    $order->time_zone = $row[PayPalCols::TIME_ZONE];
    $order->type = $row[PayPalCols::TYPE];
    $order->status = $row[PayPalCols::STATUS];
    $order->currency = $row[PayPalCols::CURRENCY];
    $order->gross = $row[PayPalCols::GROSS];
    $order->fee = $row[PayPalCols::FEE];
    $order->net = $row[PayPalCols::NET];
    $order->note = $row[PayPalCols::NOTE];
    $order->from_email = $row[PayPalCols::FROM_EMAIL];
    $order->to_email = $row[PayPalCols::TO_EMAIL];
    $order->transaction_id = $row[PayPalCols::TRANSACTION_ID];
    $order->counterparty_status = $row[PayPalCols::COUNTERPARTY_STATUS];
    $order->address_status = $row[PayPalCols::ADDRESS_STATUS];
    $order->item_title = $row[PayPalCols::ITEM_TITLE];
    $order->item_id = $row[PayPalCols::ITEM_ID];
    $order->address_line_1 = utf8_encode( $row[PayPalCols::ADDRESS_LINE_1] );
    $order->address_line_2 = utf8_encode( $row[PayPalCols::ADDRESS_LINE_2] );
    $order->city = utf8_encode( $row[PayPalCols::TOWN_CITY] );
    $order->state = utf8_encode( $row[PayPalCols::STATE] );
    $order->zip = utf8_encode( $row[PayPalCols::ZIP] );
    $order->country = utf8_encode( $row[PayPalCols::COUNTRY] );
    $order->phone = utf8_encode( $row[PayPalCols::PHONE] );

    return $order;

}

For creating New order, You will have to create Object of WC_Order , If you working outside WooCommerce or in function.php then, First Define Global $woocommerce variable. 要创建新订单,您必须创建WC_Order对象,如果您在WooCommerce之外或在function.php之外工作,则首先定义Global $woocommerce变量。

So, There will be just 2 line of Code. 所以,只有2行代码。

global $woocommerce;

$order = new WC_Order( $order_id );

Hope, It will help You. 希望,它会帮助你。

As of WooCommerce 2.2 (or maybe 2.1 I'm not 100% sure) there is now a function specifically designed for this. 从WooCommerce 2.2(或者2.1我不是100%肯定)开始,现在有一个专门为此设计的功能。

wc_create_order( $args = array() )

with the following default arguments. 使用以下默认参数。

$default_args = array(
    'status'        => '',
    'customer_id'   => null,
    'customer_note' => null,
    'order_id'      => 0
);

You can see the whole function in the includes/wc-core-functions.php file. 您可以在includes/wc-core-functions.php文件中查看整个函数。

There's a much easier way of doing it, using wc_create_order() . 使用wc_create_order()可以更轻松地完成它。 Here's an example, which also adds shipping and product line items. 这是一个示例,它还添加了运输和产品系列项目。 It also creates a Woocommerce subscription, but you can ignore that part for a normal product, the same code will work. 它还会创建一个Woocommerce订阅,但您可以忽略该部分的正常产品,相同的代码将起作用。

function create_test_sub() {

    $email = 'test@test.com';

    $start_date = '2015-01-01 00:00:00';

    $address = array(
        'first_name' => 'Jeremy',
        'last_name'  => 'Test',
        'company'    => '',
        'email'      => $email,
        'phone'      => '777-777-777-777',
        'address_1'  => '31 Main Street',
        'address_2'  => '', 
        'city'       => 'Auckland',
        'state'      => 'AKL',
        'postcode'   => '12345',
        'country'    => 'AU'
    );

    $default_password = wp_generate_password();

    if (!$user = get_user_by('login', $email)) $user = wp_create_user( $email, $default_password, $email );

    // I've used one product with multiple variations

    $parent_product = wc_get_product(22998);

    $args = array(
        'attribute_billing-period' => 'Yearly',
        'attribute_subscription-type' => 'Both'
    );

    $product_variation = $parent_product->get_matching_variation($args);

    $product = wc_get_product($product_variation);  

    // Each variation also has its own shipping class

    $shipping_class = get_term_by('slug', $product->get_shipping_class(), 'product_shipping_class');

    WC()->shipping->load_shipping_methods();
    $shipping_methods = WC()->shipping->get_shipping_methods();

    // I have some logic for selecting which shipping method to use; your use case will likely be different, so figure out the method you need and store it in $selected_shipping_method

    $selected_shipping_method = $shipping_methods['free_shipping'];

    $class_cost = $selected_shipping_method->get_option('class_cost_' . $shipping_class->term_id);

    $quantity = 1;

    // As far as I can see, you need to create the order first, then the sub

    $order = wc_create_order(array('customer_id' => $user->id));

    $order->add_product( $product, $quantity, $args);
    $order->set_address( $address, 'billing' );
    $order->set_address( $address, 'shipping' );

    $order->add_shipping((object)array (
        'id' => $selected_shipping_method->id,
        'label'    => $selected_shipping_method->title,
        'cost'     => (float)$class_cost,
        'taxes'    => array(),
        'calc_tax'  => 'per_order'
    ));

    $order->calculate_totals();

    $order->update_status("completed", 'Imported order', TRUE);

    // Order created, now create sub attached to it -- optional if you're not creating a subscription, obvs

    // Each variation has a different subscription period

    $period = WC_Subscriptions_Product::get_period( $product );
    $interval = WC_Subscriptions_Product::get_interval( $product );

    $sub = wcs_create_subscription(array('order_id' => $order->id, 'billing_period' => $period, 'billing_interval' => $interval, 'start_date' => $start_date));

    $sub->add_product( $product, $quantity, $args);
    $sub->set_address( $address, 'billing' );
    $sub->set_address( $address, 'shipping' );

    $sub->add_shipping((object)array (
        'id' => $selected_shipping_method->id,
        'label'    => $selected_shipping_method->title,
        'cost'     => (float)$class_cost,
        'taxes'    => array(),
        'calc_tax'  => 'per_order'
    ));

    $sub->calculate_totals();

    WC_Subscriptions_Manager::activate_subscriptions_for_order($order);

    print "<a href='/wp-admin/post.php?post=" . $sub->id . "&action=edit'>Sub created! Click here to edit</a>";
}

have a look at my solution: creating Woocommerce order with line_item programmatically 看看我的解决方案: 以编程方式使用line_item创建Wo​​ocommerce订单

Works like a charm and goes to the correct WC class that is used by the new REST API 像魅力一样工作,并转到新REST API使用的正确WC类

Unfortunately, I don't think there are no easy way to do this I'm afraid. 不幸的是,我不认为没有简单的方法可以做到这一点我害怕。

You need to add the order post using wp_insert_post(); 您需要使用wp_insert_post();添加订单帖子wp_insert_post(); and then add all the meta data using update_post_meta() . 然后使用update_post_meta()添加所有元数据。 You then need to add the using woocommerce_add_order_item() and woocommerce_add_order_item_meta() . 然后,您需要添加使用woocommerce_add_order_item()woocommerce_add_order_item_meta() Lasty you need to set the order status using wp_set_object_terms() . 最后你需要使用wp_set_object_terms()设置订单状态。

It's quite a lot of steps and pitfalls. 这是很多步骤和陷阱。 You need to check your database carefully and add all the data and meta data you need to process and complete the order. 您需要仔细检查数据库并添加处理和完成订单所需的所有数据和元数据。

in woocommerce WC_Checkout class has a "create_order" method. 在woocommerce中,WC_Checkout类有一个“create_order”方法。 You can clone WC_Checkout class, give it another name, change the code of the method for your purposes and call like 您可以克隆WC_Checkout类,给它另一个名称,为您的目的更改方法的代码并调用

include 'path_to_Cloned_WC_Checkout';
$chk = new Cloned_WC_Checkout();
$chk->create_order();

in form handler 在表单处理程序中

maybe this way.. 也许这样..

    function insert_order_to_db($seller,$order_date){
        global $wpdb;
        $result   = $wpdb->query(
            "
            INSERT INTO `wp_posts`(`ID`, `post_author`, `post_date`, `post_date_gmt`, `post_content`, `post_title`, `post_excerpt`, `post_status`, `comment_status`, `ping_status`, `post_password`, `post_name`, `to_ping`, `pinged`, `post_modified`, `post_modified_gmt`, `post_content_filtered`, `post_parent`, `guid`, `menu_order`, `post_type`, `post_mime_type`, `comment_count`)

            VALUES (
            17188,
            $seller,
            '".date_format($order_date, 'Y-m-d H:i:s e')."',
            '".date_format($order_date, 'Y-m-d H:i:s e')."',
            'no',
            'Order &ndash;". date_format($order_date, 'F d, Y @ h:i A')."',
            'noxp',
            'wc-completed',
            'open',
            'close',
            '".uniqid( 'order_' )."',
            'order-". date_format($order_date, 'M-d-Y-hi-a')."',
            '',
            '',
            '2017-07-24',
            '2017-07-24',
            '',
            0,
            '',
            0,
            'shop_order',
            '',
            0)

            "
        );
        $order_id = $wpdb->insert_id;
        return $order_id;
    }
function proccess_order_meta(){
        $date     = date_create("2017-07-24");
        $order_id = insert_order_to_db(194816,$date);
        if( is_wp_error( $order_id ) ){
            $order->errors = $order_id;
        }
        else
        {
            $order_id = 17188;
            add_post_meta($order_id, '_payment_method_title', 'پرداخت آنلاین', true);
            add_post_meta($order_id, '_order_total', 30000, true);
            add_post_meta($order_id, '_customer_user',  194816, true);
            add_post_meta($order_id, '_completed_date', date_format( $date, 'Y-m-d H:i:s e'), true);
            add_post_meta($order_id, '_paid_date', date_format( $date, 'Y-m-d H:i:s e'), true);
            add_post_meta($order_id, '_billing_email', "mavaezi46@gmail.com", true);
            add_post_meta($order_id, '_billing_first_name', "علی", true);

        }

    }
    proccess_order_meta();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM