MW WP Formで、テーマファイルに直接ショートコードを記述している場合の「Invalid reCAPTCHA Secret key」エラーと「timeout-or-duplicate」エラーの解消方法(25.08.27 更新)

2025.05.26

2025年8月27日
reCAPTCHAの処理をバリデーションからメール送信タイミングに変更しました。

本記事は、Wordpressのプラグイン「MW WP Form」と「reCAPTCHA for MW WP Form」を使用し、「Invalid reCAPTCHA Secret key」と「timeout-or-duplicate」にハマってしまった人向けの記事です。

reCAPTCHAのサイトキーやシークレットキーは取得済みとして、取得方法は省ます。

「MW WP Form」自体は、開発が終了してしまい脆弱性対応のみとなってしまいました。
しかし、既存サイトで使用していたり、作業コストの点から採用せざるおえない状況はあったりします。


「Invalid reCAPTCHA Secret key」のエラー

お問い合わせフォームからの迷惑メールBOT対策で、後からreCAPTCHA v3を入れるケースもあります。
簡単に導入するのであれば、「reCAPTCHA for MW WP Form」で解決できますが、ハマってしまうのが「Invalid reCAPTCHA Secret key」のエラーです。

「Invalid reCAPTCHA Secret key」のエラーが出てしまうことをネットで調べるとPHPファイルに直接ショートコードを書いているのが原因なので、「the_content()」に置き換えましょうという情報が出てきます。

PHPファイルに直接ショートコードを書いている場合、直前に何かしらの処理をしていたり、カスタムブロックの中で使っているなど、「the_content()」に置き換えることができないケースだと思います。


reCAPTCHA v3のバリデーションを自作する

解決方法はいくつかありますが、reCAPTCHA v3を通常の方法で導入し、バリデーションを自作する方法です。
バリデーション以外にメール送信のタイミングで処理するなどもあります。

通常の方法で導入する場合、以下のscriptタグとinputタグを追加する必要があります。

head内に記載します。
※必要なページ(フォームがあるページなど)だけに仕込むようにしましょう。

<script src="https://www.google.com/recaptcha/api.js?render=ここにサイトキーを入力"></script>

次にフォーム内にinputタグを追加します。

<input type="hidden" name="recaptcha_response" id="recaptchaResponse">

しかし、ここでハマります。
MW WP FORMでは、inputタグを入力しても出力されません。ショートコードに置き換える必要があります。
ショートコードで[mwform_hidden name=”” value=””]が用意されていますが、こちらはidを付けることができません。
reCaptchaのapi.jsは、idのrecaptchaResponseを参照するので、ここで詰まります。

そこで、独自ショーコードを作成して、inputタグを追加します。


独自ショートコードの追加

独自ショートコードは、functions.phpに記載します。

function shortcode_output_recaptcha($atts) {
  $output = '<input type="hidden" name="recaptcha_response" id="recaptchaResponse">';
  return $output;
}
add_shortcode('recaptcha_tag', 'shortcode_output_recaptcha');

MW WP Formのフォーム画面に作成したショートコード とエラーを表示するための [mwform_error keys=”recaptcha_error”]を追加します。

さらにここでハマるポイントがあります。
reCAPTCHAは、トークンを発行してから2分以内に処理をしないとタイムアウトのエラー(timeout-or-duplicate)になります。
フォームの入力項目が少なければ問題ないですが、そこそこ多いと2分経過してしまします。


reCAPTCHAの2分問題の解決方法

フォームの入力画面を表示した際にトークンを発行するのではなく、「submit」のタイミングでトークンを発行します。

MW WP FORMを使っている場合、確認画面を挟みたいからという理由が多いと思います。

入力画面の「入力内容を確認するボタン」にトークンの発行処理を追加すると確認画面を挟まずに完了画面に遷移してしまいます。
それを防ぐために、入力内容の確認画面「送信するボタン」のあるページに以下のscriptタグを追加します。

<script>
jQuery(function($) {
  $('form').on('submit', function(e) {
    var submitter = e.originalEvent.submitter;
    if (submitter && $(submitter).val() === 'send') {
      e.preventDefault();
      var $form = $(this);
      grecaptcha.ready(function() {
        grecaptcha.execute('ここにサイトキーを入力', {action: 'submit'}).then(function(token) {
          $('#recaptchaResponse').val(token);
          $form.off('submit').submit();
        });
      });
    }
  });
});
</script>

timeout-or-duplicateエラーの回避

timeout-or-duplicateエラーになるのは、バリデーション処理でエラーになった場合、バリデーションの処理が2回動いてしまうのが原因です。
タイミングとしては、確認画面に遷移する際に1回、入力画面を再度表示する際に1回、の合計2回動作していまし、timeout-or-duplicateエラーになっているようです。

以前はfunctions.php(もしくは別ファイル)にMW WP FORM用のカスタムバリデーションを作成し、そこで、reCAPTCHAの処理をしていましたが、どうもうまく動作してないようなので、メールを送信する直前のタイミングで設定するようにしました。

function my_mwform_before_send_admin_mail( $Mail_admin,  $Data ) {

  if($Data->get('recaptcha_response')){
    $recaptcha_response = $Data->get('recaptcha_response');

    $recaptcha_secret = 'ここにシークレットキーを入力';
    $recaptcha_url = 'https://www.google.com/recaptcha/api/siteverify';

    $request_body = [
      'secret'   => $recaptcha_secret,
      'response' => $recaptcha_response,
      'remoteip' => $_SERVER['REMOTE_ADDR']
    ];

    $api_response = wp_remote_post(
      $recaptcha_url,
      [
          'method'  => 'POST',
          'timeout' => 10,
          'blocking' => true,
          'headers' => [
              'Content-Type' => 'application/x-www-form-urlencoded',
          ],
          'body'    => http_build_query($request_body),
      ]
    );

    $recaptcha = json_decode( wp_remote_retrieve_body($api_response));

    $recaptcha_score_value = $recaptcha->score;
    $recaptcha_threshold = 0.5;

    if ($recaptcha_score_value < $recaptcha_threshold) {
      // botなどは入力画面などにリダイレクト
      wp_safe_redirect( get_bloginfo('url').'ページののURL' );
      exit;
    }

  }

  return $Data;
  
}
add_action('mwform_before_send_admin_mail_mw-wp-form-数字', 'my_mwform_before_send_admin_mail', 10, 2 );

reCAPTCHAスコアがクリアできていれば、処理を継続して送信。
クリアできれなければ、特定のページにリダイレクトされ、exitで送信処理が止まるようにしています。
exitがないと、メールが送信されてしまします。

file_gets_contents()関数は、reCAPTCHAの事例でよく目にしますが、reCAPTCHAのAPIはPOSTメソッドを必要とします。そのため、cURL関数を利用するのが適しています。
WordPressの場合、wp_remote_post()関数でPOSTリクエストを送信しできます。APIから返ってきた情報は、wp_remote_retrieve_body() 関数を使って取得できます。

0.5の数字は、reCAPTCHAスコアを判定する数値です。
Googleのデベロッパーサイトによると 0.5から始めて、管理コンソールを見ながら、1.0に少しずつ近づけていき、適切な値を探るのがいいようです。
スコア判定が設定した数値を満たしていない場合は、エラーを出力します。

これでMW WP Formでテーマファイルに直接ショートコードを記述している場合の「Invalid reCAPTCHA Secret key」エラーを解消できます。