[WooCommerce] 客製化已出貨訂單狀態顧客通知信的方法

本篇文章更新時間:2023/09/13
如有資訊過時或語誤之處,歡迎使用 Contact 功能通知。
一介資男的 LINE 社群開站囉!歡迎入群聊聊~
如果本站內容對你有幫助,歡迎使用 BFX Pay 加密貨幣新台幣 贊助支持。


剛好最近處理幾個 WooCommerce 網站,發現其實「已出貨」的這個訂單狀態需求還算滿常見的!

上網找沒看到一個滿意的寫法,自己順過一次正確註冊通知信的方法後來筆記一下~

本篇分以下幾個流程:

  1. 註冊訂單狀態
  2. 後台功能加入新訂單狀態選項
  3. 註冊訂單狀態發信的類別
  4. 註冊發信的事件(時機)
  5. 設計發信的範本(template)

註冊訂單狀態

// 註冊新訂單狀態
function mxp_register_custom_order_status() {
    register_post_status('wc-awaiting-delivery', array(
        'label'                     => '已出貨訂單',
        'public'                    => true,
        'exclude_from_search'       => false,
        'show_in_admin_all_list'    => true,
        'show_in_admin_status_list' => true,
        'label_count'               => _n_noop('已出貨訂單 (%s)', '已出貨訂單 (%s)', 'woocommerce'),
    ));
}
add_action('init', 'mxp_register_custom_order_status', 20);

可以使用 init 或是 woocommerce_init 這兩個事件來註冊。記得不管包在哪裡使用這段,勾點的觸發時機都不能有順序不對的狀況。也就是 plugins_loaded 執行的順序比 init 後面,就不能在 plugins_loaded 這裡面才使用這樣的勾點。

其他訂單狀態就以此類推,這部分也有一些工具幫忙,客製化訂單狀態來分類訂單算常見的需求。

後台功能加入新訂單狀態選項

加入訂單編輯頁面中,下拉選單的訂單狀態:

// 加入新訂單狀態
function mxp_custom_wc_order_statuses($order_statuses) {
    $order_statuses['wc-awaiting-delivery'] = '已出貨訂單';
    return $order_statuses;
}
add_filter('wc_order_statuses', 'mxp_custom_wc_order_statuses');

再來是加入列表頁面批次處理訂單狀態的功能選單:

// 批次處理訂單狀態
function mxp_custom_dropdown_bulk_actions_shop_order($actions) {
    $actions['mark_awaiting-delivery'] = '變更狀態為已出貨訂單';
    return $actions;
}
add_filter('bulk_actions-edit-shop_order', 'mxp_custom_dropdown_bulk_actions_shop_order', 20, 1);

註冊訂單狀態發信的類別

到這邊才是重頭戲,寫一個 WC_Email_Awaiting_Delivery_Order 已出貨通知信的類別,然後使用勾點註冊這方法。

說是「寫」也不難,直接拿「處理中」的類別去改一改就好,很方便!

id             = 'awaiting_delivery_order';
            $this->customer_email = true;

            $this->title          = '已出貨訂單';
            $this->description    = '通知購買人商品已經出貨的信';
            $this->template_html  = 'emails/customer-awaiting-delivery-order.php';
            $this->template_plain = 'emails/plain/customer-awaiting-delivery-order.php';
            $this->placeholders   = array(
                '{order_date}'   => '',
                '{order_number}' => '',
            );

            // Triggers for this email.
            add_action('woocommerce_order_status_processing_to_awaiting-delivery_notification', array($this, 'trigger'), 10, 2);
            add_action('woocommerce_order_status_cancelled_to_awaiting-delivery_notification', array($this, 'trigger'), 10, 2);
            add_action('woocommerce_order_status_failed_to_awaiting-delivery_notification', array($this, 'trigger'), 10, 2);
            add_action('woocommerce_order_status_on-hold_to_awaiting-delivery_notification', array($this, 'trigger'), 10, 2);
            add_action('woocommerce_order_status_pending_to_awaiting-delivery_notification', array($this, 'trigger'), 10, 2);

            // Call parent constructor.
            parent::__construct();
        }

        /**
         * Get email subject.
         *
         * @since  3.1.0
         * @return string
         */
        public function get_default_subject() {
            return '商品已出貨,感謝您的惠顧';
        }

        /**
         * Get email heading.
         *
         * @since  3.1.0
         * @return string
         */
        public function get_default_heading() {
            return '商品已出貨,感謝您的惠顧';
        }

        /**
         * Trigger the sending of this email.
         *
         * @param int            $order_id The order ID.
         * @param WC_Order|false $order Order object.
         */
        public function trigger($order_id, $order = false) {
            $this->setup_locale();

            if ($order_id && !is_a($order, 'WC_Order')) {
                $order = wc_get_order($order_id);
            }

            if (is_a($order, 'WC_Order')) {
                $this->object                         = $order;
                $this->recipient                      = $this->object->get_billing_email();
                $this->placeholders['{order_date}']   = wc_format_datetime($this->object->get_date_created());
                $this->placeholders['{order_number}'] = $this->object->get_order_number();
            }

            if ($this->is_enabled() && $this->get_recipient()) {
                $this->send($this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments());
            }

            $this->restore_locale();
        }

        /**
         * Get content html.
         *
         * @return string
         */
        public function get_content_html() {
            return wc_get_template_html(
                $this->template_html,
                array(
                    'order'              => $this->object,
                    'email_heading'      => $this->get_heading(),
                    'additional_content' => $this->get_additional_content(),
                    'sent_to_admin'      => false,
                    'plain_text'         => false,
                    'email'              => $this,
                )
            );
        }

        /**
         * Get content plain.
         *
         * @return string
         */
        public function get_content_plain() {
            return wc_get_template_html(
                $this->template_plain,
                array(
                    'order'              => $this->object,
                    'email_heading'      => $this->get_heading(),
                    'additional_content' => $this->get_additional_content(),
                    'sent_to_admin'      => false,
                    'plain_text'         => true,
                    'email'              => $this,
                )
            );
        }

        /**
         * Default content to show below main email content.
         *
         * @since 3.7.0
         * @return string
         */
        public function get_default_additional_content() {
            return __('Thanks for using {site_url}!', 'woocommerce');
        }
    }

endif;

return new WC_Email_Awaiting_Delivery_Order();

將上述的類別存成 class-wc-email-awaiting-delivery-order.php 檔案放在(子)主題目錄下,再來繼續補寫註冊方法到 functons.php

// 註冊狀態信件類別
function mxp_woocommerce_email_classes($emails) {
    $emails['WC_Email_Awaiting_Delivery_Order'] = include __DIR__ . '/class-wc-email-awaiting-delivery-order.php';
    return $emails;
}
add_filter('woocommerce_email_classes', 'mxp_woocommerce_email_classes', 11, 1);

WC_Email_Awaiting_Delivery_Order 這類別給註冊進系統後,此時後台 WooCommerce -> 設定 -> 電子郵件 就可以看到新加入的狀態通知信。

註冊發信的事件(時機)

到前面的階段還僅能看到這個通知類別,但還沒辦法根據觸發狀態連動。

這時候就是要補注冊一些事件,讓訂單改變的時候來觸發發信機制。

// 註冊發信事件
function mxp_woocommerce_email_actions($actions) {
    $actions[] = 'woocommerce_order_status_processing_to_awaiting-delivery';
    $actions[] = 'woocommerce_order_status_pending_to_awaiting-delivery';
    $actions[] = 'woocommerce_order_status_failed_to_awaiting-delivery';
    $actions[] = 'woocommerce_order_status_cancelled_to_awaiting-delivery';
    $actions[] = 'woocommerce_order_status_on-hold_to_awaiting-delivery';
    return $actions;
}
add_filter('woocommerce_email_actions', 'mxp_woocommerce_email_actions', 11, 1);

到這一步才完成一個訂單狀態連動 WordPress/WooCommerce 系統發信的串接。

設計發信的範本(template)

串接好後剩下就是「發信內容」的處理。從 WC_Email_Awaiting_Delivery_Order 類別中的定義可以看到,一樣遵循 WooCommerce 發信架構的設計,只要把這個範本放入到(子)主題資料夾內的 woocommerce/emails/ 中,就可以開始編寫內容。

這邊就算是一個過程筆記,操作起來也不難,把也是「處理中」狀態的範本檔案 customer-processing-order.php 複製一份新的檔案為 customer-awaiting-delivery-order.php 再來改內容描述就完成拉!

搭配 [WooCommerce] 搭配修改信件、預覽發信的工具 – Preview E-mails for WooCommerce 這套工具拉預覽結果很方便!

後記

其實從註冊一個新的訂單狀態到根據這個訂單狀態對應觸發的事件都有滿多連動的功能要處理。

當然最簡單只是開一個狀態的分類出來歸類訂單是沒問題,但也不能不考慮到前端客戶端查詢訂單的時候對應的呈現部分。

比方說,是否要開放全部的訂單狀態輸出訂單列表?

// 訂單列表全狀態顯示
function mxp_woocommerce_my_account_my_orders_query($args) {
        $args['post_status'] = array_keys(wc_get_order_statuses());
        return $args;
}
add_filter('woocommerce_my_account_my_orders_query', 'mxp_woocommerce_my_account_my_orders_query', 11, 1);

還有把訂單狀態納入「已付款」的內建判斷方法內:

// 註冊「已付款」的狀態類別
function mxp_woocommerce_order_is_paid_statuses($status) {
        return array('processing', 'completed', 'awaiting-delivery');
}
add_filter('woocommerce_order_is_paid_statuses', 'mxp_woocommerce_order_is_paid_statuses', 11, 1);

最後還有修改其他狀態的名稱之類的操作:


// 修改其他狀態對應名稱
function mxp_woocommerce_register_shop_order_post_statuses($statuses) {
    // 其他狀態還要考量搭配金流來決定保留或修改與否
    $statuses['wc-pending'] = array(
        'label'                     => '預留訂單',
        'public'                    => false,
        'exclude_from_search'       => false,
        'show_in_admin_all_list'    => true,
        'show_in_admin_status_list' => true,
        'label_count'               => _n_noop('預留訂單 (%s)', '預留訂單 (%s)', 'woocommerce'));
    return $statuses;
}
add_filter('woocommerce_register_shop_order_post_statuses', 'mxp_woocommerce_register_shop_order_post_statuses', 11, 1);

其他關於發信機制參考的筆記:


Share:

作者: Chun

資訊愛好人士。主張「人人都該為了偷懶而進步」。期許自己成為斜槓到變進度條 100% 的年輕人。[///////////____36%_________]

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *


文章
Filter
Apply Filters
Mastodon