从 WooCommerce 中的自动补货中排除一个特定的支付网关 [英] Exclude one specific payment gateway from auto-restock in WooCommerce

查看:80
本文介绍了从 WooCommerce 中的自动补货中排除一个特定的支付网关的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的付款方式之一是 ipay88,它只会在付款结清后减少库存.

One of my payment getaway is ipay88 which only reduce stock after payment is cleared.

客户付款期间,订单处于待付款"状态,库存不减少.但是,当客户没有及时付款时,订单将自动标记为已取消".

During the time when customer is making the payment, the order is under "pending payment" which the stock does not reduce. However, when customer does not make the payment in time, the order will automatically be marked as "cancelled".

因为我已经集成了自动补货插件,待付款"到取消"会增加库存.

As I have integrated with auto-restock plugin, "pending payment" to "cancelled" will increase the stock.

我想问一下如何防止为特定的付款假期(ipay88)补货.

I would like to ask how do prevent restock for a specific payment getaway which is ipay88.

if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly

if ( ! class_exists( 'WC_Auto_Stock_Restore' ) ) {

class WC_Auto_Stock_Restore {

    public function __construct() {
    add_action( 'woocommerce_order_status_processing_to_cancelled', array( $this, 'restore_order_stock' ), 10, 1 );
        add_action( 'woocommerce_order_status_on-hold_to_cancelled', array( $this, 'restore_order_stock' ), 10, 1 );
        add_action( 'woocommerce_order_status_pending_to_cancelled', array( $this, 'restore_order_stock' ), 10, 1 );
        add_action( 'woocommerce_order_status_completed_to_cancelled', array( $this, 'restore_order_stock' ), 10, 1 );
        add_action( 'woocommerce_order_status_processing_to_refunded', array( $this, 'restore_order_stock' ), 10, 1 );
        add_action( 'woocommerce_order_status_completed_to_refunded', array( $this, 'restore_order_stock' ), 10, 1 );
        add_action( 'woocommerce_order_status_on-hold_to_refunded', array( $this, 'restore_order_stock' ), 10, 1 );
        add_action( 'woocommerce_order_status_cancelled_to_completed', array( $this, 'remove_order_stock' ), 10, 1 );
        add_action( 'woocommerce_order_status_cancelled_to_processing', array( $this, 'remove_order_stock' ), 10, 1 );
        add_action( 'woocommerce_order_status_cancelled_to_on-hold', array( $this, 'remove_order_stock' ), 10, 1 );
        add_action( 'woocommerce_order_status_cancelled_to_pending', array( $this, 'remove_order_stock' ), 10, 1 );
        //add_action( 'woocommerce_order_status_changed', array( $this, 'adjust_order_stock' ), 10, 3 );
    } // End __construct()

    //public function adjust_order_stock( $order_id, $old_status, $new_status ) {
        //$valid_new_statuses = array( 'complete' );
        //if ( $old_status == cancelled AND $new_status )
    //}

    public function remove_order_stock( $order_id ) {
        $order = new WC_Order( $order_id );

        if ( ! get_option('woocommerce_manage_stock') == 'yes' && ! sizeof( $order->get_items() ) > 0 ) {
            return;
        }

        foreach ( $order->get_items() as $item ) {

            if ( $item['product_id'] > 0 ) {
                $_product = $order->get_product_from_item( $item );

                if ( $_product && $_product->exists() && $_product->managing_stock() ) {
                    $old_stock = $_product->stock;

                    $qty = apply_filters( 'woocommerce_order_item_quantity', $item['qty'], $this, $item );

                    $new_quantity = $_product->reduce_stock( $qty );

                    do_action( 'woocommerce_auto_stock_restored', $_product, $item );

                    $order->add_order_note( sprintf( __( 'Item #%s stock decremented from %s to %s.', 'woocommerce' ), $item['product_id'], $old_stock, $new_quantity) );

                    $order->send_stock_notifications( $_product, $new_quantity, $item['qty'] );
                }
            }
        }
    }

    public function restore_order_stock( $order_id ) {
        $order = new WC_Order( $order_id );

        if ( ! get_option('woocommerce_manage_stock') == 'yes' && ! sizeof( $order->get_items() ) > 0 ) {
            return;
        }

        foreach ( $order->get_items() as $item ) {

            if ( $item['product_id'] > 0 ) {
                $_product = $order->get_product_from_item( $item );

                if ( $_product && $_product->exists() && $_product->managing_stock() ) {
                    $old_stock = $_product->stock;

                    $qty = apply_filters( 'woocommerce_order_item_quantity', $item['qty'], $this, $item );

                    $new_quantity = $_product->increase_stock( $qty );

                    do_action( 'woocommerce_auto_stock_restored', $_product, $item );

                    $order->add_order_note( sprintf( __( 'Item #%s stock incremented from %s to %s.', 'woocommerce' ), $item['product_id'], $old_stock, $new_quantity) );

                    $order->send_stock_notifications( $_product, $new_quantity, $item['qty'] );
                }
            }
        }
    } // End restore_order_stock()
}
$GLOBALS['wc_auto_stock_restore'] = new WC_Auto_Stock_Restore();
}

推荐答案

针对 Woocommerce 版本 3+ 进行更新、测试且功能齐全

自 WooCommerce 版本 3 以来,您的代码确实过时了.所以我重新访问了所有代码......

Your code is really obsolete since WooCommerce version 3. So I have revisited all the code…

此外,对于每种状态更改,您还可以使用多个钩子替换所有钩子:woocommerce_order_status_changed...

Also instead using multiple hooks for each kind of status change, you can replace all the hooks by a unique one: woocommerce_order_status_changed

最后,有了这个独特的钩子,您将需要一个独特的功能,当订单状态改变时,可以轻松排除您的 'ipay88' 支付网关 ID从待定"到已取消".

Finally with that unique hook, you will need a unique function, where it will be possible to exclude easily your 'ipay88' payment gateway ID when order status is changed from 'pending' to 'cancelled'.

对于生成的订单备注,当订单中有多个商品时,最好得到一个唯一的订单备注...

For the generated order note, It's better to get a unique order note when there is multiple items in the order…

所以这个插件的完整代码是:

So the complete code for this plugin is:

## ---- for WooCommerce versions 3+ - Plugin code version ---- ##

if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly

if ( ! class_exists( 'WC_Auto_Stock_Restore' ) ) {

    class WC_Auto_Stock_Restore {

        public function __construct() {
            add_action( 'woocommerce_order_status_changed', array( $this, 'adjust_order_stock' ), 10, 3 );
        }

        public function adjust_order_stock( $order_id, $old_status, $new_status ) {
            $order = new WC_Order( $order_id );
            $items = $order->get_items();

            if ( ! get_option('woocommerce_manage_stock') == 'yes' && ! count( $items ) > 0 )
                return; // We exit

            // EXCEPTION for 'ipay88' payment method id, when Order status change from 'pending' to 'cancelled'
            if( $order->get_payment_method() == 'ipay88' && $old_status == 'pending' && $new_status == 'cancelled' )
                return; // We exit

            // We don't need from 'pending' to 'refunded' order status
            if( $old_status == 'pending' && $new_status == 'refunded' )
                return; // We exit

            // Group Order statuses in 2 groups (array)
            $statuses_group1 = array( 'processing', 'on-hold', 'pending', 'completed' );
            $statuses_group2 = array( 'cancelled', 'refunded' );

            $change_stock = false;
            $order_note = array();

            ## 1. Restore Order stock (7 order status change types)
            if ( in_array( $old_status, $statuses_group1 ) && in_array( $new_status, $statuses_group2 ) ) {
                $change_stock = true;
                $change_type = 'increase';
                $change_text =  __( 'incremented', 'woocommerce' );
            }
            ## 2. Restore Order stock (4 order status change types)
            elseif ( $old_status == 'cancelled' && in_array( $new_status, $statuses_group1 ) ) {
                $change_stock = true;
                $change_type = 'decrease';
                $change_text =  __( 'decremented', 'woocommerce' );
            }
            ## 3. Other cases
            else return; // We exit

            if( $change_stock ){
                // Iterating through each order 'line_item'
                // Since WC 3, $item is a WC_Order_Item_Product object
                foreach ( $items as $item ) {
                    $product_id = $item->get_product_id(); // The product ID
                    if ( $product_id > 0 ) {
                         // Get tan instance of the WC_Product object
                        $product = $item->get_product();
                        if ( $product && $product->exists() && $product->managing_stock() ) {

                            // Get the product initial stock quantity (before update)
                            $initial_stock = $product->get_stock_quantity();

                            $item_qty = apply_filters( 'woocommerce_order_item_quantity', $item->get_quantity(), $this, $item );

                            // Update the product stock quantity
                            // Replace DEPRECATED methods: increase_stock() & discrease_stock()
                            wc_update_product_stock( $product, $item_qty, $change_type );

                            // Get the product updated stock quantity
                            $updated_stock = ( $change_type == 'increase' ) ? $initial_stock + $item_qty : $initial_stock - $item_qty;

                            do_action( 'woocommerce_auto_stock_restored', $product, $item );

                            // A unique Order note: Store each order note in an array…
                            $order_note[] = sprintf( __( 'Product ID #%s stock %s from %s to %s.', 'woocommerce' ), $product_id, $change_text, $initial_stock, $updated_stock);

                            // DEPRECATED & NO LONGER NEEDED - can be removed
                            //$order->send_stock_notifications( $product, $updated_stock, $item_qty );
                        }
                    }
                }
                // Adding a unique composite order note (for multiple items)
                $order_notes = count($order_note) > 1 ? implode(' | ', $order_note) : $order_note[0];
                $order->add_order_note( $order_notes );
            }
        }
    }
    $GLOBALS['wc_auto_stock_restore'] = new WC_Auto_Stock_Restore();
}

这应该放在一个插件 php 文件中(见这与 WooCommerce 插件创建相关).

This should go in a plugin php file (see this related to WooCommerce plugins creation).

普通版 (用于主题function.php文件):

## ---- for WooCommerce versions 3+ - Theme code version ---- ##

add_action( 'woocommerce_order_status_changed', 'adjust_order_stock', 10, 3 );
function adjust_order_stock( $order_id, $old_status, $new_status ) {
    $order = new WC_Order( $order_id );
    $items = $order->get_items();

    if ( ! get_option('woocommerce_manage_stock') == 'yes' && ! count( $items ) > 0 )
        return; // We exit

    // EXCEPTION for 'ipay88' payment method id, when Order status change from 'pending' to 'cancelled'
    if( $order->get_payment_method() == 'ipay88' && $old_status == 'pending' && $new_status == 'cancelled' )
        return; // We exit

    // We don't need from 'pending' to 'refunded' order status
    if( $old_status == 'pending' && $new_status == 'refunded' )
        return; // We exit

    // Group Order statuses in 2 groups (array)
    $statuses_group1 = array( 'processing', 'on-hold', 'pending', 'completed' );
    $statuses_group2 = array( 'cancelled', 'refunded' );

    $change_stock = false;
    $order_note = array();

    ## 1. Restore Order stock (7 order status change types)
    if ( in_array( $old_status, $statuses_group1 ) && in_array( $new_status, $statuses_group2 ) ) {
        $change_stock = true;
        $change_type = 'increase';
        $change_text =  __( 'incremented', 'woocommerce' );
    }
    ## 2. Restore Order stock (4 order status change types)
    elseif ( $old_status == 'cancelled' && in_array( $new_status, $statuses_group1 ) ) {
        $change_stock = true;
        $change_type = 'decrease';
        $change_text =  __( 'decremented', 'woocommerce' );
    }
    ## 3. Other cases
    else return; // We exit

    if( $change_stock ){
        // Iterating through each order 'line_item'
        // Since WC 3, $item is a WC_Order_Item_Product object
        foreach ( $items as $item ) {
            $product_id = $item->get_product_id(); // The product ID
            if ( $product_id > 0 ) {
                 // Get tan instance of the WC_Product object
                $product = $item->get_product();
                if ( $product && $product->exists() && $product->managing_stock() ) {

                    // Get the product initial stock quantity (before update)
                    $initial_stock = $product->get_stock_quantity();

                    $item_qty = apply_filters( 'woocommerce_order_item_quantity', $item->get_quantity(), $this, $item );

                    // Update the product stock quantity
                    // Replace DEPRECATED methods: increase_stock() & discrease_stock()
                    wc_update_product_stock( $product, $item_qty, $change_type );

                    // Get the product updated stock quantity
                    $updated_stock = ( $change_type == 'increase' ) ? $initial_stock + $item_qty : $initial_stock - $item_qty;

                    do_action( 'woocommerce_auto_stock_restored', $product, $item );

                    // A unique Order note: Store each order note in an array…
                    $order_note[] = sprintf( __( 'Product ID #%s stock %s from %s to %s.', 'woocommerce' ), $product_id, $change_text, $initial_stock, $updated_stock);

                    // DEPRECATED & NO LONGER NEEDED - can be removed
                    //$order->send_stock_notifications( $product, $updated_stock, $item_qty );
                }
            }
        }
        // Adding a unique composite order note (for multiple items)
        $order_notes = count($order_note) > 1 ? implode(' | ', $order_note) : $order_note[0];
        $order->add_order_note( $order_notes );
    }
}

此代码位于活动子主题(或主题)的 function.php 文件中.

所有代码都经过测试,仅适用于 WooCommerce 版本 3+

All the code is tested and works only for WooCommerce versions 3+

Woocommerce 订单相关:

Woocommerce Order related:

这篇关于从 WooCommerce 中的自动补货中排除一个特定的支付网关的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆