Как добавить несколько невидимых recaptcha на одной странице?
Я добавил два невидимых элемента recaptcha, но когда я увидел код в элементе inspect, на моей странице была добавлена только одна невидимая recaptcha. Мой код:
<div id="captcha1" class="g-recaptcha"
data-sitekey="your_site_key"
data-callback="onSubmit"
data-size="invisible"></div>
<div id="captcha2" class="g-recaptcha"
data-sitekey="your_site_key"
data-callback="onSubmit"
></div>
Получить ссылку от Программно вызвать recaptcha
Можете ли вы помочь мне, что я делаю не так?
7 ответов
Ниже приведено более надежное решение ответов Петра и Алессандро при вложении элементов.
<script>
$(".g-recaptcha").each(function() {
var object = $(this);
grecaptcha.render(object.attr("id"), {
"sitekey" : "6LdwRC0UAAAAAK0hjA8O4y1tViGPk9ypXEH_LU22",
"callback" : function(token) {
object.parents('form').find(".g-recaptcha-response").val(token);
object.parents('form').submit();
}
});
});
</script>
<form>
<input type="text" name="example"/>
<button id="captcha1" class="g-recaptcha">submit form 1</button>
</form>
<form>
<input type="text" name="example"/>
<button id="captcha2" class="g-recaptcha">submit form 2</button>
</form>
<script src='https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit' async defer></script>
Была такая же проблема. После некоторого недоумения я заставил это работать.
Воспользовался предложенной Алессандро идеей и сделал так, чтобы форма автоматически отправлялась в случае успеха.
<script type="text/javascript">
var onloadCallback = function() {
$(".g-recaptcha").each(function() {
var el = $(this);
grecaptcha.render($(el).attr("id"), {
"sitekey" : SITE_KEY,
"callback" : function(token) {
$(el).parent().find(".g-recaptcha-response").val(token);
$(el).parent().submit();
}
});
});
};
</script>
<script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit" async defer></script>
Вы должны сделать явный рендер на каждой кнопке отправки
<form>
<button id="captcha1" class="g-recaptcha invisible-recaptcha">submit form 1</button>
</form>
<form>
<button id="captcha2" class="g-recaptcha invisible-recaptcha">submit form 2</button>
</form>
<script>
function verifyCaptcha(token){
console.log('success!');
};
var onloadCallback = function() {
$( ".invisible-recaptcha" ).each(function() {
grecaptcha.render($( this ).attr('id'), {
'sitekey' : $key,
'callback' : verifyCaptcha
});
});
};
</script>
<script src='https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit' async defer></script>
Несколько невидимых reCaptcha V2 на одной странице динамически
Код Github: https://github.com/prathameshsawant7/multiple-invisible-recaptcha
Шаг 1>
Добавить ниже 2 Js библиотеки на странице
<!-- reCaptcha Library -->
<script type="text/javascript" src="https://www.google.com/recaptcha/api.js?render=explicit"></script>
<!-- Customized Init for invisible reCaptcha -->
<script src="js/init_recaptcha.js" async defer></script>
Шаг 2>
Добавьте ниже div в соответствующих формах.
<div id="recaptcha-form-1" style="display:none;"></div> <!--for Form 1-->
<div id="recaptcha-form-2" style="display:none;"></div> <!--for Form 2-->
<div id="recaptcha-form-3" style="display:none;"></div> <!--for Form 3-->
Шаг 3>
Создать init_recaptcha.js
- Шаг 1 - Инициализируйте ключ сайта ReCaptcha и виджет, например: widget_1 для формы 1
- Шаг 2 - В функцию init добавьте код для создания формы отправки обратного вызова.
Шаг 3 - Вызовите функцию renderInvisibleReCaptcha, передав идентификатор reCaptcha и ответ createCallbackFn.
"use strict"; var PS = PS || {}; var widget_1;var widget_2;var widget_3; var recaptcha_site_key = 'RECAPTCHA_SITE_KEY'; if( typeof PS.RECAPTCHA === 'undefined' ) { (function (a, $) { var retryTime = 300; var x = { init: function(){ if(typeof grecaptcha != 'undefined'){ //For Form 1 Initialization if($('#form1 #recaptcha-form-1').length > 0){ var callbackFn = { action : function(){ saveData('1'); //Here Callback Function } } /*--- 'recaptcha-form-1' - reCaptcha div ID | 'form1' - Form ID ---*/ widget_1 = x.renderInvisibleReCaptcha('recaptcha-form-1',x.createCallbackFn(widget_1,'form1',callbackFn)); } //For Form 2 Initialization if($('#form2 #recaptcha-form-2').length > 0){ var callbackFn = { action : function(){ saveData('2'); //Here Callback Function } } /*--- 'recaptcha-form-2' - reCaptcha div ID | 'form2' - Form ID ---*/ widget_2 = x.renderInvisibleReCaptcha('recaptcha-form-2',x.createCallbackFn(widget_2,'form2',callbackFn)); } //For Form 3 Initialization if($('#form3 #recaptcha-form-3').length > 0){ var callbackFn = { action : function(){ saveData('3'); //Here Callback Function } } /*--- 'recaptcha-form-3' - reCaptcha div ID | 'form3' - Form ID ---*/ widget_3 = x.renderInvisibleReCaptcha('recaptcha-form-3',x.createCallbackFn(widget_3,'form3',callbackFn)); } }else{ setTimeout(function(){ x.init();} , retryTime); } }, renderInvisibleReCaptcha: function(recaptchaID,callbackFunction){ return grecaptcha.render(recaptchaID, { 'sitekey' : recaptcha_site_key, "theme" : "light", 'size' : 'invisible', 'badge' : 'inline', 'callback' : callbackFunction }); }, createCallbackFn: function (widget,formID,callbackFn) { return function(token) { $('#'+formID+' .g-recaptcha-response').val(token); if($.trim(token) == ''){ grecaptcha.reset(widget); }else{ callbackFn.action(); } } } } a.RECAPTCHA = x; })( PS, $ ); } $(window).load(function(){ PS.RECAPTCHA.init(); });
Шаг 4> Изменения в проверке формы JS -
/* Execute respective Widget on form submit after form Validations */
function formSubmit(form){
var text = $.trim($('#text'+form).val());
if(text != ''){
switch(form){
case '1' : grecaptcha.execute(widget_1); break;
case '2' : grecaptcha.execute(widget_2); break;
case '3' : grecaptcha.execute(widget_3); break;
}
}
}
Шаг 5> Проверить reCaptcha со стороны сервера -
<?php
define('RECAPTCHA_SECRET_KEY','KEY');
/**
* @Desc: To Validate invisible recaptcha from server-side
* @Param: g-recaptcha-response value
* @Return: True/False
**/
if(!function_exists('check_recaptcha')){
function check_recaptcha($recaptcha_response){
$test = array ('secret' => RECAPTCHA_SECRET_KEY,'remoteip' => $_SERVER["REMOTE_ADDR"],'response' => $recaptcha_response);
foreach ($test as $key => $value) {
$req .= $key . '=' . urlencode(stripslashes($value)) . '&';
}
$req=substr($req, 0, strlen($req)-1);
$path = 'https://www.google.com/recaptcha/api/siteverify?';
$response = file_get_contents($path . $req);
$responseData = json_decode($response);
if($responseData->success){
return true;
}else{
return false;
}
}
}
// Validate reCaptcha
if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == "POST" && !empty($_POST)) {
$checkCapcha = false;
$recaptcha = $_POST['g-recaptcha-response'];
$checkCapcha = check_recaptcha($recaptcha);
if($checkCapcha){
echo $_POST['textmsg']; exit;
/** Perform Actions Here (Add,Update,Delete etc)
**/
}
else{
echo “reCaptcha Error”;
}
}
echo "failed";exit;
?>
Шаг 6> Сброс виджета после вызова сервера -
// saveData will be automatically get called on grecaptacha.execute
function saveData(form){
$.ajax( {
type: 'POST',
url: $("#form"+form).attr( 'action' ),
data: $("#form"+form).serialize(),
success: function( response ) {
switch(form){
case '1' : grecaptcha.reset(widget_1); break;
case '2' : grecaptcha.reset(widget_2); break;
case '3' : grecaptcha.reset(widget_3); break;
}
}
} );
}
Вы можете использовать невидимую recaptcha. На вашей кнопке используйте тег типа " formname='rcaptchaformname' ", чтобы указать, какая форма должна быть отправлена, и скрыть ввод формы отправки.
Это позволяет вам сохранить проверку формы html5 без изменений, один повтор, но несколько кнопок интерфейсов. Просто запишите входное значение "captcha" для ключа токена, сгенерированного recaptcha.
<script src="https://www.google.com/recaptcha/api.js" async defer ></script>
<div class="g-recaptcha" data-sitekey="yours" data-callback="onSubmit" data-size="invisible"></div>
<script>
$('button').on('click', function () { formname = '#'+$(this).attr('formname');
if ( $(formname)[0].checkValidity() == true) { grecaptcha.execute(); }
else { $(formname).find('input[type="submit"]').click() }
});
var onSubmit = function(token) {
$(formname).append("<input type='hidden' name='captcha' value='"+token+"' />");
$(formname).find('input[type="submit"]').click()
};
</script>
Решение @Prathamesh Sawant завершено, но если вам не нужно, чтобы оно было динамичным, вы можете упростить процесс:
1. Загрузите библиотеку рекапчи.
<script src='https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit' async defer></script>
2. Добавьте свой заполнитель в HTML-код каждой формы.
<form ...>
...
<div class="g-recaptcha"></div>
...
</form>
3. В вашем JS напишите обратный вызов, который вы вызвали, как параметр при загрузке скрипта reCaptcha:
window.onloadCallback = function() {
$('.g-recaptcha').each(function(i, v) {
const $placeholder = $(this)
// Define a widget id that will be used by every grecaptcha method
// to keep track of which form is being used
$placeholder.data('widget-id', i)
grecaptcha.render( this, {
callback: function( token ) {
return new Promise(function(resolve, reject) {
if( grecaptcha === undefined ) {
console.log( 'reCaptcha not defined' )
reject()
}
var response = grecaptcha.getResponse( $placeholder.data('widget-id') )
if( !response ) {
console.log( 'Could not get reCaptcha response' )
reject()
}
const $form = $placeholder.closest('form')
$form.find('.g-recaptcha-response').val( token )
$form
// Add a class that will be used to bypass the prevented submit event
.addClass('recap-done')
// submit by clicking the submit button of your form
.find('[type="submit"]').trigger('click')
resolve()
grecaptcha.reset( $placeholder.data('widget-id') )
})
},
sitekey: RECAPTCHA_KEY,
size: 'invisible', // This makes the real reCaptcha V2 Invisible
})
})
}
Примечание. Я использую обещание, чтобы предотвратить проблему с нулевым обещанием, описанную здесь .
4. Добавьте обработчик событий отправки для всех форм.
$('form').on('submit', function(e) {
const $form = $(this)
// 2nd pass (when the submit is triggered within the callback)
// This bypasses the event to be prevented a new time -> form is really submitted
if( $form.hasClass('recap-done') ) {
return
}
// 1st pass: prevents the form to be submitted and do the reCaptcha process
const $placeholder = $form.find('.g-recaptcha')
if( $placeholder.length > 0 ) {
e.preventDefault()
grecaptcha.execute( $placeholder.data('widget-id') )
}
})
5. Наслаждайтесь
Для Google Recaptcha V3 несколько Recpatchas на странице:
HTML:
<script src="https://www.google.com/recaptcha/api.js?render=explicit&onload=grecaptcha_onload"></script>
<script>
function grecaptcha_onload() {
$('.g-recaptcha-response').each(function( k, v ) {
var submit = $(v).closest("form").find('[type="submit"]');
grecaptcha.render( submit[0], {
'sitekey' : SITE_KEY,
'callback' : function( token ) {
$(v).closest("form").find('.g-recaptcha-response').val( token );
$(v).closest("form").submit();
},
'size' : 'invisible',
});
});
}
</script>
<form>
<input type="hidden" value="" name="g-recaptcha-response" class="g-recaptcha-response" />
<button type="submit">Submit</button>
</form>
<form>
<input type="hidden" value="" name="g-recaptcha-response" class="g-recaptcha-response" />
<button type="submit">Submit</button>
</form>
PHP:
function validate()
{
if( $_SERVER['REQUEST_METHOD'] == 'POST' ) {
// Build POST request:
$recaptcha_url = 'https://www.google.com/recaptcha/api/siteverify';
$recaptcha_response = $_POST[ 'g-recaptcha-response' ];
$recaptcha = file_get_contents( $recaptcha_url . '?secret=' . self::SECRET_KEY . '&response=' . $recaptcha_response );
$recaptcha = json_decode( $recaptcha );
if( $recaptcha->success == true ){
// Take action based on the score returned:
if( $recaptcha->score >= 0.1 ) {
return true;
} else {
$this->errors[] = 'Something went wrong with sumbitting the form.<br />Please try again!';
foreach( (array) $recaptcha as $key => $value ) {
$this->errors[] = 'Key: ' . $key . ' Value: ' . $value;
}
return false;
}
} else { // there is an error /
switch ( $recaptcha->{'error-codes'}[0] ) {
case 'missing-input-secret':
$this->errors[] = 'The secret parameter is missing';
break;
case 'invalid-input-secret':
$this->errors[] = 'The secret parameter is invalid or malformed';
break;
case 'missing-input-response':
$this->errors[] = 'The response parameter is missing';
break;
case 'invalid-input-response':
$this->errors[] = 'The response parameter is invalid or malformed';
break;
case 'bad-request':
$this->errors[] = 'The request is invalid or malformed';
break;
case 'timeout-or-duplicate':
$this->errors[] = 'The response is no longer valid: either is too old or has been used previously';
break;
default:
break;
}
return false;
}
}
}