Как мне показать несколько рекапч на одной странице?


102

У меня 2 формы на одной странице. В одной из форм постоянно отображается рекапча. Другой должен отображать recaptcha только после определенного события, такого как максимальное количество попыток входа в систему. Так что бывают случаи, когда мне нужно, чтобы на одной странице отображалось 2 рекапчи. Это возможно? Я знаю, что мог бы, вероятно, использовать один для обоих, но, учитывая мой макет, я бы предпочел иметь 2. Спасибо.

Обновление: ну, я думаю, это может быть невозможно. Может ли кто-нибудь порекомендовать другую библиотеку захвата для использования вместе с reCaptcha? Я действительно хочу, чтобы на одной странице было 2 капчи.

Обновление 2. Что, если поместить каждую форму в iframe? Было бы это приемлемым решением?


Не могли бы вы просто показать одно и то же дважды?
Тайлер Картер,

1
Я пробовал это ... когда я пытаюсь продублировать код капчи, он просто отображает
капчу,

Любой, кто сталкивается с этим для нового API рекапчи, это возможно с помощью явной загрузки, описанной с примерами в документации на developers.google.com/recaptcha/docs/display#recaptcha_methods
El Yobo

3
Использование iframe должно быть возможным, но это плохой способ решения проблемы по сравнению с использованием JavaScript, как в Hüseyin Yağlıответе . Большинство браузеров должны поддерживать JavaScript, и reCAPTCHA по умолчанию в любом случае использует JavaScript. Однако я не знаю, что нужно сделать для решения проблемы без поддержки JavaScript.
Эдвард

Ответы:


14

Аналогичный вопрос был задан об этом на странице ASP ( ссылка ), и все согласились, что это невозможно сделать с recaptcha. Кажется, что несколько форм на одной странице должны использовать кодировку, если вы не хотите использовать другую капчу. Если вы не привязаны к recaptcha, хорошей библиотекой для изучения является компонент Zend Frameworks Zend_Captcha ( ссылка ). Он содержит несколько


9
На самом деле это возможно с reCAPTCHA , но без JavaScript невозможно . Большинство браузеров должны поддерживать JavaScript, а ReCaptcha по умолчанию в любом случае использует JavaScript, так что это решение хорошее. Hüseyin YağlıОтвет объясняет решение. Документация по reCAPTCHA для этого решения находится на сайте developers.google.com/recaptcha/docs/display#explicit_render . Однако я не знаю, что нужно сделать для решения проблемы без поддержки JavaScript.
Эдвард

На самом деле это абсолютно возможно с reCAPTCHA
Карлос Эспиноза

210

С текущей версией Recaptcha ( reCAPTCHA API версии 2.0 ) вы можете иметь несколько рекапч на одной странице.

Нет необходимости ни клонировать recaptcha, ни пытаться решить проблему. Вам просто нужно поместить несколько элементов div для рекапч и явно отобразить внутри них рекапчи.

Это легко сделать с помощью API-интерфейса google recaptcha:
https://developers.google.com/recaptcha/docs/display#explicit_render

Вот пример html-кода:

<form>
    <h1>Form 1</h1>
    <div><input type="text" name="field1" placeholder="field1"></div>
    <div><input type="text" name="field2" placeholder="field2"></div>
    <div id="RecaptchaField1"></div>
    <div><input type="submit"></div>
</form>

<form>
    <h1>Form 2</h1>
    <div><input type="text" name="field3" placeholder="field3"></div>
    <div><input type="text" name="field4" placeholder="field4"></div>
    <div id="RecaptchaField2"></div>
    <div><input type="submit"></div>
</form>

В вашем коде javascript вы должны определить функцию обратного вызова для recaptcha:

<script type="text/javascript">
    var CaptchaCallback = function() {
        grecaptcha.render('RecaptchaField1', {'sitekey' : '6Lc_your_site_key'});
        grecaptcha.render('RecaptchaField2', {'sitekey' : '6Lc_your_site_key'});
    };
</script>

После этого URL-адрес вашего скрипта recaptcha должен выглядеть так:

<script src="https://www.google.com/recaptcha/api.js?onload=CaptchaCallback&render=explicit" async defer></script>

Или вместо того, чтобы указывать идентификаторы для полей рекапчи, вы можете указать имя класса и зациклить эти элементы с помощью селектора классов и вызвать .render ()


1
Кстати, знаете ли вы, как добавить скрытое поле рекапчи для проверки jquery для каждого поля? В настоящее время у меня оно работает только с одним полем рекапчи, но может ли оно работать с двумя рекапчами? <input type = "hidden" class = "hiddenRecaptcha required" name = "hiddenRecaptcha" id = "hiddenRecaptcha">
Иван Хуарес,

2
@IvanJuarez Это хороший вопрос, чтобы задать ему новый вопрос.
Хусейн Яглы

2
Для тех из вас, кто хочет использовать grecaptcha.getResponse () с несколькими экземплярами, вы можете просто ссылаться на каждый рендер как 0,1,2 и т. Д. Например, первый экземпляр будет обозначаться как grecaptcha.getResponse (0).
Джин Келли,

1
Сэкономьте мое время, это идеальное решение
Мирза Обейд

2
Вот Это Да! Это потребовало некоторой работы, но чтобы добавить к примечанию @ GeneKelly относительно grecaptcha.getResponse(0)и grecaptcha.getResponse(1)для проверки нескольких экземпляров, я бы добавил, что индексация действительно должна соответствовать grecaptcha.renderпорядку. В этом примере grecaptcha.render('RecaptchaField1'...будет проверяться grecaptcha.getResponse(0)и grecaptcha.render('RecaptchaField2'...проверяться с помощью grecaptcha.getResponse(1)и т. Д.
codacopia

75

Просто и понятно:

1) Создайте поля рекапчи, как правило, следующим образом:

<div class="g-recaptcha" data-sitekey="YOUR_KEY_HERE"></div>

2) Загрузите скрипт следующим образом:

<script src="https://www.google.com/recaptcha/api.js?onload=CaptchaCallback&render=explicit" async defer></script>

3) Теперь вызовите это, чтобы перебирать поля и создавать рекапчи:

<script type="text/javascript">
  var CaptchaCallback = function() {
    jQuery('.g-recaptcha').each(function(index, el) {
        grecaptcha.render(el, {
            'sitekey' : jQuery(el).attr('data-sitekey')
            ,'theme' : jQuery(el).attr('data-theme')
            ,'size' : jQuery(el).attr('data-size')
            ,'tabindex' : jQuery(el).attr('data-tabindex')
            ,'callback' : jQuery(el).attr('data-callback')
            ,'expired-callback' : jQuery(el).attr('data-expired-callback')
            ,'error-callback' : jQuery(el).attr('data-error-callback')
        });
    });
  };
</script>

4
Это правильный путь, ИМО, это делает его динамичным, так как я могу иметь неограниченное количество экземпляров без определения статических идентификаторов
Грег Александр

1
Если вам нужно вручную извлечь код captcha (например, в запросах ajax), посмотрите мой ответ .
VanDir

Не могли бы вы взглянуть на мой вопрос ? Параметр POST становится пустым.
Марсио Маццукато

3
data-sitekey="YOUR_KEY_HERE"бесполезен и может быть удален из div (если вам нужно изменить ключ, меньше мест для редактирования)
the_nuts

3
На самом деле у вас там опечатка. Атрибут data-sitekey необходим и делает его еще более динамичным в случае, если у вас будет несколько ключей сайта, зачем вообще. Правильная строка будетgrecaptcha.render(el, {'sitekey' : $(el).attr('data-sitekey') });
Gkiokan

13

Это легко сделать с помощью clone()функции jQuery .

Таким образом, вы должны создать два блока-оболочки для рекапчи. Моя первая форма recaptcha div:

<div id="myrecap">
    <?php
        require_once('recaptchalib.php');
        $publickey = "XXXXXXXXXXX-XXXXXXXXXXX";
        echo recaptcha_get_html($publickey);
    ?>
</div>

Div второй формы пуст (другой идентификатор). Так что мой просто:

<div id="myraterecap"></div>

Тогда javascript довольно прост:

$(document).ready(function() {
    // Duplicate our reCapcha 
    $('#myraterecap').html($('#myrecap').clone(true,true));
});

Наверное, не нужен второй параметр со trueзначением внутри clone(), но это не повредит ... Единственная проблема с этим методом заключается в том, что если вы отправляете свою форму через ajax, проблема в том, что у вас есть два элемента, которые имеют с тем же именем, и вы должны мне немного поумнее фиксировать правильные значения элементов (два идентификатора для элементов #recaptcha_response_fieldreCaptcha и #recaptcha_challenge_field на случай, если они кому-то понадобятся)


Вы столкнетесь с проблемами, когда запросите новое испытание, так как он будет обновлять только один экземпляр
рекапчи

это не работает ... означает, что будет обновлена ​​только исходная капча (первая называется <div id = "myrecap"> здесь), а другая не будет обновлена
Oxi

На самом деле Окси, ваше беспокойство было рассмотрено в моем предыдущем комментарии
Серж Саган

1
Вы, вероятно, делаете это неправильно ... как насчет ссылки на ваш код в jsfiddle.net В любом случае, больше нет необходимости делать что-либо из этого ... вы должны использовать ответ Hüseyin Yağlı.
Серж Саган,

7

Я знаю, что это старый вопрос, но на тот случай, если кто-то будет его искать в будущем. На одной странице можно разместить две капчи. Розовая документация находится здесь: https://developers.google.com/recaptcha/docs/display. Пример ниже - это просто копия документа формы, и вам не нужно указывать разные макеты.

<script type="text/javascript">
  var verifyCallback = function(response) {
    alert(response);
  };
  var widgetId1;
  var widgetId2;
  var onloadCallback = function() {
    // Renders the HTML element with id 'example1' as a reCAPTCHA widget.
    // The id of the reCAPTCHA widget is assigned to 'widgetId1'.
    widgetId1 = grecaptcha.render('example1', {
      'sitekey' : 'your_site_key',
      'theme' : 'light'
    });
    widgetId2 = grecaptcha.render(document.getElementById('example2'), {
      'sitekey' : 'your_site_key'
    });
    grecaptcha.render('example3', {
      'sitekey' : 'your_site_key',
      'callback' : verifyCallback,
      'theme' : 'dark'
    });
  };
</script>

5

Этот ответ является расширением @raphadko ответа «s .

Если вам нужно вручную извлечь код капчи (как в запросах ajax), вам необходимо вызвать:

grecaptcha.getResponse(widget_id)

Но как получить параметр идентификатора виджета?

Я использую это определение CaptchaCallback для хранения идентификатора виджета каждого блока g-recaptcha (как атрибут данных HTML):

var CaptchaCallback = function() {
    jQuery('.g-recaptcha').each(function(index, el) {
        var widgetId = grecaptcha.render(el, {'sitekey' : 'your code'});
        jQuery(this).attr('data-widget-id', widgetId);
    });
};

Тогда я могу позвонить:

grecaptcha.getResponse(jQuery('#your_recaptcha_box_id').attr('data-widget-id'));

для извлечения кода.


1
Эй, спасибо за это. Что такое #your_recaptcha_box_id?
Лукас Бустаманте

4

У меня есть контактная форма в нижнем колонтитуле, которая всегда отображается, а также на некоторых страницах, таких как Create Account, тоже может быть captcha, поэтому он динамически, и я использую следующий способ с jQuery:

html:

<div class="g-recaptcha" id="g-recaptcha"></div>

<div class="g-recaptcha" id="g-recaptcha-footer"></div>

javascript

<script src="https://www.google.com/recaptcha/api.js?onload=CaptchaCallback&render=explicit&hl=en"></script>
<script type="text/javascript">
  var CaptchaCallback = function(){        
      $('.g-recaptcha').each(function(){
        grecaptcha.render(this,{'sitekey' : 'your_site_key'});
      })
  };
</script>

4

Это версия без JQuery ответа, предоставленного raphadko и существительным .

1) Создайте поля рекапчи, как правило, следующим образом:

<div class="g-recaptcha"></div>

2) Загрузите скрипт следующим образом:

<script src="https://www.google.com/recaptcha/api.js?onload=CaptchaCallback&render=explicit" async defer></script>

3) Теперь вызовите это, чтобы перебирать поля и создавать рекапчи:

var CaptchaCallback = function() {
    var captchas = document.getElementsByClassName("g-recaptcha");
    for(var i = 0; i < captchas.length; i++) {
        grecaptcha.render(captchas[i], {'sitekey' : 'YOUR_KEY_HERE'});
    }
};

2

Посмотрев на исходный код страницы, я взял часть reCaptcha и немного изменил код. Вот код:

HTML:

<div class="tabs">
    <ul class="product-tabs">
        <li id="product_tabs_new" class="active"><a href="#">Detailed Description</a></li>
        <li id="product_tabs_what"><a href="#">Request Information</a></li>
        <li id="product_tabs_wha"><a href="#">Make Offer</a></li>
    </ul>
</div>

<div class="tab_content">
    <li class="wide">
        <div id="product_tabs_new_contents">
            <?php $_description = $this->getProduct()->getDescription(); ?>
            <?php if ($_description): ?>
                <div class="std">
                    <h2><?php echo $this->__('Details') ?></h2>
                    <?php echo $this->helper('catalog/output')->productAttribute($this->getProduct(), $_description, 'description') ?>
                </div>
            <?php endif; ?>
        </div>
    </li>

    <li class="wide">
        <label for="recaptcha">Captcha</label>
        <div id="more_info_recaptcha_box" class="input-box more_info_recaptcha_box"></div>
    </li>

    <li class="wide">
        <label for="recaptcha">Captcha</label>
        <div id="make_offer_recaptcha_box" class="input-box make_offer_recaptcha_box"></div>
    </li>
</div>

jQuery:

<script type="text/javascript" src="http://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script>
<script type="text/javascript">
    jQuery(document).ready(function() {
        var recapExist = false;
      // Create our reCaptcha as needed
        jQuery('#product_tabs_what').click(function() {
            if(recapExist == false) {
                Recaptcha.create("<?php echo $publickey; ?>", "more_info_recaptcha_box");
                recapExist = "make_offer_recaptcha_box";
            } else if(recapExist == 'more_info_recaptcha_box') {
                Recaptcha.destroy(); // Don't really need this, but it's the proper way
                Recaptcha.create("<?php echo $publickey; ?>", "more_info_recaptcha_box");
                recapExist = "make_offer_recaptcha_box";
            }
        });
        jQuery('#product_tabs_wha').click(function() {
            if(recapExist == false) {
                Recaptcha.create("<?php echo $publickey; ?>", "make_offer_recaptcha_box");
                recapExist = "more_info_recaptcha_box";
            } else if(recapExist == 'make_offer_recaptcha_box') {
                Recaptcha.destroy(); // Don't really need this, but it's the proper way (I think :)
                Recaptcha.create("<?php echo $publickey; ?>", "make_offer_recaptcha_box");
                recapExist = "more_info_recaptcha_box";
            }
        });
    });
</script>

Я использую здесь простую функциональность вкладки javascript. Итак, не включил этот код.

Когда пользователь нажимает «Запросить информацию», (#product_tabs_what)JS проверяет, recapExistимеет falseли оно какое-то значение. Если у него есть значение, это вызовет Recaptcha.destroy();уничтожение старой загруженной reCaptcha и воссоздает ее для этой вкладки. В противном случае это просто создаст reCaptcha и поместит в #more_info_recaptcha_boxdiv. То же, что и для #product_tabs_whaвкладки «Сделать предложение» .


2

var ReCaptchaCallback = function() {
    	 $('.g-recaptcha').each(function(){
    		var el = $(this);
    		grecaptcha.render(el.get(0), {'sitekey' : el.data("sitekey")});
    	 });  
        };
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://www.google.com/recaptcha/api.js?onload=ReCaptchaCallback&render=explicit" async defer></script>


ReCaptcha 1
<div class="g-recaptcha" data-sitekey="6Lc8WQcUAAAAABQKSITdXbc6p9HISCQhZIJwm2Zw"></div>

ReCaptcha 2
<div class="g-recaptcha" data-sitekey="6Lc8WQcUAAAAABQKSITdXbc6p9HISCQhZIJwm2Zw"></div>

ReCaptcha 3
<div class="g-recaptcha" data-sitekey="6Lc8WQcUAAAAABQKSITdXbc6p9HISCQhZIJwm2Zw"></div>


где часть 2 форм?
MeSo2

прости, что не
понимаю

просто поместите <div class="g-recaptcha" data-sitekey="your_site_key"></div>там, где вам нужно, в формах /
divs

1

Хороший вариант - генерировать ввод рекапчи для каждой формы на лету (я сделал это с двумя, но вы, вероятно, могли бы создать три или более форм). Я использую jQuery, jQuery validation и jQuery form plugin для публикации формы через AJAX вместе с Recaptcha AJAX API -

https://developers.google.com/recaptcha/docs/display#recaptcha_methods

Когда пользователь отправляет одну из форм:

  1. перехватить отправку - я использовал свойство beforeSubmit плагина jQuery Form
  2. уничтожить все существующие входы recaptcha на странице - я использовал метод jQuery $ .empty () и Recaptcha.destroy ()
  3. вызовите Recaptcha.create (), чтобы создать поле рекапчи для конкретной формы
  4. вернуть ложь.

Затем они могут заполнить recaptcha и повторно отправить форму. Если вместо этого они решат отправить другую форму, то ваш код проверяет существующие рекапчи, так что у вас будет только одна рекапча на странице за раз.


1

Для того, чтобы добавить немного к raphadko ответ «s : так как у вас есть несколько каптч (на одной странице), Вы не можете использовать (универсальный) g-recaptcha-responseпараметр POST (потому что он содержит только один ответ Captcha в). Вместо этого вы должны использовать grecaptcha.getResponse(opt_widget_id)вызов для каждой капчи. Вот мой код (при условии, что каждая капча находится внутри своей формы):

HTML:

<form ... />

<div id="RecaptchaField1"></div>

<div class="field">
  <input type="hidden" name="grecaptcha" id="grecaptcha" />
</div>

</form>

и

<script src="https://www.google.com/recaptcha/api.js?onload=CaptchaCallback&render=explicit" async defer></script>

JavaScript:

var CaptchaCallback = function(){
    var widgetId;

    $('[id^=RecaptchaField]').each(function(index, el) {

         widgetId = grecaptcha.render(el.id, {'sitekey' : 'your_site_key'});

         $(el).closest("form").submit(function( event ) {

            this.grecaptcha.value = "{\"" + index + "\" => \"" + grecaptcha.getResponse(widgetId) + "\"}"

         });
    });
};

Обратите внимание, что я применяю делегирование событий (см. « Обновление DOM после добавления элемента» ) ко всем динамически изменяемым элементам. Это связывает ответ каждой отдельной капты с ее submitсобытием формы .


Вау, я часами искал это. Спасибо!!
Black

1

Вот решение, основанное на многих отличных ответах. Этот вариант является динамическим и свободным от jQuery, и не требует от вас целевого задания элементов по идентификатору.

1) Добавьте разметку reCAPTCHA, как обычно:

<div class="g-recaptcha" data-sitekey="YOUR_KEY_HERE"></div>

2) Добавьте в документ следующее. Он будет работать в любом браузере, поддерживающем API querySelectorAll.

<script src="https://www.google.com/recaptcha/api.js?onload=renderRecaptchas&render=explicit" async defer></script>
<script>
    window.renderRecaptchas = function() {
        var recaptchas = document.querySelectorAll('.g-recaptcha');
        for (var i = 0; i < recaptchas.length; i++) {
            grecaptcha.render(recaptchas[i], {
                sitekey: recaptchas[i].getAttribute('data-sitekey')
            });
        }
    }
</script>

1

grecaptcha.getResponse()Метод принимает необязательный «WIDGET_ID» параметр и значение по умолчанию для первого виджета , созданного , если не определены. Widget_id возвращается из grecaptcha.render()метода для каждого созданного виджета, он не связан с атрибутом idконтейнера reCAPTCHA !!

У каждой reCAPTCHA свои данные ответа. Вы должны указать идентификатор div reCAPTCHA и передать его getResponseметоду:

например

<div id="reCaptchaLogin"
     class="g-recaptcha required-entry"
     data-sitekey="<?php echo $this->helper('recaptcha')->getKey(); ?>"
     data-theme="<?php echo($this->helper('recaptcha')->getTheme()); ?>"
     style="transform:scale(0.82);-webkit-transform:scale(0.82);transform-origin:0 0;-webkit-transform-origin:0 0;">
</div>


<script type="text/javascript">
  var CaptchaCallback = function() {
    jQuery('.g-recaptcha').each(function(index, el) {
        grecaptcha.render(el, {
            'sitekey' : jQuery(el).attr('data-sitekey')
            ,'theme' : jQuery(el).attr('data-theme')
            ,'size' : jQuery(el).attr('data-size')
            ,'tabindex' : jQuery(el).attr('data-tabindex')
            ,'callback' : jQuery(el).attr('data-callback')
            ,'expired-callback' : jQuery(el).attr('data-expired-callback')
            ,'error-callback' : jQuery(el).attr('data-error-callback')
        });
    });
  };
</script>

<script src="https://www.google.com/recaptcha/api.js?onload=CaptchaCallback&render=explicit" async defer></script>

Ответ доступа:

var reCaptchaResponse = grecaptcha.getResponse(0);

или

var reCaptchaResponse = grecaptcha.getResponse(1);

0

Возможно, просто перезапишите обратные вызовы Recaptcha Ajax. Рабочий jsfiddle: http://jsfiddle.net/Vanit/Qu6kn/

Вам даже не нужен прокси-div, потому что при перезаписи код DOM не будет выполняться. Вызывайте Recaptcha.reload () всякий раз, когда хотите снова запустить обратные вызовы.

function doSomething(challenge){
    $(':input[name=recaptcha_challenge_field]').val(challenge);
    $('img.recaptcha').attr('src', '//www.google.com/recaptcha/api/image?c='+challenge);
}

//Called on Recaptcha.reload()
Recaptcha.finish_reload = function(challenge,b,c){
    doSomething(challenge);
}

//Called on page load
Recaptcha.challenge_callback = function(){
    doSomething(RecaptchaState.challenge)
}

Recaptcha.create("YOUR_PUBLIC_KEY");

0

Вот хорошее руководство для этого:

http://mycodde.blogspot.com.ar/2014/12/multiple-recaptcha-demo-same-page.html

Обычно вы добавляете некоторые параметры к вызову API и вручную визуализируете каждую рекапчу:

<script src="https://www.google.com/recaptcha/api.js?onload=myCallBack&render=explicit" async defer></script>
<script>
        var recaptcha1;
        var recaptcha2;
        var myCallBack = function() {
            //Render the recaptcha1 on the element with ID "recaptcha1"
            recaptcha1 = grecaptcha.render('recaptcha1', {
                'sitekey' : '6Lc_0f4SAAAAAF9ZA', //Replace this with your Site key
                'theme' : 'light'
            });

            //Render the recaptcha2 on the element with ID "recaptcha2"
            recaptcha2 = grecaptcha.render('recaptcha2', {
                'sitekey' : '6Lc_0f4SAAAAAF9ZA', //Replace this with your Site key
                'theme' : 'dark'
            });
        };
</script>

PS: Метод "grecaptcha.render" получает идентификатор


0

Я бы использовал невидимую рекапчу. Затем на вашей кнопке используйте тег типа «formname = 'yourformname'», чтобы указать, какая форма должна быть отправлена, и скрыть ввод формы отправки.

Преимущество этого заключается в том, что он позволяет вам сохранить целостность проверки формы html5, одну recaptcha, но несколько интерфейсов кнопок. Просто зафиксируйте входное значение «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>
var formanme = ''
$('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>

Я считаю, что это НАМНОГО проще и легче в управлении.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.