WordPress教學 – ATM匯款通知

網拍很常看到匯款到固定的銀行帳戶,並要求客人回報銀行的末5碼,這個「通知匯款」功能比我想像中的簡單,相對「超商取貨」功能就難很多。原理就是在訂單檢視的畫面裡多顯示2個輸入框給客人輸入,然後存進database裡。

在讀這篇前你需要先會2個 wordpresss 指令 update_post_meta 和 get_post_meta


Step 1: 前台的畫面

請修改 yourtheme/woocommerce/order/order-details.php :


Step 2: 前台的條列頁

增加判斷訂單付款是用  ATM,狀態是 on-hold ,就增加一個「通知匯款」的按鈕,這個按鈕的內容和「查看」一樣,就是在 url 裡多加  ?atm=1
url: https://your-domain.com/my-account/orders/

修改程式在:yourtheme/woocommerce/myaccount/orders.php

在這裡增加 on-hold 的判斷:

if($order->get_status() == "on-hold") { ... }

增加付款方式是「銀行匯款」的判斷:

if ('bacs' === $order->get_payment_method()) { ... }

附註:學習 woocommerce order object
https://docs.woocommerce.com/wc-apidocs/class-WC_Order.html

修改完的執行畫面:

  • 說明1:畫面裡有二筆訂單,「待匯款」的訂單會顯示「通知匯款」功能。
  • 說明2:「已通知匯款」的訂單,會顯示「更新匯款帳號」的功能,來重新送出打錯的資料。
  • 說明3:已「取消」的訂單,只需顯示「查看」功能。

Step 3: 後台的 Billing Address 要增加 atm_code 和 atm_datetime

程式 yourtheme/functions.php 在這一篇裡有附:
WordPress教學 – 動態欄位必填檢查
https://stackoverflow.max-everyday.com/2017/04/wordpress-dynmanic-fields-checkout/

需要了解一下 WooCommerce Custom Order Status

  • Payment Pending
  • Processing
  • On Hold (ATM 匯款,訂單會停在 on-hold 狀態)
  • Completed
  • Cancelled
  • Refunded
  • Failed

如果需要增加新的狀態,參考這一篇:
How To Create WooCommerce Custom Order Status
https://www.cloudways.com/blog/create-woocommerce-custom-order-status/


yourtheme/woocommerce/order/order-details.php 的 部份source code 如下,黑字就不用去看,看紅字部份即可:

<?php
$order_items           = $order->get_items( apply_filters( 'woocommerce_purchase_order_item_types', 'line_item' ) );
$show_purchase_note    = $order->has_status( apply_filters( 'woocommerce_purchase_note_order_statuses', array( 'completed', 'processing' ) ) );
$show_customer_details = is_user_logged_in() && $order->get_user_id() === get_current_user_id();
$downloads             = $order->get_downloadable_items();
$show_downloads        = $order->has_downloadable_item() && $order->is_download_permitted();

function send_notification($order_id, $atm_code, $atm_datetime) {
$to = get_option( ‘admin_email’ );
$shop_title = get_option( ‘blogname’ );

$datetime = date (“Y-m-d H:i:s” , mktime(date(‘H’)+8, date(‘i’), date(‘s’), date(‘m’), date(‘d’), date(‘Y’)));
$subject = ‘您在 [‘.$shop_title.’] 的匯款通知 (‘.$order_id.’) – ‘.$datetime;
$message = “您已收到一筆新的匯款,\n<br/>訂單編號:<a href=’http://moca-shop.com/wp-admin/post.php?post=$order_id&action=edit’>”.$order_id.”</a>\n<br/>匯款日期:”.$atm_datetime.”\n<br/>匯款帳號末5碼:”.$atm_code;

$headers = “Content-Type: text/html\r\n”;
$attachments = “”;
wc_mail( $to, $subject, $message, $headers, $attachments);

if ( $show_downloads ) {
wc_get_template( ‘order/order-downloads.php’, array( ‘downloads’ => $downloads, ‘show_title’ => true ) );
}

/**
* Get bank details and place into a list format.
*
* @param int $order_id
*/
// BACS account fields shown on the thanks page and in emails
$account_details = get_option( ‘woocommerce_bacs_accounts’,
array(
array(
‘account_name’ => get_option( ‘account_name’ ),
‘account_number’ => get_option( ‘account_number’ ),
‘sort_code’ => get_option( ‘sort_code’ ),
‘bank_name’ => get_option( ‘bank_name’ ),
‘iban’ => get_option( ‘iban’ ),
‘bic’ => get_option( ‘bic’ ),
),
)
);
$bacs_accounts = apply_filters( ‘woocommerce_bacs_accounts’, $account_details);

if ( ! empty( $bacs_accounts ) ) {
$account_html = ”;
$has_details = false;

$bacs_account_index=0;
foreach ( $bacs_accounts as $bacs_account ) {
$bacs_account_index+=1;
$bacs_account = (object) $bacs_account;

if($bacs_account_index>1) {
$account_html .= ‘<p>或是匯款到:</p>’;
}

$account_html .= ‘<ul class=”wc-bacs-bank-details customer_details bacs_details”>’ . PHP_EOL;

// BACS account fields shown on the thanks page and in emails
$account_fields = apply_filters( ‘woocommerce_bacs_account_fields’, array(
‘account_name’ => array(
‘label’ => __( ‘Account name’, ‘woocommerce’ ),
‘value’ => $bacs_account->account_name,
),
‘bank_name’ => array(
‘label’ => __( ‘Bank’, ‘woocommerce’ ),
‘value’ => $bacs_account->bank_name,
),
‘account_number’ => array(
‘label’ => __( ‘Account number’, ‘woocommerce’ ),
‘value’ => $bacs_account->account_number,
),
), $order_id );

foreach ( $account_fields as $field_key => $field ) {
if ( ! empty( $field[‘value’] ) ) {
$account_html .= ‘<li class=”‘ . esc_attr( $field_key ) . ‘”>’ . wp_kses_post( $field[‘label’] ) . ‘: <strong>’ . wp_kses_post( wptexturize( $field[‘value’] ) ) . ‘</strong></li>’ . PHP_EOL;
$has_details = true;
}
}

$order_atm_code = get_post_meta($order_id, ‘atm_code’, true);
$order_atm_datetime = get_post_meta($order_id, ‘atm_datetime’, true);
// check if the custom field has a value
if($order_atm_code != ”) {
$field_key = ‘匯款帳號末5碼’;
$account_html .= ‘<li class=”‘ . esc_attr( $field_key ) . ‘”>’ . wp_kses_post( $field_key ) . ‘: <strong>’ . wp_kses_post( wptexturize( $order_atm_code ) ) . ‘</strong></li>’ . PHP_EOL;
if($order_atm_code != ”) {
$field_key = ‘匯款通知日期’;
$account_html .= ‘<li class=”‘ . esc_attr( $field_key ) . ‘”>’ . wp_kses_post( $field_key ) . ‘: <strong>’ . wp_kses_post( wptexturize( $order_atm_datetime ) ) . ‘</strong></li>’ . PHP_EOL;
}

if($order->get_status() == “on-hold”) {
// hide bacs info block for payed user.
$has_details = false;
}
}
$account_html .= ‘</ul>’;
}

if ( $has_details ) {
echo ‘<section class=”woocommerce-bacs-bank-details”><h2 class=”wc-bacs-bank-details-heading”>’ . __( ‘Our bank details’, ‘woocommerce’ ) . ‘</h2>’ . PHP_EOL . $account_html . ‘</section>’;
}
}

if (isset($_GET[‘atm_code’])) {
$atm_code_url = (string)$_GET[‘atm_code’];
$atm_datetime = (string)$_GET[‘atm_datetime’];
if(strlen($atm_code_url)==5 && is_numeric($atm_code_url)) {
//echo ‘update atm code’;
update_post_meta($order_id,’atm_code’,$atm_code_url);

//$datetime = date (“Y-m-d H:i:s” , mktime(date(‘H’)+8, date(‘i’), date(‘s’), date(‘m’), date(‘d’), date(‘Y’))) ;
update_post_meta($order_id,’atm_datetime’, $atm_datetime);
send_notification($order_id, $atm_code_url, $atm_datetime);
echo ‘<script language=”javascript”>window.location = “/my-account/orders/”;</script>’;
}
}

if (isset($_GET[‘atm’])) {
$atm_url = (string)$_GET[‘atm’];
if($atm_url==”1″) {
$post_url = “/my-account/view-order/”.$order_id.”/”;
$atm_html=””;
$atm_html=$atm_html.'<h2 class=”woocommerce-order-details__title”>通知匯款</h2>’;
$atm_html=$atm_html.'<form name=”atm_form” method=”GET” action=”‘.$post_url.'” onsubmit=”return check_atm();”><ul class=”wc-bacs-bank-details customer_details bacs_details”>’;
$atm_html=$atm_html.'<li>匯款日期: <input name=”atm_datetime” id=”atm_datetime” type=”text” value=”” size=”20″ maxlength=”30″ style=”ime-mode: disabled”/></li>’;
$atm_html=$atm_html.'<li>匯款帳號末5碼: <input name=”atm_code” id=”atm_code” type=”text” value=”” maxlength=”5″ style=”ime-mode: disabled”/> <input type=”submit” value=”確定” /></li>’;
$atm_html=$atm_html.'</ul></form>’;
echo $atm_html;
}
}

?>
<script type=”text/javascript”>
jQuery(document).ready(function(){
jQuery(‘#atm_datetime’).datepicker({
dateFormat: ‘yy-mm-dd’,
dayNames:[“星期日”,”星期一”,”星期二”,”星期三”,”星期四”,”星期五”,”星期六”],
dayNamesMin:[“日”,”一”,”二”,”三”,”四”,”五”,”六”],
monthNames:[“一月”,”二月”,”三月”,”四月”,”五月”,”六月”,”七月”,”八月”,”九月”,”十月”,”十一月”,”十二月”],
monthNamesShort:[“一月”,”二月”,”三月”,”四月”,”五月”,”六月”,”七月”,”八月”,”九月”,”十月”,”十一月”,”十二月”],
prevText:”&#x3C;上月”,
nextText:”下月&#x3E;”,
firstDay: 1,
isRTL: false,
showMonthAfterYear: true,
yearSuffix: ‘年’,
weekHeader:”週”
});
});

function check_atm() {
var element = document.getElementById(‘atm_code’);
if (typeof element !== “undefined”) {
if(element.value == ”) {
alert (“請輸入「匯款帳號末5碼」”);
element.focus();
return false;
}
if(element.value.length != 5) {
alert (“「匯款帳號末5碼」長度不正確”);
element.focus();
return false;
}
}
element = document.getElementById(‘atm_datetime’);
if (typeof element !== “undefined” && element.value == ”) {
element.focus();
alert (“請輸入「匯款日期」”);
return false;
}
return true;
}
</script>

<section class=”woocommerce-order-details”>
<?php do_action( ‘woocommerce_order_details_before_order_table’, $order ); ?>

<h2 class=”woocommerce-order-details__title”><?php _e( ‘Order details’, ‘woocommerce’ ); ?></h2>

<table class=”woocommerce-table woocommerce-table–order-details shop_table order_details”>

<thead>
<tr>
<th class=”woocommerce-table__product-name product-name”><?php _e( ‘Product’, ‘woocommerce’ ); ?></th>
<th class=”woocommerce-table__product-table product-total”><?php _e( ‘Total’, ‘woocommerce’ ); ?></th>
</tr>
</thead>

<tbody>
<?php
do_action( ‘woocommerce_order_details_before_order_table_items’, $order );

foreach ( $order_items as $item_id => $item ) {
$product = $item->get_product();

wc_get_template( ‘order/order-details-item.php’, array(
‘order’ => $order,
‘item_id’ => $item_id,
‘item’ => $item,
‘show_purchase_note’ => $show_purchase_note,
‘purchase_note’ => $product ? $product->get_purchase_note() : ”,
‘product’ => $product,
) );
}

do_action( ‘woocommerce_order_details_after_order_table_items’, $order );
?>
</tbody>

<tfoot>
<?php
foreach ( $order->get_order_item_totals() as $key => $total ) {
?>
<tr>
<th scope=”row”><?php echo $total[‘label’]; ?></th>
<td><?php echo ( ‘payment_method’ === $key ) ? esc_html( $total[‘value’] ) : $total[‘value’]; ?></td>
</tr>
<?php
}
?>
<?php if ( $order->get_customer_note() ) : ?>
<tr>
<th><?php _e( ‘Note:’, ‘woocommerce’ ); ?></th>
<td><?php echo wptexturize( $order->get_customer_note() ); ?></td>
</tr>
<?php endif; ?>
</tfoot>
</table>

<?php do_action( ‘woocommerce_order_details_after_order_table’, $order ); ?>
</section>

<?php
if ( $show_customer_details ) {
wc_get_template( ‘order/order-details-customer.php’, array( ‘order’ => $order ) );
}


為了要讓 order-detail 裡出現匯款的資料,所以我面增加了上面的 code,但上面的 code 會造成訂單成立時,顯示2次「我們的銀行匯款資訊」,解法:

修改程式檔案:yourtheme/woocommerce/checkout/thankyou.php

服用下面的 code:

<?php 
if ('bacs' !== $order->get_payment_method()) {
do_action( 'woocommerce_thankyou_' . $order->get_payment_method(), $order->get_id() ); 
}
?>
<?php do_action( 'woocommerce_thankyou', $order->get_id() ); ?>

<?php
if ('bacs' === $order->get_payment_method()) {
$order_id=$order->get_id();
echo '<script language="javascript">function start_notify(){window.location = "/my-account/view-order/' . $order_id . '?atm=1"};</script>';

$atm_html="";
$atm_html=$atm_html.'如果你已經匯好貨款請在「<a href="/my-account" title="我的帳號">我的帳號</a>」→「<a href="/my-account/orders/" title="訂單">訂單</a>」→「通知匯款」,或直接點右面的按扭:';
$atm_html=$atm_html.'<input type="button" value="通知匯款" onclick="javascript:start_notify();"/>';
echo $atm_html;
}
?>

修改後的執行畫面:


我姐姐的網站:http://moca-shop.com/

如果需要我幫忙修改您的網站的php 程式,歡迎與我聯絡,這一個ATM匯款功能費用是NT$4,000元。

  • 附註1:這個金額是一次性的修改,不包含後續程式的維護,謝謝。
  • 附註2:在WordPress 裡升級「主題」(theme) 也許會造成已修改的程式被覆蓋,會因為升級造成功能消失。針對這一個可能會發生的情況,我會把針對您主題裡修改好的程式先打包一份給您,如果遇到升級造成功能消失,直接把舊的.php程式檔案覆蓋回去即可。
  • 附註3:除此之下,升級 WooCommerce這一個外掛,如果官方如果大改了架構或是修改了共用的相關副程式也許也會造成功能執行結果不符合預期,後續的維護都不包括在我們協助建置的費用裡。

Comments

  1. 你好想請問,若請你加上這個ATM回報功能或者做成外掛,是如何收費呢~ 感謝~

    1. 目前的code離可以賣的外掛還有一段距離 Q_Q;, 要可以和您即有的系統並存,需要增加更多的彈性在外掛裡。我也不知道這能賣多少錢。

  2. 您好~打擾一下,對於步驟二的在 url 裡多加 ?atm=1 ,這部分是改orders.php這個檔案嗎?是否也有參考檔案呢?感謝您~

  3. 您好,看完您的文章後我們的網站想請您協助php的部分,我們可以付費,是否方便留下聯絡方式?

  4. 您好 我嘗試照著上面的做法做 但是在Step 2加上
    if($order->get_status() == “on-hold”) { … }
    if (‘bacs’ === $order->get_payment_method()) { … }
    的時候 我的訂單管理那邊訂單完全都看不到了><
    其他部分都有成功 謝謝您的教學:)

  5. 您好,感謝您的分享,我試著做了看看發現很有用,但同時也發現了幾個問題點。

    1.這功能在填寫完匯款通知後那個按鈕好像不會消失…

    2.客戶填寫完匯款通知後,我方並不會收到任何通知(例如Email)

    以上兩點是否有甚麼能改善的辦法?有費用上的問題也請告知,謝謝

    1. 1:已修改為不會消失,針對已匯款的訂單增加「修改匯款帳號」的功能。
      2:php 寄發 email 很簡單,google 一下有很多範例。

  6. 您好 請問Step2 我把 ?atm放在get_view_order_url($atm=1) )是這樣嗎><
    感覺沒動作 應該是這部分出錯xD

發佈留言

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