Como faço para mostrar várias recaptchas em uma única página?


102

Tenho 2 formulários em uma única página. Um dos formulários tem um recaptcha sendo exibido o tempo todo. O outro deve exibir uma recaptcha somente após um determinado evento, como o limite de tentativas de login. Portanto, há momentos em que eu precisaria de 2 recaptchas para aparecer na mesma página. Isso é possível? Sei que provavelmente poderia usar um único para os dois, mas da forma como tenho o layout, prefiro ter 2. Obrigado.

Atualização: bem, acho que pode não ser possível. Alguém pode recomendar outra biblioteca de captura para usar lado a lado com o reCaptcha? Eu realmente quero poder ter 2 captchas na mesma página.

Atualização 2: e se colocar cada formulário em um iframe? Isso seria uma solução aceitável?


Você não poderia simplesmente exibir o mesmo duas vezes?
Tyler Carter

1
Eu tentei isso ... quando tento duplicar o código do captcha, ele apenas exibe o captcha que vem primeiro
oym

Qualquer pessoa que encontrar isso para a nova API de recaptcha, isso é possível usando o carregamento explícito descrito com exemplos nos documentos em developers.google.com/recaptcha/docs/display#recaptcha_methods
El Yobo

3
Um iframe deveria ser possível, mas é uma maneira ruim de resolver o problema, em comparação com o uso de JavaScript, como na Hüseyin Yağlıresposta de . A maioria dos navegadores deve oferecer suporte a JavaScript e o reCAPTCHA padrão usa JavaScript de qualquer maneira. No entanto, não sei o que seria necessário fazer para resolver o problema sem o suporte a JavaScript.
Edward

Respostas:


14

Uma pergunta semelhante foi feita sobre fazer isso em uma página ASP ( link ) e o consenso ali era que não era possível fazer com recaptcha. Parece que vários formulários em uma única página devem compartilhar o captcha, a menos que você queira usar um captcha diferente. Se você não estiver preso ao recaptcha, uma boa biblioteca para dar uma olhada é o componente Zend Frameworks Zend_Captcha ( link ). Contém alguns


9
Na verdade , é possível com o reCAPTCHA , mas não é possível fazer sem JavaScript . A maioria dos navegadores deve suportar JavaScript e o ReCaptcha padrão usa JavaScript de qualquer maneira, então esta solução é boa. Hüseyin YağlıA resposta de explica a solução. A documentação do reCAPTCHA para esta solução está em developers.google.com/recaptcha/docs/display#explicit_render . No entanto, não sei o que seria necessário fazer para resolver o problema sem o suporte a JavaScript.
Edward

Na verdade, é absolutamente possível com o reCAPTCHA
Carlos Espinoza

208

Com a versão atual do Recaptcha ( reCAPTCHA API versão 2.0 ), você pode ter vários recaptchas em uma página.

Não há necessidade de clonar o recaptcha nem tentar contornar o problema. Você apenas precisa colocar vários elementos div para os recaptchas e renderizar os recaptchas dentro deles explicitamente.

Isso é fácil com o google recaptcha api:
https://developers.google.com/recaptcha/docs/display#explicit_render

Aqui está o exemplo de código 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>

Em seu código javascript, você deve definir uma função de retorno de chamada para 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>

Depois disso, o url do seu script recaptcha deve ser semelhante a este:

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

Ou, em vez de fornecer IDs para seus campos de recaptcha, você pode dar um nome de classe e fazer um loop desses elementos com seu seletor de classe e chamar .render ()


1
Coincidentemente, você sabe como adicionar o campo recaptcha oculto para validação do jquery para cada campo? Atualmente, estou trabalhando com apenas 1 recaptchafield, mas pode funcionar com dois recaptchas? <input type = "hidden" class = "hiddenRecaptcha obrigatório" name = "hiddenRecaptcha" id = "hiddenRecaptcha">
Ivan Juarez

2
@IvanJuarez Esta é uma boa pergunta para se fazer como uma pergunta nova.
Hüseyin Yağlı

2
Para aqueles que desejam usar grecaptcha.getResponse () com várias instâncias, você pode simplesmente fazer referência a cada renderização como 0,1,2, etc. Por exemplo, a primeira instância seria referenciada como grecaptcha.getResponse (0).
Gene Kelly

1
Economize meu tempo, a solução perfeita
Mirza Obaid

2
Uau! Isso demandou algum trabalho, mas para acrescentar à nota de @GeneKelly a respeito grecaptcha.getResponse(0)e grecaptcha.getResponse(1)para validar várias instâncias, eu acrescentaria que a indexação tem que corresponder à grecaptcha.renderordem. Para este exemplo, grecaptcha.render('RecaptchaField1'...seria verificado com grecaptcha.getResponse(0)e grecaptcha.render('RecaptchaField2'...seria verificado com grecaptcha.getResponse(1), etc ...
codacopia

75

Simples e direto:

1) Crie seus campos de recaptcha normalmente com este:

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

2) Carregue o script com isto:

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

3) Agora chame isso para iterar os campos e criar as recaptchas:

<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
Este é o caminho certo, IMO, o que o torna dinâmico, pois posso ter instâncias ilimitadas sem definir ids estáticos
Greg Alexander

1
Se você precisar extrair manualmente o código captcha (como em solicitações ajax), veja minha resposta .
VanDir

Você poderia dar uma olhada na minha pergunta ? O parâmetro POST ficará vazio.
Marcio Mazzucato

3
data-sitekey="YOUR_KEY_HERE"é inútil e pode ser removido do div (se você precisar alterar a chave, menos lugares para editar)
the_nuts

3
Na verdade, você cometeu um erro de digitação. O atributo data-sitekey é necessário e torna isso ainda mais dinâmico, caso você tenha vários siteskey. A linha correta seriagrecaptcha.render(el, {'sitekey' : $(el).attr('data-sitekey') });
Gkiokan

13

Isso é facilmente realizado com a clone()função jQuery .

Portanto, você deve criar duas divs wrapper para o recaptcha. Div recaptcha do meu primeiro formulário:

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

O div do segundo formulário está vazio (ID diferente). Então o meu é apenas:

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

Então o javascript é bastante simples:

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

Provavelmente não precisa do segundo parâmetro com um truevalor em clone(), mas não custa nada tê-lo ... O único problema com este método é se você está enviando seu formulário via ajax, o problema é que você tem dois elementos que têm o mesmo nome e você deve me um pouco mais esperto com a maneira como você captura os valores desse elemento correto (os dois ids para elementos reCaptcha são #recaptcha_response_fielde #recaptcha_challenge_field apenas no caso de alguém precisar deles)


Você encontrará problemas quando solicitar um novo desafio, pois ele atualizará apenas uma instância de recaptcha
Ogugua Belonwu

isso não funciona ... significa que apenas o captcha original (o primeiro chamado <div id = "myrecap"> aqui) será atualizado apenas, e outro não será atualizado
Oxi

Na verdade, Oxi, sua preocupação foi abordada por meu comentário anterior
Serj Sagan

1
Você provavelmente está fazendo errado ... que tal um link para seu código em jsfiddle.net De qualquer forma, não há mais necessidade de fazer nada disso ... você deve usar a resposta de Hüseyin Yağlı.
Serj Sagan

7

Eu sei que esta pergunta é antiga, mas no caso de alguém procurar por ela no futuro. É possível ter dois captcha em uma página. Rosa para a documentação está aqui: https://developers.google.com/recaptcha/docs/display O exemplo abaixo é apenas uma cópia do documento e você não precisa especificar layouts diferentes.

<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

Esta resposta é uma extensão para @raphadko resposta 's .

Se você precisar extrair manualmente o código captcha (como em solicitações ajax), deverá chamar:

grecaptcha.getResponse(widget_id)

Mas como você pode recuperar o parâmetro id do widget?

Eu uso esta definição de CaptchaCallback para armazenar o id do widget de cada caixa g-recaptcha (como um atributo de dados 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);
    });
};

Então posso ligar para:

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

para extrair o código.


1
Ei, obrigado por isso. O que é #your_recaptcha_box_id?
Lucas Bustamante

4

Tenho formulário de contato em rodapé que sempre exibe e também algumas páginas, como Criar Conta, podem ter captcha também, então é dinamicamente e estou usando a próxima forma com 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

Esta é uma versão livre de JQuery da resposta fornecida por raphadko e substantivo .

1) Crie seus campos de recaptcha normalmente com este:

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

2) Carregue o script com isto:

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

3) Agora chame isso para iterar os campos e criar as recaptchas:

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

Olhando para o código-fonte da página, peguei a parte do reCaptcha e mudei um pouco o código. Aqui está o código:

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>

Estou usando aqui a funcionalidade de guia de javascript simples. Então, não incluí esse código.

Quando o usuário clica em "Solicitar informações" (#product_tabs_what), o JS verifica se recapExisté falseou tem algum valor. Se tiver um valor, isso irá chamar Recaptcha.destroy();para destruir o antigo reCaptcha carregado e irá recriá-lo para esta guia. Caso contrário, isso apenas criará um reCaptcha e será colocado no #more_info_recaptcha_boxdiv. O mesmo que para a #product_tabs_whaguia "Fazer oferta" .


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>


onde está a parte 2 formas?
MeSo2

desculpe não ter
entendido

basta colocar <div class="g-recaptcha" data-sitekey="your_site_key"></div>onde você precisa, no forms / divs
surinder singh

1

Uma boa opção é gerar uma entrada de recaptcha para cada formulário na hora (fiz isso com dois, mas provavelmente você poderia fazer três ou mais formulários). Estou usando jQuery, jQuery validation e jQuery form plugin para postar o formulário via AJAX, junto com a API Recaptcha AJAX -

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

Quando o usuário envia um dos formulários:

  1. interceptar o envio - usei a propriedade beforeSubmit do plug-in de formulário jQuery
  2. destruir todas as entradas recaptcha existentes na página - usei o método $ .empty () do jQuery e Recaptcha.destroy ()
  3. chame Recaptcha.create () para criar um campo recaptcha para o formulário específico
  4. retorna falso.

Em seguida, eles podem preencher a recaptcha e reenviar o formulário. Se eles decidirem enviar um formulário diferente, bem, seu código verifica se há recaptchas existentes, então você terá apenas um recaptcha na página por vez.


1

Para adicionar um pouco à resposta do raphadko : como você tem vários captchas (em uma página), você não pode usar o g-recaptcha-responseparâmetro POST (universal) (porque ele contém apenas uma resposta do captcha). Em vez disso, você deve usar grecaptcha.getResponse(opt_widget_id)call para cada captcha. Este é meu código (desde que cada captcha esteja dentro de sua forma):

HTML:

<form ... />

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

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

</form>

e

<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) + "\"}"

         });
    });
};

Observe que aplico a delegação de evento (consulte atualizar DOM após adicionar elemento ) a todos os elementos modificados dinamicamente. Isso vincula a resposta de cada captha individual ao seu submitevento de formulário .


Uau, eu estava procurando por isso por horas. Obrigado!!
Preto

1

Aqui está uma solução que se baseia em muitas das respostas excelentes. Esta opção é livre de jQuery e dinâmica, não exigindo que você direcione especificamente os elementos por id.

1) Adicione sua marcação reCAPTCHA como faria normalmente:

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

2) Adicione o seguinte ao documento. Funcionará em qualquer navegador compatível com a 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

O grecaptcha.getResponse()método aceita um parâmetro opcional "widget_id" e o padrão é o primeiro widget criado, se não especificado. Um widget_id é retornado do grecaptcha.render()método para cada widget criado, não está relacionado ao atributo iddo contêiner reCAPTCHA !!

Cada reCAPTCHA possui seus próprios dados de resposta. Você deve fornecer ao div reCAPTCHA um ID e passá-lo para o getResponsemétodo:

por exemplo

<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>

Resposta de acesso:

var reCaptchaResponse = grecaptcha.getResponse(0);

ou

var reCaptchaResponse = grecaptcha.getResponse(1);

0

É possível, apenas sobrescrever os callbacks do Recaptcha Ajax. Jsfiddle de trabalho: http://jsfiddle.net/Vanit/Qu6kn/

Você nem mesmo precisa de um div de proxy porque com as sobrescritas o código DOM não será executado. Chame Recaptcha.reload () sempre que quiser acionar os callbacks novamente.

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

Aqui está um bom guia para fazer exatamente isso:

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

Basicamente, você adiciona alguns parâmetros à chamada da API e renderiza manualmente cada recaptcha:

<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: O método "grecaptcha.render" recebe um ID


0

Eu usaria recaptcha invisível. Então, no botão, use uma tag como "formname = 'yourformname'" para especificar qual formulário deve ser enviado e ocultar uma entrada de formulário de envio.

A vantagem disso é que permite que você mantenha a validação do formulário html5 intacta, uma recaptcha, mas várias interfaces de botão. Basta capturar o valor de entrada "captcha" para a chave de token gerada pelo 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>

Acho isso muito mais simples e fácil de gerenciar.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.