最近我們有一案主是使用WooCommerce的臺灣電商賣家,需要重整、客製化結帳欄位,讓他們的網路商店更契合臺灣市場。也就是說,要把姓氏放在名字之前,以及重整地址欄位,把城市欄放在街道欄之前。此外,我們也針對縣市和行政區欄位設計了下拉式選單,當顧客選擇某個縣市,JavaScript就會載入該縣市的行政區列表。
重整欄位的最後一個步驟,是修改電話號碼輸入的驗證機制,讓欄位只接受臺灣電話號碼。
我們決定開發一個外掛來蓋過WooCommerce內建的結帳欄位。我們的外掛目錄包括以下這些檔案:

主檔案bdigital-checkout.php 裡,我們加進動作和空值函式,如下:
<?php
/* Plugin Name: Bdigital Custom Taiwan Checkout */
defined( 'ABSPATH' ) or die( 'No script kiddies please!' );
add_filter( 'woocommerce_checkout_fields' , 'bdigital_checkout_fields', 999 );
function bdigital_checkout_fields(){ }
調整結帳欄位順序的說明資源較為少見,但根據我們的經驗,要有效處理結帳欄位順序,需要做到以下三件事:
1) 利用CSS類別,修改姓名欄位順序
我們想保留WooCommerce 預設姓名欄位的一直線設計,但要把姓氏和名字的順序對調。所以我們在外掛功能中調整了CSS類別(class)。
2) 調整欄位資料優先權(data-priority)
更新每組欄位的資料優先屬性。
3) 用以下函式重整欄位陣列
我們加了一個新函式來保持程式碼乾淨。這個函式會根據我們放進陣列的內容重整欄位,也可以用來刪除不需要的欄位 – 這個專案裡,我們刪除了地址裡的「州」,並把地址第二行用來填入行政區。
以下是我們寫的程式碼:
function bdigital_checkout_fields(){
...
$fields['billing']['billing_last_name']['priority'] = 4;
$fields['billing']['billing_last_name']['class'] = array('form-row-first');
$fields['billing']['billing_first_name']['priority'] = 8;
$fields['billing']['billing_first_name']['class'] = array('form-row-last');
$fields['shipping']['shipping_last_name']['priority'] = 4;
$fields['shipping']['shipping_last_name']['class'] = array('form-row-first');
$fields['shipping']['shipping_first_name']['priority'] = 8;
$fields['shipping']['shipping_first_name']['class'] = array('form-row-last');
$order = array(
'billing_last_name',
'billing_first_name',
'billing_company',
'billing_city',
'billing_address_2',
'billing_address_1',
'billing_postcode',
'billing_phone',
'billing_email'
);
$priority = 10;
foreach($order as $field){
$fields2['billing'][$field] = $fields['billing'][$field];
$fields2['billing'][$field]['priority'] = $priority;
$priority++;
}
$order = array(
'shipping_last_name',
'shipping_first_name',
'shipping_company',
'shipping_city',
'shipping_address_2',
'shipping_address_1',
'shipping_postcode'
); $priority = 10;
foreach($order as $field){
$fields2['shipping'][$field] = $fields['shipping'][$field];
$fields2['shipping'][$field]['priority'] = $priority;
$priority++;
}
$fields2['order'] = $fields['order'];
$fields2['account'] = $fields['account'];
return $fields2;
}
接下來,我們做了縣市和行政區的下拉式選單,而且讓行政區的選項因應顧客所選的縣市自動調整。這個功能是透過AJAX呼叫,重整行政區選單中的選項。
function bdigital_checkout_fields($fields){
...
$fields['shipping']['shipping_city']['options'] = $cities;
$fields['billing']['billing_address_2']['type'] = 'select';
$fields['billing']['billing_address_2']['options'] = array('' => __('Select District'));
$fields['shipping']['shipping_address_2']['type'] = 'select';
$fields['shipping']['shipping_address_2']['options'] = array('' => __('Select District'));
...
}
add_filter( 'wp_footer', 'bdigital_checkout_script' );
function bdigital_checkout_script( ){
if( ! is_checkout() ) return;
?>
<script type="text/javascript">
jQuery(function($) {
$('#billing_city').on('change', function () {
var city = document.getElementById('billing_city').value;
$.ajax({
url: "<?php echo plugin_dir_url(__FILE__); ?>districts.php",
type: "get",
data: {
'city': city
},
success: function (result) {
document.getElementById('billing_address_2').innerHTML = result;
}
})
})
});
jQuery(function($) {
$('#shipping_city').on('change', function () {
var city = document.getElementById('shipping_city').value;
$.ajax({
url: "<?php echo plugin_dir_url(__FILE__); ?>districts.php",
type: "get",
data: {
'city': city
},
success: function (result) {
document.getElementById('shipping_address_2').innerHTML = result;
}
})
})
});
}
We 至於臺灣縣市、行政區清單的資料來源,是我們從開源取得的JSON(JavaScript Object Notation,JavaScript物件表示法)列表。
畫龍點睛的最後一步,是修改電話號碼驗證機制,讓欄位只接受臺灣電話號碼,目的是方便整合電子發票和快遞平台。
add_action('woocommerce_checkout_process', 'bdigital_validate_billing_phone');
function bdigita_validate_billing_phone() {
$match = preg_match('/^(?=(09))[0-9]{10}$/', $_POST['billing_phone']);
if ( $_POST['billing_phone'] && !$match) {
wc_add_notice( __( $_POST['billing_phone'].' is not a valid Taiwan phone number.' ), 'error' );
}
}
如果想參考完整程式碼,或把這個外掛用在自己的臺灣電商網站,歡迎從Github取得我們的程式碼。