Google reCAPTCHA v3 をコピペで実装(Javascript+PHP)

サーバサイドで処理できず困っているフロントエンジニア向け。「送信元」と「送信先」の2箇所に埋め込む必要がある。

★のところに任意の内容を入れてね。役に立ったと思ったら以下をクリックして、(他のものでもいいから)なにか買うなりしてくれるととっても嬉しいな。

実装前の注意

アクセス数によっては(評価を作成するための呼び出しごと)に、Googleから月単位で料金が請求されるから注意して。
2023年6月20日時点:100 万件/1ヶ月 まで無料。

送信元(タイムアウトは無視する版)

以下の★好きなアクション名についてはGoogleのヘルプ見てね(アクションには、英数字、スラッシュ、アンダースコアのみを使用できます。ユーザー固有のアクションであってはなりません)。

送信元に関する公式ヘルプはこちら。

フォームが1個のとき

事前準備:送信内容を検証したいフォームにIDをつけてね。例)IDがhogeなら <form id=”hoge”>

やっていること:元となる外部jsを読み込んで、指定したフォームのID内で 、トークンの値を持つための input#recaptchaToken[name=recaptchaToken] を生成。あわせて、そのフォームが送信される時、function onSubmitを実行するようイベントを指定。

<script src="https://www.google.com/recaptcha/api.js?render=★サイトキー"></script>
<script>
        document.addEventListener('DOMContentLoaded', function() {
                const targetFormID = '★フォームID(#記号不要)';
                document.getElementById(targetFormID).innerHTML += '<input type="hidden" name="recaptchaToken" id="recaptchaToken" />';
                document.getElementById(targetFormID).addEventListener('submit', onSubmit);
        });
        function onSubmit(event) {
                event.preventDefault();
                grecaptcha.ready(function() {
                        grecaptcha.execute('★サイトキー', {action: '★好きなアクション名'}).then(function(token) {
                                var recaptchaToken = document.getElementById('recaptchaToken');
                                    recaptchaToken.value = token;
                                    event.target.submit();
                        });
                });
        }
</script>

フォームが2個以上のとき

事前準備:送信内容を検証したいフォームにIDをつけてね。例)IDがhogeなら <form id=”hoge”>

やっていること:前述の1個のときとほぼ同じ。targetFormIDsでフォームIDを指定し、ループでぐるぐる回して1個1個処理してるよ。
ほかの違いとしては、トークンの値を持つためのinputは、 input#recaptchaToken_1[name=recaptchaToken] input#recaptchaToken_2[name=recaptchaToken] のように、ID末尾が連番になる。(また、連動して親のフォームにもform[data-recaptchaToken=”recaptchaToken_1″] と対になる値が勝手に入るよ)
ただし、[name=recaptchaToken]はすべて共通なので、送信先は連番を気にしないで処理してOK。

<script src="https://www.google.com/recaptcha/api.js?render=★サイトキー"></script>
<script>
	document.addEventListener('DOMContentLoaded', function() {
		const targetFormIDs =  ['★フォームID(#記号不要)','★hoge','★hoge2'];

		targetFormIDs.forEach((parentId, index) => {
			const parentForm = document.getElementById(parentId);

			if (!parentForm) { return; }

			const datalabel = 'recaptchaToken_' + (index + 1);
			parentForm.innerHTML += '<input type="hidden" name="recaptchaToken" id="'+datalabel+'" />';
			parentForm.dataset['recaptchaToken'] = datalabel;
			parentForm.addEventListener('submit', onSubmit);
		});
	});
	function onSubmit(event) {
		event.preventDefault();
		grecaptcha.ready(function() {
			grecaptcha.execute('★サイトキー', {action: '★好きなアクション名'}).then(function(token) {
				const recaptchaToken = document.getElementById(event.target.dataset['recaptchaToken']);
				recaptchaToken.value = token;
				event.target.submit();
			});
		});
	}
</script>

送信先(PHP)

送信先に関する公式ヘルプはこちら。

<?php
$recaptchaResponse = $_POST['recaptchaToken'];
$secretKey 	= '★シークレットキー';
$verifyResult = file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret={$secretKey}&response={$recaptchaResponse}");
$verifyResult = json_decode($verifyResult);

if ($verifyResult->success == false){
	// 重複送信時で分岐する場合は、理由が"timeout-or-duplicate"かで判定
	$dispMes = "検証失敗 理由:{$verifyResult->{'error-codes'}[0]}";
}elseif($verifyResult->success == true){
	$dispMes =  "検証成功";
}
echo $dispMes;
?>

余談

ヘルプページ見て、よそのをぐぐってみて、どれが正解かわっかんね!ってなったので。data属性つけて云々するよりプログラマティックに呼び出す方が好きでした。(ブラウザ放置によるタイムアウト考慮できるし、formをsubmitする前にバリデーションチェック入れたりしたいじゃん)

役に立ったら以下のリンクポチってね。おすすめの練乳です。コーヒー牛乳に入れて飲むと糖分が脳にキまります。在宅勤務のお供に。

コメントを残す

メールアドレスが公開されることはありません。

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)