WooCommerce Squareの日本語化~入力チェック

WordPress(以下wp)とWooCommerce(以下wc)でSquareを使ってオンラインショップを作るメモ。

下記日本語化の入力チェックについてのメモ。

WooCommerce Squareの日本語化

カード番号が未入力などの入力チェックのエラーメッセージは、javascriptで出力されている。

エラーメッセージをどのように出力しているのか表示の方から追ってみた。

対策を急ぐ方はこちら。

解析

まず、出力しているのは下記ソース。

/plugins/woocommerce-square/assets/js/frontend/wc-square.min.js

コンパイル前のソースは、

/plugins/woocommerce-square/assets/js/frontend/wc-square.coffee

530行目以降のrender_errors()にて、引数で渡されたエラーメッセージの配列を、liタグで繋いでulタグで囲って出力している。

# Public: Render any new errors and bring them into the viewport
#
# Returns nothing.
render_errors: (errors) ->

# hide and remove any previous errors
$( '.woocommerce-error, .woocommerce-message' ).remove()

# add errors
@form.prepend '<ul class="woocommerce-error"><li>' + errors.join( '</li><li>' ) + '</li></ul>'

# unblock UI
@form.removeClass( 'processing' ).unblock()
@form.find( '.input-text, select' ).blur()

# scroll to top
$( 'html, body' ).animate( { scrollTop: @form.offset().top - 100 }, 1000 )

このrender_errors()が呼ばれるのは493行目のhandle_errors()。

引数で渡されたエラーメッセージの配列を一つずつ、エラーの種類で判断して変数(messages)に入れ、render_errors()に渡している。

    # Handle error data.
    #   
    # @since 2.0.0
    # @param Object[]
    handle_errors: ( errors = null ) ->

      this.log 'Error getting payment data', 'error'

      # clear any previous nonces
      $( "input[name=wc-square-credit-card-payment-nonce]" ).val( '' )
      $( "input[name=wc-square-credit-card-buyer-verification-token]" ).val( '' )

      messages = []

      if errors

        console.error errors

        $( errors ).each ( index, error ) =>

          # only display the errors that can be helped by the customer
          if error.type in [ 'UNSUPPORTED_CARD_BRAND', 'VALIDATION_ERROR' ]

            messages.push( error.message )

          # otherwise, log more serious errors to the debug log 
          else
            this.log_data( errors, 'response' )

      # if no specific messages are set, display a general error
      if messages.length is 0
        messages.push( @general_error )

      this.render_errors( messages )

      this.unblock_ui()

handle_errors()が呼ばれているのは数箇所。

入力チェックで通るのは、400行目のhandle_verify_buyer_response()内。

引数で渡された内容がエラーだったらhandle_errors()を呼ぶ。

エラーが無ければ結果のトークンをセットしてsubmit()する。

    # Handles the response from a call to verifyBuyer()
    #   
    # @since 2.1.0
    #   
    # @param Object[] errors verification errors, if any 
    # @param Object verification_result the results of verification
    handle_verify_buyer_response: ( errors, verification_result ) =>

      if errors
        return this.handle_errors( errors )

      # no errors, but also no verification token
      if not verification_result or not verification_result.token

        message = 'Verification token is missing from the Square response'

        this.log message, 'error'
        this.log_data message, 'response'

        return this.handle_errors()

      this.log 'Verification result received'
      this.log verification_result

      $( "input[name=wc-#{@id_dasherized}-buyer-verification-token]" ).val( verification_result.token )

      @form.submit()

handle_verify_buyer_response()が呼ばれる2箇所のうち、入力チェックは318行目のvalidate_payment_data()内。

それっぽい関数名になったw

@payment_form.verifyBuyer()の引数でhandle_verify_buyer_response()が渡されている。

    # Used to request a card nonce and submit the form.
    #   
    # @since 2.0.0
    validate_payment_data: ->

      # bail when already processing
      return false if @form.is( '.processing' )

      # let through if nonce is already present - nonce is only present on non-tokenized payments
      if this.has_nonce()
        this.log 'Payment nonce present, placing order'
        return true

      tokenized_card_id = this.get_tokenized_payment_method_id()

      if tokenized_card_id

        # if 3DS is disabled and paying with a saved method, no further validation needed
        return true unless @is_3ds_enabled

        if this.has_verification_token()
          this.log 'Tokenized payment verification token present, placing order'
          return true

        this.log 'Requesting verification token for tokenized payment'
        this.block_ui()
        @payment_form.verifyBuyer tokenized_card_id, this.get_verification_details(), this.handle_verify_buyer_response
        return false

      this.log 'Requesting payment nonce'
      this.block_ui()
      @payment_form.requestCardNonce()
      return false

payment_formは、190行目で作成されているSqPaymentFormクラス。

    # Sets up the Square payment fields
    #   
    # @since 2.0.0
    set_payment_fields: =>

      if $( "#wc-#{@id_dasherized}-account-number-hosted" ).is( 'iframe' )

        this.log 'Re-adding payment form'

        for _, field of @form_fields
          $( field.attr( 'id' ) ).replaceWith( field )

        this.handle_form_loaded()

      else
        if @payment_form

          this.log 'Destroying payment form'

          @payment_form.destroy()

        this.log 'Building payment form'

        @payment_form = new SqPaymentForm( this.get_form_params() )

        @payment_form.build()

SqPaymentFormクラスは、下記外部サーバーのjavascriptファイルにて定義されている。

https://js.squareup.com/v2/paymentform/ver=...

ソースを確認するには、chromeであれば右クリックで”検証”、または右上のメニューから”その他のツール”→デベロッパーツールを開く。

Sources を選ぶ。

該当のファイルをクリックし、左下の {} を押す。

Ctrl (⌘)+ F で検索窓を開き”SqPaymentForm”と入力するとたくさん出てくるが、一番下で定義されている。

            }
        }
    }
      , Tt = Et;
    window.SqPaymentForm = Tt
}
]);

Tt は、その上の行で Et が代入されてるため実態はEt。

Etは7340行目から定義されている。

    function Et(t) {
        this.options = t;
        try {
            this._initialize()
        } catch (t) {
            throw this.eventstream && this.eventstream.track(B.a.GENERAL_EVENT, Pt(t)),
            this.errorLogger && this.errorLogger.capture(t),
            t
        }
    }

@payment_form.verifyBuyer()の実態は、7456行目にある。

引数で渡したhandle_verify_buyer_response()はnとなり、7473行目で実行される。

    Et.prototype.verifyBuyer = function(t, e, n) {
        var i = this;
        if (this._trackVerificationRequested(),
        !this.options.locationId && !this.options.accountId)
            throw this._trackVerificationError("No location id given"),
            new TypeError("`locationId` is required");
        if (!e.billingContact || "object" !== _t(e.billingContact))
            throw this._trackVerificationError("billingContact not given"),
            new TypeError("`verificationDetails.billingContact` is required and must be an object");
        var r = {
            applicationId: this.options.applicationId,
            locationId: this.options.locationId,
            accountId: this.options.accountId
        };
        d.verifyBuyer(r, t, e, function(t, e) {
            t && i._trackVerificationError(t.message),
            e ? i._trackVerificationSuccess() : i._trackVerificationError("No token generated"),
            n(t, e)
        })
    }

n(t, e)にメッセージが渡ってくるはず。

しかし、もうここまで来ると解析も面倒・・・。

諦めてメッセージから逆検索することにする。

その結果見つけたのは下記の中。

https://pci-connect.squareup.com/v2/iframe?type=main&app_id~

下の検索窓に Credit card number is not valid を入れると該当箇所がわかる。

2か所該当した。

Squareはこの辺りのスクリプトを経由してメッセージを出してるようだ。

対策

外部サーバーにあるのはどうしようもない。

仕方ない、プラグイン内のファイルを上書きするか・・・。

これを参考にする人は自己責任でお願いします。

といっても、直接上書きするのは危険すぎるので、テーマ内にjavascriptを複製し読み込み先を変えることにする。

複製するのは、メッセージを出力している下記ファイル。

/plugins/woocommerce-square/assets/js/frontend/wc-square.coffee

テーマ内に、custom-square.coffeeなどの名前にしておく。

coffeeスクリプトなので、gulp-coffeeでcustom-square.min.jsなどに変換する。

修正したのは512行目辺りのメッセージを代入しているところ。

        $( errors ).each ( index, error ) =>

          # only display the errors that can be helped by the customer
          if error.type in [ 'UNSUPPORTED_CARD_BRAND', 'VALIDATION_ERROR' ]

            messages.push( error.message )

          # otherwise, log more serious errors to the debug log

error.messageの内容で変換してから代入するように変える。

        $( errors ).each ( index, error ) =>

          # only display the errors that can be helped by the customer
          if error.type in [ 'UNSUPPORTED_CARD_BRAND', 'VALIDATION_ERROR' ]

            switch error.message
              when 'Credit card number is not valid'
                message_jp = 'クレジットカード番号が不正です' 
              when 'CVV is not valid'
                message_jp = 'セキュリティコードが不正です' 
              when 'Expiration date is not valid'
                message_jp = '有効期限が不正です' 
              when 'Postal code is not valid'
                message_jp = '郵便番号が不正です' 
              when 'The provided card was declined, please use an alternate card or other form of payment.'
                message_jp = 'カードは拒否されました。別のカードまたは他のお支払い方法をご利用ください' 
              when 'An error occurred, please try again or try an alternate form of payment.'
                message_jp = 'エラーが発生しました。もう一度試すか、別のお支払い方法をお試しください' 
              else
                message_jp = error.message

            messages.push( message_jp )

          # otherwise, log more serious errors to the debug log

そしてfuncstions.phpにて、wc-square.min.js を出力しないようにする。

function custom_print_scripts() {
  wp_dequeue_script('wc-square');
}
add_action('wp_print_scripts', 'custom_print_scripts', 100);

代わりに、custom-square.min.jsを読み込ませる。

/**
 * footer
 */
function custom_footer() {

  // 決済ページ
  if (get_the_ID() === 7) {
    wp_enqueue_script( 'square-script', get_stylesheet_directory_uri() . '/js/custom-square.min.js' );
  }
}
add_action( 'wp_footer', 'custom_footer');

これで下記のように日本語化される。

ただし、woocommerce-squareのバージョンが上がった場合は、変更箇所を確認し、必要に応じ再度同じ作業をする。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です