WooCommerce:自动完成已付款订单

42

通常情况下,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) 插件: WooCommerce自动完成订单

此插件适用于所有支付方法,但不适用于其他信用卡网关支付方式。

我的问题:

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

如何根据woocommerce支付方式实现条件代码?

我的意思是:如果支付方式不是“BACS”,“货到付款”和“支票”,则应用片段代码(将有关虚拟产品的已支付订单更新为“已完成”状态)。

非常感谢您的帮助。

5个回答

63

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

此过滤器挂钩位于:

如您所见,默认情况下允许的已付款订单状态为"processing"和"completed"。

解释: 1. 轻巧而有效: 由于它是一个过滤器钩子,当需要在线支付时,woocommerce_payment_complete_order_status 只会被触发(不适用于"cheque"、"bacs"或"cod"支付方式)。在这里,我们只是改变了允许的已支付订单状态。 因此,不需要为支付网关或其他任何内容添加条件。
2. 准确(避免多次通知): 这是唯一的方法,可以避免同时发送2个不同的客户通知: - 一个是"processing"订单状态的通知 - 另一个是"completed"订单状态的通知。
因此,客户只会在"completed"订单状态下收到一次通知。
使用下面的代码,只会将已支付订单的状态(由支付网关设置的)更改为"completed":
add_filter( '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文件中。
相关:{{link1:WooCommerce:根据运输方式自动完成付费订单}}。

2018 - 改进版本 (适用于WooCommerce 3及以上版本)

基于WooCommerce官方钩子,我找到了一个解决这个问题的方法*(适用于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;
    } 
    // Autocomplete all others payment methods
    else {
        $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文件中。

借助这篇文章的帮助:如何通过订单ID检查WooCommerce订单的付款方式?

使用这个代码:get_post_meta( $order_id, '_payment_method', true ); 来自helgatheviking

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

更新了与WC 3.0+(2017-06-10)兼容的代码


“woocommerce_thankyou”钩子仅在用户重定向到WooCommerce“感谢您”的页面时触发...如果由于某种原因用户决定不按PayPal的“返回商家”链接,这可能不会发生。 - Yair Levy
@YairLevy 我知道... 那么问题出在哪里呢?在这种情况下,订单将不会支付... - LoicTheAztec
1
@LoicTheAztec,问题在于订单将被支付,但操作不会执行。为了明确:用户在结账时离开网站(重定向到PayPal等),进行付款,然后不点击“返回商家”按钮,而是关闭浏览器或者可能转到网站主页或其他页面...只要他不访问“感谢您”的页面-订单就不会完成。 - Yair Levy
1
@LoicTheAztec 这确实是官方的 WooCommerce 代码片段... 但它有一个注意事项(如前面的评论所述)。Paypal 使用 IPN(即时付款通知)将付款批准发送回网站。当它发生时,它会触发“woocommerce_payment_complete”钩子(如果您想自动完成订单,则是正确的钩子)。 - Yair Levy
1
@MotazHomsi 我已经更新了我的答案,使用最有效和轻量的方式,避免向付款订单的客户发送多个电子邮件通知。 - LoicTheAztec
显示剩余5条评论

6

对于我来说,即使支付失败,此挂钩也会被调用,这导致了付款失败。经过一些研究,我将其改为使用“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' );
    }
}

1

对于我来说,当付款完成时修改订单状态的最简单的钩子是'woocommerce_order_item_needs_processing',因为这个筛选钩子旨在在付款完成时修改目标订单状态。

这就是最终片段的样子:

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

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

0
对我来说,在使用PayPal沙盒测试系统(WooCommerce PayPal支付插件)LoicTheAztec解决方案(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 );

@LoicTheAztec,在你的回答中,你使用了 add_action 来处理 woocommerce_payment_complete_order_status 过滤器,这样做可以吗? - Yurié

-1

如果您正在寻找虚拟订单的自动完成(如课程、电子书、可下载文件等),这可能会有所帮助。

 * 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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接