问题
I have a product that people can print directly (shipping method 1) or choose to get it via shipping service (shipping method 2). So the order should auto complete if they choose to print it directly (shipping method 2) ONLY.
Is it possible to extend that code snippet from WooCommerce?
From docs I found this
/**
* Auto Complete all WooCommerce orders.
*/
add_action( 'woocommerce_thankyou', 'custom_woocommerce_auto_complete_order');
function custom_woocommerce_auto_complete_order( $order_id ) {
if ( ! $order_id ) {
return;
}
$order = wc_get_order( $order_id );
$order->update_status( 'completed' );
}
Here is the working solution. BIG THANKS TO LoicTheAztec:
add_action( 'woocommerce_thankyou',
'wc_auto_complete_paid_order_based_on_shipping_method', 20, 1 );
function wc_auto_complete_paid_order_based_on_shipping_method( $order_id ) {
if ( ! $order_id ) return;
// HERE define the allowed shipping methods IDs (can be names or slugs changing the code a bit)
$allowed_shipping_methods = array( '5' );
// Get an instance of the WC_Order object
$order = wc_get_order( $order_id );
// Get the shipping related data for this order:
$shipping_item = $order->get_items('shipping');
$item = reset($shipping_item);
$item_data = $item->get_data();
// Get the shipping method name, rate ID and type slug
$method_rate_id = $item_data['instance_id']; // Shipping method ID
// No updated status for orders delivered with Bank wire, Cash on
delivery and Cheque payment methods.
$avoided_statuses = array( 'bacs', 'cod', 'cheque');
if ( in_array( $order->get_payment_method(), $avoided_statuses ) ){
return;
}
// update status to "completed" for paid Orders and a defined shipping
method ID
elseif ( in_array( $method_rate_id, $allowed_shipping_methods ) ){
$order->update_status( 'completed' );
}
}
回答1:
First,
get_post_meta($order_id, '_payment_method', true )
or$order->get_payment_method()
are completely similar and do the same thing.
The difference is that the first one use a Wordpress function to access this data fromwp_postmeta
table and the 2nd one is aWC_Order
method that will also access the same data fromwp_postmeta
table…
No one is better than the other.
New enhanced revisited code (see this thread for explanations).
What is the instance ID:
For example if the Shipping method rate Id is flat_rate:14
, the instance Id is 14
(unique ID)
The new version code:
add_action( 'woocommerce_payment_complete_order_status', 'auto_complete_paid_order_based_on_shipping_method', 10, 3 );
function auto_complete_paid_order_based_on_shipping_method( $status, $order_id, $order ) {
// HERE define the allowed shipping methods instance IDs
$allowed_shipping_methods_instance_ids = array( '14', '19' );
// Loop through order "shipping" items
foreach ( $order->get_shipping_methods() as $shipping_method ) {
if( in_array( $shipping_method->get_instance_id(), $allowed_shipping_methods_instance_ids ) ) {
return 'completed';
}
}
return $status;
}
Code goes in function.php file of the active child theme (or active theme). Tested and works.
Original answer:
The answer below comes from this similar answer I have maid some time ago:
WooCommerce: Auto complete paid orders
add_action( 'woocommerce_thankyou', 'auto_complete_paid_order_based_on_shipping_method', 10, 1 );
function auto_complete_paid_order_based_on_shipping_method( $order_id ) {
if ( ! $order_id ) return;
// HERE define the allowed shipping methods IDs (can be names or slugs changing the code a bit)
$allowed_shipping_methods = array( 'flat_rate:14', 'flat_rate:19' );
// Get an instance of the WC_Order object
$order = wc_get_order( $order_id );
// Get the shipping related data for this order:
$shipping_item = $order->get_items('shipping');
$item = reset($shipping_item);
$item_data = $item->get_data();
// Get the shipping method name, rate ID and type slug
$shipping_name = $item_data['name']; // Shipping method name
$method_rate_id = $item_data['method_id']; // Shipping method ID
$method_arr = explode( ':', $method_rate_id );
$method_type = $method_arr[0]; // Shipping method type slug
// No updated status for orders delivered with Bank wire, Cash on delivery and Cheque payment methods.
$avoided_statuses = array( 'bacs', 'cod', 'cheque');
if ( in_array( $order->get_payment_method(), $avoided_statuses ) ){
return;
}
// update status to "completed" for paid Orders and a defined shipping method ID
elseif ( in_array( $method_rate_id, $allowed_shipping_methods ) ){
$order->update_status( 'completed' );
}
}
Code goes in function.php file of the active child theme (or active theme).
Tested and works.
回答2:
I think what you're looking for is $order->has_shipping_method('name_of_method')
From: https://docs.woocommerce.com/wc-apidocs/class-WC_Abstract_Order.html#_has_shipping_method)
回答3:
That is my working solution (Thanks to LoicTheAztec):
add_action( 'woocommerce_thankyou',
'wc_auto_complete_paid_order_based_on_shipping_method', 20, 1 );
function wc_auto_complete_paid_order_based_on_shipping_method( $order_id ) {
if ( ! $order_id ) return;
// HERE define the allowed shipping methods IDs (can be names or slugs changing the code a bit)
$allowed_shipping_methods = array( '5' );
// Get an instance of the WC_Order object
$order = wc_get_order( $order_id );
// Get the shipping related data for this order:
$shipping_item = $order->get_items('shipping');
$item = reset($shipping_item);
$item_data = $item->get_data();
// Get the shipping method name, rate ID and type slug
$method_rate_id = $item_data['instance_id']; // Shipping method ID
// No updated status for orders delivered with Bank wire, Cash on delivery and Cheque payment methods.
$avoided_statuses = array( 'bacs', 'cod', 'cheque');
if ( in_array( $order->get_payment_method(), $avoided_statuses ) ){
return;
}
// update status to "completed" for paid Orders and a defined shipping method ID
elseif ( in_array( $method_rate_id, $allowed_shipping_methods ) ){
$order->update_status( 'completed' );
}
}
来源:https://stackoverflow.com/questions/48303688/woocommerce-autocomplete-paid-orders-based-on-shipping-method