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

本記事は、Wordpressのプラグイン「MW WP Form」と「reCAPTCHA for MW WP Form」を使用し、「Invalid reCAPTCHA Secret key」にハマってしまった人向けの記事です。
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分問題の解決方法
フォームの入力画面を表示した際にトークンを発行するのではなく、送信ボタンを押すタイミングでトークンを発行する方法がよく使われます。
入力画面に以下のscriptタグを追加します。
<script>
jQuery(function($) {
$('#mw_wp_form_mw-wp-form-数字 form').on('submit', function(e) {
e.preventDefault();
var $form = $(this);
grecaptcha.ready(function() {
grecaptcha.execute('ここにサイトキーを入力', {action: 'submit'}).then(function(token) {
$('#recaptchaResponse').val(token);
$form.off('submit').submit();
});
});
});
});
</script>
確認画面がないフォームだと実装に特に問題はありません。
しかし、確認画面が必要な場合、ハマるポイントがあります。
上記はバリデーションは通りますが、確認画面に遷移せずに送信画面に遷移されてします。
また、バリデーションでエラーになった場合、MW WP FORM用のカスタムバリデーションのチェックが2回走るので、重複エラー(timeout-or-duplicate)になります。
これもハマりポイントです。
timeout-or-duplicateエラーの回避
そこで、入力画面ではなく、確認画面にさきほどのinputタグを追加します。
入力画面から確認画面への遷移で、reCAPTCHAが走らないので、ここは改善の余地あります。
name=”recaptcha_error” にダミーのvalueを最初から入力しておいて、トークンに書き換えないとバリデーションエラーになるようにしておく?
あとはMW WP FORM用のカスタムバリデーションを作ります。
functions.phpに記載してもいいですが、別ファイルにして読み込みでも動作します。
add_filter( 'mwform_validation_mw-wp-form-数字', 'form_validation_rule', 10, 3 );
function form_validation_rule( $Validation, $data, $Data ) {
if($data){
//ここに他のバリデーション
if($data['recaptcha_response']){
$recaptcha_response = $data['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_threshold = 0.5;
if ($recaptcha_score_value < $recaptcha_threshold) {
$Validation->set_rule( 'recaptcha_error', 'noEmpty', array( 'message' => '不正なエラーです。' ) );
}
}
return $Validation;
}
}
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」エラーを解消できます。