最後更新:2026/10/25
在台灣開網店,結帳時最常被問的兩句話是「可以打統編嗎?」和「發票可以存到手機條碼嗎?」。WooCommerce 是國外的系統,結帳頁本來沒有這些欄位,很多店家只好請客人寫在訂單備註裡,結果有人寫在備註、有人另外傳 LINE、有人統編少打一碼,開發票時才發現。
這篇在新版的區塊結帳頁加上一組發票欄位:先選發票類型,選「公司」才出現統一編號和公司抬頭,選「捐贈」才出現捐贈碼;統一編號還會照財政部公告的檢查碼規則,在客人按下單時就先檢查一次。
先說清楚一件事:這段程式碼只負責把客人的發票資料收齊、存進訂單,開立電子發票還是要靠你使用的電子發票服務。如果你用的電子發票外掛已經有自己的發票欄位,就不需要再加這一段。
不想自己改?把這篇交給 AI
把這篇的網址(或全文)連同下面這段話貼給 AI:
我的網站是 WordPress,有裝 WooCommerce。我想照下面這篇文章,在結帳頁加上發票欄位(發票類型、手機條碼、統一編號、公司抬頭、捐贈碼)。
請先問我:我的結帳頁是新版區塊結帳還是傳統結帳、有沒有裝電子發票外掛、我要提供哪幾種發票類型、選項文字要怎麼寫。
問清楚之後,再一步一步告訴我:要用哪一段程式碼、貼在哪裡、哪些地方要換成我自己的資料,以及改完怎麼測試。
如果文章的做法不適合我的網站,請直接告訴我原因和替代做法。
文章:(貼上這篇的網址,或整篇內容)
改之前先備份,密碼不要貼給 AI。
先認識這幾個欄位的格式
台灣的電子發票,消費者常用的有三種開法:存在載具裡(店家的會員載具,或客人自己的手機條碼)、打統一編號開給公司、捐贈給公益團體。每一種要填的資料不一樣:
手機條碼載具一共 8 碼,第 1 碼是「/」,後面 7 碼是數字、大寫英文字母,或「+」「-」「.」三種符號。統一編號是 8 位數字,最後一位是檢查碼,打錯一個數字通常就算不出來。捐贈碼也叫愛心碼,是 3 到 7 位數字。
這些規則可以先在結帳頁檢查格式,擋掉打錯字的情況;但格式對,不代表號碼一定存在。手機條碼是不是真的有人申請過、捐贈碼是哪個團體,要用電子發票服務提供的查詢功能才能確認。
完整程式碼
// 第 112 篇:WooCommerce 結帳頁加發票欄位(個人、公司統編、捐贈),新版區塊結帳頁
// 統一編號檢查:8 位數字,每一位乘上 1、2、1、2、1、2、4、1,乘積的十位數和個位數相加,全部加總後能被 5 整除
// (財政部 112 年 4 月起的新規則;舊規則是被 10 整除,能被 10 整除的也一定能被 5 整除,所以舊號碼照樣通過)
function mimi_check_tax_id($id) {
if (!preg_match('/^\d{8}$/', $id)) {
return false;
}
$weights = [1, 2, 1, 2, 1, 2, 4, 1];
$sum = 0;
foreach (str_split($id) as $i => $digit) {
$p = (int) $digit * $weights[$i];
$p = intdiv($p, 10) + $p % 10; // 乘積拆成十位數+個位數
$sum += intdiv($p, 10) + $p % 10; // 只有 7×4=28 會加出 10,再拆一次變成 1
}
if ($sum % 5 === 0) {
return true;
}
// 第 7 位是 7 的時候,那一位可以算 1 也可以算 0,兩種有一種能整除就算對
return $id[6] === '7' && ($sum - 1) % 5 === 0;
}
// 條件:「發票類型」選了某一種
function mimi_invoice_is($type) {
return ['checkout' => ['properties' => ['additional_fields' => ['properties' => [
'mimi/invoice-type' => ['const' => $type],
]]]]];
}
function mimi_invoice_is_not($type) {
return ['checkout' => ['properties' => ['additional_fields' => ['properties' => [
'mimi/invoice-type' => ['not' => ['const' => $type]],
]]]]];
}
add_action('woocommerce_init', function () {
if (!function_exists('woocommerce_register_additional_checkout_field')) {
return;
}
// 1. 發票類型(必選)
woocommerce_register_additional_checkout_field([
'id' => 'mimi/invoice-type',
'label' => '發票類型',
'location' => 'order',
'type' => 'select',
'required' => true,
'options' => [
['value' => 'personal', 'label' => '個人(存在會員載具,可歸戶手機條碼)'],
['value' => 'company', 'label' => '公司(開立統一編號)'],
['value' => 'donate', 'label' => '捐贈發票'],
],
]);
// 2. 個人:手機條碼載具(選填),格式是「/」加 7 碼數字、大寫英文或 + - .
woocommerce_register_additional_checkout_field([
'id' => 'mimi/carrier',
'label' => '手機條碼載具',
'location' => 'order',
'type' => 'text',
'required' => false,
'hidden' => mimi_invoice_is_not('personal'),
'sanitize_callback' => function ($value) {
return strtoupper(trim($value));
},
'validate_callback' => function ($value) {
if ($value !== '' && !preg_match('~^/[0-9A-Z.+-]{7}$~', $value)) {
return new WP_Error('mimi_carrier', '手機條碼載具格式不對:第 1 碼是「/」,後面 7 碼是數字、大寫英文或 + - . 符號。');
}
},
]);
// 3. 公司:統一編號、公司抬頭(選公司才出現,而且必填)
woocommerce_register_additional_checkout_field([
'id' => 'mimi/tax-id',
'label' => '統一編號',
'location' => 'order',
'type' => 'text',
'required' => mimi_invoice_is('company'),
'hidden' => mimi_invoice_is_not('company'),
'sanitize_callback' => function ($value) {
return preg_replace('/\s+/', '', $value);
},
'validate_callback' => function ($value) {
if ($value !== '' && !mimi_check_tax_id($value)) {
return new WP_Error('mimi_tax_id', '統一編號好像打錯了,請再確認一次(8 位數字)。');
}
},
]);
woocommerce_register_additional_checkout_field([
'id' => 'mimi/company-title',
'label' => '公司抬頭',
'location' => 'order',
'type' => 'text',
'required' => mimi_invoice_is('company'),
'hidden' => mimi_invoice_is_not('company'),
]);
// 4. 捐贈:捐贈碼(愛心碼),3 到 7 位數字
woocommerce_register_additional_checkout_field([
'id' => 'mimi/donate-code',
'label' => '捐贈碼(愛心碼)',
'location' => 'order',
'type' => 'text',
'required' => mimi_invoice_is('donate'),
'hidden' => mimi_invoice_is_not('donate'),
'validate_callback' => function ($value) {
if ($value !== '' && !preg_match('/^\d{3,7}$/', $value)) {
return new WP_Error('mimi_donate', '捐贈碼是 3 到 7 位數字,請再確認一次。');
}
},
]);
});
// 5. 客人先選「公司」填了統編、又改回「個人」時,藏起來的欄位不要留在訂單上
add_action('woocommerce_store_api_checkout_order_processed', function ($order) {
$keep = [
'personal' => ['carrier'],
'company' => ['tax-id', 'company-title'],
'donate' => ['donate-code'],
];
$type = $order->get_meta('_wc_other/mimi/invoice-type');
foreach (['carrier', 'tax-id', 'company-title', 'donate-code'] as $field) {
if (!in_array($field, $keep[$type] ?? [], true)) {
$order->delete_meta_data('_wc_other/mimi/' . $field);
}
}
$order->save();
});
程式碼放在 Code Snippets 這類外掛或子主題,放法和備份方式見〈WooCommerce 結帳頁改成台灣習慣〉。
程式碼各段做了什麼
最上面的 mimi_check_tax_id 是統一編號的檢查。財政部的算法是這樣:8 個數字依序乘上 1、2、1、2、1、2、4、1,每個乘積的十位數和個位數相加,再全部加總。以前的規則是加總要能被 10 整除;財政部為了讓統一編號有更多號碼可以用,112 年 4 月起改成能被 5 整除。能被 10 整除的數字一定也能被 5 整除,所以舊的統編照樣通過。第 7 位是 7 的時候有一個特例:那一位的乘積是 28,2 加 8 等於 10,這個 10 可以算成 1 也可以算成 0,兩種算法只要有一種能整除就算對,程式的最後一行就是在處理這個情況。
接著的 mimi_invoice_is 和 mimi_invoice_is_not 是兩個條件,意思分別是「發票類型選了某一種」和「沒有選這一種」。新版結帳頁加欄位的方法 woocommerce_register_additional_checkout_field,可以讓欄位依照其他欄位的值決定要不要出現、要不要必填,這兩個條件就是給它用的。
第 1 段是「發票類型」下拉選單,三個選項的文字可以照你的電子發票服務改,例如你的會員載具有自己的名稱,就寫進去。
第 2 段是手機條碼,只有選「個人」才出現,而且是選填;客人打小寫字母,程式會自動轉成大寫,再檢查格式。
第 3 段是統一編號和公司抬頭,只有選「公司」才出現,而且兩個都必填。統編中間打了空格也沒關係,程式會先把空格拿掉再檢查。
第 4 段是捐贈碼,只有選「捐贈」才出現,必填,檢查是不是 3 到 7 位數字。
第 5 段處理一個容易被忽略的情況:客人先選「公司」填了統編,後來改選「個人」,那個統編欄位雖然藏起來了,資料還是會一起送出。這一段在訂單建立時,把和發票類型不相符的欄位刪掉,避免訂單上同時出現「個人」和一組統編,讓開發票的人看不懂。
測試結果
我們在本機測試站(WordPress 7.1.3、WooCommerce 11.2.1,新版區塊結帳頁,Twenty Twenty-Five 佈景主題)實際下單:
- 結帳頁的「其他訂單資訊」一開始只有「發票類型」;選「個人」出現「手機條碼載具 (選填)」,選「公司」出現「統一編號」和「公司抬頭」,選「捐贈」出現「捐贈碼(愛心碼)」。
- 統編填 12345678 按下單,頁面出現「統一編號好像打錯了,請再確認一次(8 位數字)。」,訂單沒有送出;改成正確的統編就下單成功。
- 財政部公告附件裡的例子 04595257、04595252、10458575、10458574、10458570 都判斷為正確,12345678、少一碼、有英文字的都判斷為錯誤。
- 手機條碼打「/abc+123」,存進訂單的是「/ABC+123」;打「ABC1234」(少了斜線)會被擋下。
- 選公司但沒填統編或抬頭、選捐贈但沒填捐贈碼,都會被擋下來,提示是必填欄位。
- 先填了統編再改選「個人」,訂單上只留下發票類型,沒有殘留的統編。
- 下單後,謝謝頁、寄給客人和寄給店家的通知信、後台訂單頁,都看得到發票類型、統一編號和公司抬頭。
使用前要注意的事
這個方法只對新版的區塊結帳頁有效。如果你的結帳頁是傳統的短代碼版本,這些欄位不會出現;怎麼分辨是哪一種,見〈WooCommerce 結帳頁改成台灣習慣〉。傳統結帳頁通常由電子發票外掛提供欄位,或請工程師依外掛的方式另外寫。
欄位的資料存在訂單裡,開發票的人從後台訂單頁就看得到。如果要讓電子發票外掛自動讀取這些資料,要看外掛讀的是哪些欄位名稱,再請工程師對接,這部分每家外掛都不一樣。
格式檢查只能擋住打錯字,擋不住填了別人的統編。統編填錯開出去的發票,處理起來很麻煩,所以結帳頁的說明可以提醒客人「請確認統一編號正確,發票開立後無法更改抬頭」,實際的作廢、折讓規定,照你的電子發票服務說明。
發票這一關,決定了公司客戶會不會回來
對公司客戶來說,能不能順利拿到正確的發票,常常決定了下次還會不會跟你買。結帳頁把發票欄位做清楚,客人一次填對,你也不用在開發票時一筆一筆回頭確認。結帳頁還有哪些地方要改成台灣的習慣,可以看〈WooCommerce 結帳頁改成台灣習慣〉;想多問客人別的問題,可以看〈WooCommerce 訂單資料整理〉。
MIMI 專做客製化網頁設計,購物車電商網站的結帳流程、發票欄位,都可以依你的電子發票服務一起規劃。MIMI 提供台灣網頁設計服務,臺北、新北到全台灣的店家,都可以用電話、Email 直接和設計師討論;費用可以先看首頁的製作費用參考,歡迎聯絡 MIMI。
