WordPress+WooCommerce でネットショップ構築すると、「注文する」で確認ダイアログも注文確認画面も出ずに、速攻受注処理が走って完了画面になる。
日本以外ではそれが当たり前らしく、本体にそのような機能は取り入れられなかったらしい。
なので、確認ダイアログを出すことにトライ。数日がかりでようやく動いた。
オリジナルのソースに手を入れることなく、ググった英語のページを参考に、PHP・jsそれぞれのトリガー・フックでのカスタマイズ記述のみで対応した。
- 動作
・WooCommerceのエラーがあれば、そのエラー表示
・WooCommerceのエラーがなければ、確認ダイアログ表示 → OKで受注処理、完了画面。キャンセルで元の画面。
エラーチェックの後に確認ダイアログを出すことにこだわった。 - 方針
・submitされた時に、confirm用のjsで拾う
・php側、class-wc-checkout.php のvalidateの後、受注処理が走る前に抜けてjsに戻る
・戻ってきたjs側でダイアログを表示する - 修正
(1)/(子テーマ)/woocommerce/checkout/payment.php
※Woocommerceの該当フォルダから、子テーマにコピーし、submitボタン周りを修正する。
【参考】Woocommerceの該当フォルダについて
WooCommerceのカスタマイズ方法
※今回は「storefront」を親テーマとした。<input type="hidden" value="0" name="chkcfm"><!-- 追記。これがconfirmであることのフラグとなる --> <?php echo apply_filters( 'woocommerce_order_button_html', '<button type="submit" onclick="javascript:document.checkout.chkcfm.value=1;" class="button alt" name="woocommerce_confirm_place_order" id="place_order3" value="' . esc_attr( $order_button_text ) . '" data-value="' . esc_attr( $order_button_text ) . '">' . esc_html( $order_button_text ) . '[確認]</button>' ); // @codingStandardsIgnoreLine ?> <!-- onclick()を追記する -->
(2)/(子テーマ)/function.php
以下、追記する。<?php //使用するスクリプト・CSSを登録する function __wc_add_scripts_checkout() { wp_enqueue_script( 'checkout-script', get_stylesheet_directory_uri() . '/assets/js/woocommerce/confirm_checkout.js', array( 'jquery' ) ); wp_enqueue_script( 'checkout-confirm-dlg-script', get_stylesheet_directory_uri() . '/assets/jquery.confirm/jquery.confirm.js', array( 'jquery' ) ); wp_enqueue_style( 'checkout-confirm-dlg-css', get_stylesheet_directory_uri() . '/assets/jquery.confirm/jquery.confirm.css', "" ); } add_action( 'woocommerce_before_checkout_form', '__wc_add_scripts_checkout'); //WooCommerceのsubmit時のvalidate後に実行する。 // /woocommerce/includes/class-wc-checkout.php validate_checkout() //エラーなしなら、result='confirm_checkout'を返す function __wc_comfirm_checkout($data, $errors) { if ( $_POST['chkcfm'] == 1 ) { if (count($errors->errors) <= 0) { $response = array( 'result' => 'confirm_checkout', ); unset( WC()->session->refresh_totals, WC()->session->reload_checkout ); wp_send_json( $response ); exit; } } } add_action('woocommerce_after_checkout_validation', '__wc_comfirm_checkout', 10, 2);
(3)/(子テーマ)/assets/js/woocommerce/confirm_checkout.js
以下、新規作成する。jQuery( function( $ ) { var checkout_form = $( 'form.checkout' ); //checkout.js の submitで、受注処理実行前に実行されるハンドラ checkout_form.on( 'checkout_place_order', function() { var $form = $( this ); if ($form.context.elements.chkcfm.value == 0) { return true; } $form.addClass( 'processing' ); var form_data = $form.data(); if ( 1 !== form_data['blockUI.isBlocked'] ) { $form.block({ message: null, overlayCSS: { background: '#fff', opacity: 0.6 } }); } $.ajax({ type: 'POST', url: wc_checkout_params.checkout_url, data: $form.serialize(), dataType: 'json', success: function( result ) { try { if ( 'confirm_checkout' === result.result ) { show_confirm_checkout_dlg($form); return false; } else if ( 'failure' === result.result ) { throw 'Result failure'; } else { throw 'Invalid response'; } } catch( err ) { // Reload page if ( true === result.reload ) { window.location.reload(); return; } // Trigger update in case we need a fresh nonce if ( true === result.refresh ) { $( document.body ).trigger( 'update_checkout' ); } // Add new errors if ( result.messages ) { confirm_checkout_error( result.messages ); } else { confirm_checkout_error( '<div class="woocommerce-error">' + wc_checkout_params.i18n_checkout_error + '</div>' ); } } }, error: function( jqXHR, textStatus, errorThrown ) { confirm_checkout_error( '<div class="woocommerce-error">' + errorThrown + '</div>' ); } }); checkout_form.removeClass( 'processing' ).unblock(); return false; }); //ダイアログを表示し、OKならsubumitし、受注処理を実行する function show_confirm_checkout_dlg($obj) { $.confirm({ 'title' : '注文確認', 'message' : 'この内容で注文処理を行います', 'buttons' : { 'OK' : { 'action': function(){ //「confirmでない」フラグをたてる $obj.context.elements.chkcfm.value = 0; //submitする $obj.submit(); return true; } }, 'キャンセル': { 'action': function(){ $obj.removeClass( 'processing' ).unblock(); return false; } } } }); } //エラー処理。 // 本来は、wc_checkout_form.submit_error()、wc_checkout_form.scroll_to_notices()を呼びたいが… function confirm_checkout_error( error_message ) { $form = checkout_form; $( '.woocommerce-NoticeGroup-checkout, .woocommerce-error, .woocommerce-message' ).remove(); $form.prepend( '<div class="woocommerce-NoticeGroup woocommerce-NoticeGroup-checkout">' + error_message + '</div>' ); $form.removeClass( 'processing' ).unblock(); $form.find( '.input-text, select, input:checkbox' ).trigger( 'validate' ).blur(); var scrollElement = $( '.woocommerce-NoticeGroup-updateOrderReview, .woocommerce-NoticeGroup-checkout' ); if ( ! scrollElement.length ) { scrollElement = $( '.form.checkout' ); } $.scroll_to_notices( scrollElement ); $( document.body ).trigger( 'checkout_error' ); } });
(4)ダイアログ。jQueryプラグインのConfirmを利用している。
置き場所はどこでもよい。以下は例。
/(子テーマ)/assets/jquery.confirm/jquery.confirm.js
/(子テーマ)/assets/jquery.confirm/jquery.confirm.css※DL元
How to Create a jQuery Confirm Dialog Replacementcssのみ、レスポンシブ対応と、ボタン表示不具合を修正した。以下。
モバイル用
該当箇所を修正。
※ダイアログが中央に来ません。すみません。#confirmBox .button{ display:inline-block; background:url('buttons.png') no-repeat; color:white; position:relative; height: 33px; font:17px/33px 'Cuprum','Lucida Sans Unicode', 'Lucida Grande', sans-serif; margin-right: 15px; padding: 0 35px 0 40px; text-decoration:none; border:none; }
PC用
追記。@media (min-width: 768px) { #confirmBox{ background:url('body_bg.jpg') repeat-x left bottom #e5e5e5; width:460px; position:fixed; left:50%; top:50%; margin:-130px 0 0 -230px; border: 1px solid rgba(33, 33, 33, 0.6); -moz-box-shadow: 0 0 2px rgba(255, 255, 255, 0.6) inset; -webkit-box-shadow: 0 0 2px rgba(255, 255, 255, 0.6) inset; box-shadow: 0 0 2px rgba(255, 255, 255, 0.6) inset; }
ボタン表示不具合対応。最後の1行「transform: scaleX(-1);」を追記。
#confirmBox .button span{ position:absolute; top:0; right:-5px; background:url('buttons.png') no-repeat; width:5px; height:33px; transform: scaleX(-1); }
以上で、動くはず。
Google Chrome最新バージョンでのみ動作確認済み。その他は不明です。
修正前にはバックアップを取るなど、自己責任でどうぞ。。。 - 【参考】
Hooking into WooCommerce’s checkout JS events
※checkout.jsでのイベントフックにものすごく役立った。Adding custom functionality to a WooCommerce checkout
アラート画面のデザインを自由にカスタマイズ!警告表示のダイアログのUI機能をjQueryプラグインConfirmで印象をガラッと変更する方法!