広告

Google reCAPTCHA v3 2分以上でも使えるようにする

JavaScript
この記事は約15分で読めます。

またまた、ハマってしまったGoogle reCAPTCHAということで、書き直しました。

なお、この記事は2025年4月現在の方法です。

Google reCAPTCHA の種類

有名なのは、Google reCAPTCHA v2 とGoogle reCAPTCHA v3 ですが、reCAPTCHA Enterprise というものもあります。

2025年にハマってしまったのは、Google reCAPTCHA と reCAPTCHA Enterprise の違いを知らず、2つのドキュメントを見てしまったためです。

特徴reCAPTCHA v3reCAPTCHA Enterprise
ユーザーインタラクションバックグラウンドで評価バックグラウンドで評価、リスクに応じて追加措置
スコアリング0.0 – 1.0 のリスクスコアより詳細なリスクスコア、リスク理由コード
アクション対応対応
モバイルアプリ保護ウェブサイトのみウェブサイト、Android、iOS アプリケーション
パスワード漏洩検出ユーザーのパスワードが過去に漏洩していないかをチェック可能
多要素認証SMS やメールによる多要素認証をトリガー可能
モデル調整グローバルモデルグローバルモデル + サイト固有の調整
メトリクスとレポート基本的なダッシュボードリアルタイムの詳細なダッシュボードとレポート
WAF 連携対応
SLAエンタープライズレベルの SLA
テクニカルサポートコミュニティサポート有償テクニカルサポート
料金基本無料
一定のAPI呼び出し回数制限あり(例:1秒あたり1,000回、月あたり100万回)。超える場合は reCAPTCHA Enterprise 利用推奨
無料枠(月あたり10,000評価まで)がありますが、超える場合は従量課金制
主な用途一般的なスパム対策、ボット軽減大規模サイト、高セキュリティが求められる用途

こうやって比較すると、お問い合わせフォームであれば、Google reCAPTCHA v3 で大丈夫そうですね。

簡単に分けるとすると、コードを作る場所が違う

そもそも、Google reCAPTCHA v2 とGoogle reCAPTCHA v3 、reCAPTCHA Enterprise はサイトキーなどを作る場所が違います。

違うといっても、どちらもGoogle Cloud Platformを使うので、注意が必要です。
→ここでハマった…

Google reCAPTCHA v2 とGoogle reCAPTCHA v3を作る場所

https://www.google.com/recaptcha/admin/create?hl=ja

Google reCAPTCHA

ここで作成するわけですが、Google Cloud Platform は、サイトに応じたプロジェクトとするといいでしょう。

また、同じドメインでまとめておくといいと思います。

違うドメインを同じプロジェクトにすると、ハマりそうですね。

reCAPTCHA Enterprise は、Google Cloud Platform (GCP) で作成と管理

念のため、書いておくとreCAPTCHA Enterprise を作成するときは、以下の流れになります。

  1. Google Cloud Platform コントロールから
  2. 必要に応じてプロジェクトを作成
  3. reCAPTCHA Enterprise API を有効化
  4. reCAPTCHA Enterprise のカギを作成

reCAPTCHA Enterprise と reCAPTCHA V3 では、フロントで使用するJavaScriptのコードもバックでAPI通信したときの戻り値も違うので、ご注意ください。

Google reCAPTCHA v3 2分以上経過しても使えるようにするコード

htmlでGoogle reCAPTCHA v3は2分以上経過してから送信できるようにするには、JavaScriptで送信ボタンをアレンジする必要があります。

フロント部分

<form id="contactform" method="post" action="">

<input ~~~~~~~>など フォームの内容

<!-- JavaScriptでidを使って指定しているのでお忘れなく -->

<input type="hidden" name="recaptchaResponse" id="recaptchaResponse">
<input type="hidden" name="submitConfirm" value="confirm">
<button id="btn_confirm" type="button" class="contact__btn">確認画面へ</button>

<button type="button" onclick="location.href='<?php echo esc_url( PAGE_URL ); ?> '">リセット</button>

</form>

こんな感じのフォームにして、

Javascriptは、こんな感じ。

<? Site_Key ?>の部分はGoogle reCAPTCHA v3を設定したときに出てくるサイトキーです。

<script src="https://www.google.com/recaptcha/api.js?render=<? Site_Key ?>"></script>
<script>
window.onload = function() {
// 送信ボタン指定
const btnConfirm = document.getElementById('btn_confirm');
// console.log(btnConfirm);

// btnConfirmをクリックしたら.
btnConfirm.addEventListener( 'click', function(e) {
e.preventDefault(); // 必要なら、デフォルトの動作(送信)を停止
btnConfirm.style.display ="none"; // 必要なら、ボタンを非表示にする

grecaptcha.ready(function () {
grecaptcha.execute('<? Site_Key ?>', {action: 'submit'}).then(function(token) {
// recaotchaトークン挿入場所指定.
const recaptchaResponse = document.getElementById('recaptchaResponse');
// トークン挿入.
recaptchaResponse.value = token;
// id="contactform"のフォームを送信
document.getElementById('contactform').submit();
return false;
});
});
});
}
</script>

はい。これで行くと思います。

バック部分 php

サニタイズ処理や、ノンスチェックは入っていないのでご注意ください。

// サニタイズ処理やエラー処理をする
// $_POST をサニタイズ処理などをして、$cleanに入れています。

if ( empty( $clean['recaptchaResponse'] ) ) {
  die( '不正アクセスの疑いにより、処理できません。' );
}
// echo '$clean[recaptchaResponse] あるよ。';

// ユーザーのIPアドレス(推奨)
$remote_ip = wp_unslash( $_SERVER['REMOTE_ADDR'] ) ?? '';

// Postリクエスト パラメーター
$post_data = array(
  'secret'   => $reCAPTCHA_Secret_Key, // Secret Keyをここに入れます。
  'response' => $clean['recaptchaResponse'],
  'remoteip' => $remote_ip,
);

try {
  // curlの初期化、オプション設定、実行など

  $ch = curl_init( 'https://www.google.com/recaptcha/api/siteverify' );
  if ( false === $ch ) {
    throw new Exception( 'cURLの初期化に失敗しました。' );
  }

  curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
  curl_setopt( $ch, CURLOPT_POST, true );
  curl_setopt( $ch, CURLOPT_POSTFIELDS, http_build_query( $post_data ) );

  $response = curl_exec( $ch );

  if ( false === $response ) {
    $curl_error = curl_error( $ch );
    curl_close( $ch );
    throw new Exception( 'cURLエラー: ' . $curl_error );
  }

  $http_code = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
  if ( $http_code < 200 || $http_code >= 300 ) {
    throw new Exception( 'HTTPエラー: ' . $http_code . ' - レスポンス: ' . $response );
  }

  // 成功時の処理
  curl_close( $ch );

  echo 'HTTP POSTリクエストを送信しました。';
  echo 'レスポンス:';
  echo $response;

  $response_array = json_decode( $response, true );
  if ( null === $response_array && json_last_error() !== JSON_ERROR_NONE ) {
    echo 'JSONレスポンスのデコードに失敗しました: ' . json_last_error_msg();
  } else {

    // $opt_val_google_reCAPTCHA_score は許容するスコア
    $opt_val_google_reCAPTCHA_score = 0.5;

       
    // レスポンスの処理
    if ( $response_array['success'] && $response_array['score'] >= $opt_val_google_reCAPTCHA_score ) {
      echo 'reCAPTCHAスコア: ' . $responseArray['score'];
      // スコアに基づいた処理
      // 確認画面を表示させる関数など

    }
    // その他のレスポンス処理
  }
} catch ( Exception $e ) {
  echo 'エラーが発生しました: ' . $e->getMessage();
  // 必要に応じてログ出力やエラー通知などの処理を行う
}

curlを使って、API通信をしています。

curlが無効になっているサーバーでは使えません。

応用編・・・以前のままなのでご参考程度で・・・

処理の時間がかかるな・・・ってときは

<form id="yorozuya_form" name="yorozuya_form" method="post" action="">
  フォームの内容
<div id="yorozuya_form-submit">
  <button name="btn_submit" value="送信" id="subbtn" type="button" data-type="submit">申し込む</button>
</div>
</form>
<script>
// 送信ボタン指定.
var subbtn = document.getElementById('subbtn');
subbtn.addEventListener( 'click', function(e) {
  // デフォルトの動作(送信)を停止.
  e.preventDefault();
  // ボタンを非表示.
  subbtn.style.display ="none";
  // ボタンの上のDIVを指定.
  var formSubmit = document.getElementById( 'yorozuya_form-submit' );
  // 処理中の表示を作る.
  var addDiv = document.createElement( 'div' );
  addDiv.textContent = '処理中です。しばらくお待ちください。';
  formSubmit.appendChild(addDiv);
  // google reCAPTCHA v3のトークン挿入と送信処理.
  grecaptcha.ready(function() {
    grecaptcha.execute('~~~~', {action: 'submit'}).then(function(token) {
      // recaotchaトークン挿入場所指定.
      var recaptchaResponse = document.getElementById('recaptchaResponse');
      // トークン挿入.
      recaptchaResponse.value = token;
      // フォーム送信.
      document.yorozuya_form.submit();
      return false;
    });
  });
});
</script>

JavaScriptでボタンを非表示、表示を切り替える方法も

<form id="yorozuya_form" name="yorozuya_form" method="post" action="">
  フォームの内容
  <button name="btn_submit" value="送信" id="subbtn" type="button" data-type="submit">申し込む</button>
<div id="yorozuya_form-submit" style="display: none;">処理中です。しばらくお待ちください。</div>
</form>
<script>
// 送信ボタン指定.
var subbtn = document.getElementById('subbtn');
var yorozuyaFormSubmit = document.getElementById('yorozuya_form-submit');
subbtn.addEventListener( 'click', function(e) {
  // デフォルトの動作(送信)を停止.
  e.preventDefault();
  // ボタンを非表示.
  subbtn.style.display ="none";
  // 処理中の表示をONに.
  yorozuyaFormSubmit.style.display ="block";
  // google reCAPTCHA v3のトークン挿入と送信処理.
  grecaptcha.ready(function() {
    grecaptcha.execute('~~~~', {action: 'submit'}).then(function(token) {
      // recaotchaトークン挿入場所指定.
      var recaptchaResponse = document.getElementById('recaptchaResponse');
      // トークン挿入.
      recaptchaResponse.value = token;
      // フォーム送信.
      document.yorozuya_form.submit();
      return false;
    });
  });
});
</script>

こんな感じもありです。

すべて実装しているので、問題があったらお知らせいただけると嬉しいです。