WooCommerce:自动完成已付款订单

WooCommerce: Auto complete paid orders

通常 wooCommerce 应该自动完成虚拟产品的订单。但事实并非如此,这是一个真正的问题,甚至是一个BUG之类的。

所以此时你可以找到一些有用的东西(但不是很方便):

1) A snippet code (that you can find in wooCommerce docs):

/**
 * 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' );
}

But this snippet does not work for BACS*, Pay on delivery and Cheque payment methods. It's ok for Paypal and Credit Card gateways payment methods.

*BACS 是直接银行转账付款方式

还有……

2) A plugin: WooCommerce Autocomplete Orders

This plugin works for all payment methods, but not for other Credit Card gateways payment methods.

我的问题:

使用(作为基础)第 1 点中的 wooCommerce 片段:

如何实现基于 woocommerce 支付方式的条件代码?

我的意思是:如果付款方式不是 "BACS"、"Pay on delivery" 和 "Cheque",则应用代码段(将状态更新为 "completed"有关虚拟产品的订单)。

一些帮助会很好。

最准确、最有效、最轻便的解决方案 (适用于 WooCommerce 3 及以上版本)- 2019

此过滤器挂钩位于:

如您所见,默认情况下允许的已付款订单状态是“正在处理”和“已完成”。

###Explanations:

  1. Lightweight and effective:

As it is a filter hook, woocommerce_payment_complete_order_status is only triggered when an online payment is required (not for "cheque", "bacs" or "cod" payment methods). Here we just change the allowed paid order statuses.

So no need to add conditions for the payment gateways or anything else.

  1. Accurate (avoid multiple notifications):

This is the only way to avoid sending 2 different customer notifications at the same time:
• One for "processing" orders status
• And one for "completed" orders status.

So customer is only notified once on "completed" order status.

使用下面的代码,只会更改已付款订单状态 (由支付网关为已付款订单设置) “完成”:

add_action( 'woocommerce_payment_complete_order_status', 'wc_auto_complete_paid_order', 10, 3 );
function wc_auto_complete_paid_order( $status, $order_id, $order ) {
    return 'completed';
}

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

相关:


2018 - 改进版本[​​=97=] (适用于 WooCommerce 3 及更高版本)

基于 Woocommerce 官方 hook,我找到了解决这个问题的方法 *(适用于 WC 3+)。

在 Woocommerce 中除 bacs (银行电汇)chequecod 以外的所有其他支付网关(货到付款)已付款订单状态为“处理中”和“已完成”

所以我针对所有支付网关(如 Paypal 或信用卡支付)的“正在处理”订单状态,更新订单状态以完成。

代码:

add_action( 'woocommerce_thankyou', 'wc_auto_complete_paid_order', 20, 1 );
function wc_auto_complete_paid_order( $order_id ) {
    if ( ! $order_id )
        return;
    
    // Get an instance of the WC_Product object
    $order = wc_get_order( $order_id );
    
    // No updated status for orders delivered with Bank wire, Cash on delivery and Cheque payment methods.
    if ( in_array( $order->get_payment_method(), array( 'bacs', 'cod', 'cheque', '' ) ) ) {
        return;
    } 
    // For paid Orders with all others payment methods (paid order status "processing")
    elseif( $order->has_status('processing') ) {
        $order->update_status( 'completed' );
    }
}

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


原始答案 (适用于所有 woocommerce 版本):

代码:

/**
 * AUTO COMPLETE PAID ORDERS IN WOOCOMMERCE
 */
add_action( 'woocommerce_thankyou', 'custom_woocommerce_auto_complete_paid_order', 10, 1 );
function custom_woocommerce_auto_complete_paid_order( $order_id ) {
    if ( ! $order_id )
    return;

    $order = wc_get_order( $order_id );

    // No updated status for orders delivered with Bank wire, Cash on delivery and Cheque payment methods.
    if ( ( 'bacs' == get_post_meta($order_id, '_payment_method', true) ) || ( 'cod' == get_post_meta($order_id, '_payment_method', true) ) || ( 'cheque' == get_post_meta($order_id, '_payment_method', true) ) ) {
        return;
    } 
    // For paid Orders with all others payment methods (with paid status "processing")
    elseif( $order->get_status()  === 'processing' ) {
        $order->update_status( 'completed' );
    }
}

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

在这个post的帮助下:How to check payment method on a WooCommerce order by id?

与此 : get_post_meta( $order_id, '_payment_method', true ); 来自 helgatheviking

“银行电汇”(bacs)、“货到付款”(cod) 和“支票”(cheque) 支付方式将被忽略并保持其原始订单状态。

更新代码以兼容WC 3.0+ (2017-06-10)

对我来说,即使付款没有通过或失败也会调用这个钩子,这会导致完成失败的付款。经过一些研究,我将其更改为使用 'woocommerce_payment_complete' 因为它仅在付款完成时调用,并且它涵盖了@LoicTheAztec 上面提到的问题 –

add_action( 'woocommerce_payment_complete', 'wc_auto_complete_paid_order', 20, 1 );
function wc_auto_complete_paid_order( $order_id ) {
    if ( ! $order_id )
        return;

    // Get an instance of the WC_Product object
    $order = wc_get_order( $order_id );

    // No updated status for orders delivered with Bank wire, Cash on delivery and Cheque payment methods.
    if ( in_array( $order->get_payment_method(), array( 'bacs', 'cod', 'cheque', '' ) ) ) {
        return;
    // Updated status to "completed" for paid Orders with all others payment methods
    } else {
        $order->update_status( 'completed' );
    }
}

如果您正在寻找虚拟订单(如课程、电子书、可下载内容等)的自动完成功能,这可能会有用。

 * Auto Complete all WooCommerce virtual orders.
 * 
 * @param  int  $order_id The order ID to check
 * @return void
 */
function custom_woocommerce_auto_complete_virtual_orders( $order_id ) {

    // if there is no order id, exit
    if ( ! $order_id ) {
        return;
    }

    // No updated status for orders delivered with Bank wire, Cash on delivery and Cheque payment methods.
    if ( in_array( $order->get_payment_method(), array( 'bacs', 'cod', 'cheque', '' ) ) ) {
        return;
    } 

    // get the order and its exit
    $order = wc_get_order( $order_id );
    $items = $order->get_items();

    // if there are no items, exit
    if ( 0 >= count( $items ) ) {
        return;
    }

    // go through each item
    foreach ( $items as $item ) {

        // if it is a variation
        if ( '0' != $item['variation_id'] ) {

            // make a product based upon variation
            $product = new WC_Product( $item['variation_id'] );

        } else {

            // else make a product off of the product id
            $product = new WC_Product( $item['product_id'] );

        }

        // if the product isn't virtual, exit
        if ( ! $product->is_virtual() ) {
            return;
        }
    }

    /*
     * If we made it this far, then all of our items are virual
     * We set the order to completed.
     */
    $order->update_status( 'completed' );
}
add_action( 'woocommerce_thankyou', 'custom_woocommerce_auto_complete_virtual_orders' );

改编自https://gist.github.com/jessepearson/33f383bb3ea33069822817cfb1da4258

对我来说,最简单的在支付完成时修改订单状态的钩子是'woocommerce_order_item_needs_processing',因为这个过滤钩子的目的是在支付完成时修改目标订单状态。

这就是最终代码段的样子:

add_filter('woocommerce_order_item_needs_processing', '__return_false',999);

它还与网站上的其他插件兼容。

对我来说,在带有 PayPal 沙盒(WooCommerce PayPal 支付插件)的测试系统上,(2019 年更新)仅在我添加 $order->update_status( 'completed' ); 代码行时才有效。 return 'completed'; 对我没有影响,我保留它只是因为它是一个过滤器。

add_filter( 'woocommerce_payment_complete_order_status', function( $status, $order_id, $order ) {
    $order->update_status( 'completed' );
    return 'completed';
}, 10, 3 );