web-dev-qa-db-fra.com

Comment puis-je afficher plusieurs recaptchas sur une seule page?

J'ai 2 formulaires sur une seule page. Une des formes a un recaptcha affiché tout le temps. L'autre ne doit afficher un recaptcha qu'après un certain événement, tel que le nombre maximal de tentatives de connexion. Donc, il y a des moments où il me faudrait 2 recaptchas pour apparaître sur la même page. Est-ce possible? Je sais que je pourrais probablement en utiliser un seul pour les deux, mais je préférerais de beaucoup en avoir deux. Merci.

Mise à jour: eh bien, je suppose que cela pourrait ne pas être possible. Quelqu'un peut-il recommander une autre bibliothèque de capture à utiliser côte à côte avec reCaptcha? Je veux vraiment pouvoir avoir 2 captchas sur la même page.

Update 2: / Et si on mettait chaque formulaire dans une iframe? Serait-ce une solution acceptable?

90
oym

Une question similaire a été posée à propos de cette opération sur une page ASP ( link ) et, de l’avis général, il n’était pas possible de le faire avec recaptcha. Il semble que plusieurs formulaires d'une même page doivent partager le captcha, à moins que vous ne souhaitiez utiliser un captcha différent. Si vous n’êtes pas verrouillé dans recaptcha, vous pouvez jeter un œil au composant Zend_Captcha de Zend Frameworks ( link ). Il contient quelques 

9
Steven Surowiec

Avec la version actuelle de Recaptcha ( reCAPTCHA API version 2.0 ), vous pouvez avoir plusieurs recaptchas sur une page.

Il n'est pas nécessaire de cloner le recaptcha ni d'essayer de contourner le problème. Il vous suffit de placer plusieurs éléments div pour les recaptchas et de les rendre explicitement à l'intérieur.

C’est facile avec l’API Google Recaptcha:
https://developers.google.com/recaptcha/docs/display#explicit_render

Voici l'exemple de code 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>

Dans votre code javascript, vous devez définir une fonction de rappel pour 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>

Après cela, votre URL de script recaptcha devrait ressembler à ceci:

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

Ou au lieu de donner des identifiants à vos champs recaptcha, vous pouvez donner un nom de classe et mettre en boucle ces éléments avec votre sélecteur de classe et appeler .render ()

186
Hüseyin Yağlı

Simple et direct:

1) Créez vos champs recaptcha normalement avec ceci:

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

2) Chargez le script avec ceci:

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

3) Appelez maintenant ceci pour parcourir les champs et créer les 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>
68
raphadko

Ceci est facilement accompli avec la fonction clone() de jQuery.

Donc, vous devez créer deux divs wrapper pour le recaptcha. Ma première forme recaptcha div:

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

Le div du second formulaire est vide (identifiant différent). Donc le mien est juste:

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

Alors le javascript est assez simple:

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

Probablement pas besoin du second paramètre avec une valeur true dans clone(), mais cela ne fait pas de mal de l'avoir ... Le seul problème avec cette méthode est si vous soumettez votre formulaire via ajax, le problème est que vous avez deux éléments qui portent le même nom et vous devez être un peu plus intelligent avec la façon dont vous capturez les valeurs de cet élément correct (les deux identifiants des éléments reCaptcha sont #recaptcha_response_field et #recaptcha_challenge_field au cas où quelqu'un en aurait besoin)

14
Serj Sagan

Je sais que cette question est ancienne mais au cas où quelqu'un le chercherait à l'avenir. Il est possible d'avoir deux captcha sur une page. La documentation en rose se trouve ici: https://developers.google.com/recaptcha/docs/display L’exemple ci-dessous n’est qu’une copie du document et il n’est pas nécessaire de spécifier différentes mises en page.

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

Cette réponse est une extension de la réponse de @raphadko .

Si vous devez extraire manuellement le code captcha (comme dans les requêtes ajax), vous devez appeler:

grecaptcha.getResponse(widget_id)

Mais comment pouvez-vous récupérer le paramètre id du widget?

J'utilise cette définition de CaptchaCallback pour stocker le identifiant de widget de chaque zone g-recaptcha (en tant qu'attribut de données 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);
    });
};

Alors je peux appeler:

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

extraire le code.

6
VanDir

Ceci est une version sans réponse de JQuery de la réponse fournie par raphadko et nom .

1) Créez vos champs recaptcha normalement avec ceci:

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

2) Chargez le script avec ceci:

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

3) Appelez maintenant ceci pour parcourir les champs et créer les 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'});
    }
};
4
turboLoop

J'ai un formulaire de contact dans le pied de page qui affiche toujours et certaines pages, comme Créer un compte, peuvent aussi avoir un captcha, c'est donc dynamiquement et j'utilise la méthode suivante avec 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>
3
Sergey Kharchishin

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

En regardant le code source de la page, j'ai pris la partie reCaptcha et changé un peu le code. Voici le code:

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>

J'utilise ici la fonctionnalité simple de l'onglet javascript. Donc, n'a pas inclus ce code. 

Lorsque l'utilisateur clique sur "Demande d'informations" (#product_tabs_what), JS vérifie si recapExist est false ou a une valeur. Si elle a une valeur, ceci appellera Recaptcha.destroy(); pour détruire l'ancien reCaptcha chargé et le recréera pour cet onglet. Sinon, cela créera simplement un reCaptcha et sera placé dans le #more_info_recaptcha_box div. Identique à l'onglet "Créer une offre" #product_tabs_wha.

2
Omar Faruk Sharif

Voici une solution qui s'appuie sur bon nombre des excellentes réponses. Cette option est jQuery libre et dynamique, ne vous obligeant pas à cibler spécifiquement les éléments par id. 

1) Ajoutez votre balise reCAPTCHA comme vous le feriez normalement:

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

2) Ajoutez ce qui suit dans le document. Cela fonctionnera dans n'importe quel navigateur qui supporte l'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
kfriend

Pour ajouter un peu à la réponse de raphadko : puisque vous avez plusieurs captchas (sur une page), vous ne pouvez pas utiliser le paramètre (universel) g-recaptcha-response POST (car il ne contient que la réponse d'un captcha). Au lieu de cela, vous devriez utiliser l'appel grecaptcha.getResponse(opt_widget_id) pour chaque captcha. Voici mon code (à condition que chaque captcha soit à l'intérieur de sa forme):

HTML:

<form ... />

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

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

</form>

et

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

         });
    });
};

Notez que j'applique la délégation d'événements (voir actualise le DOM après l'ajout d'élément ) à tous les éléments modifiés dynamiquement. Cela lie la réponse de chaque captha à son événement submit de forme.

1
prograils

Une bonne option consiste à générer une entrée recaptcha pour chaque formulaire à la volée (je l'ai déjà fait avec deux, mais vous pouvez probablement en créer trois ou plus). J'utilise jQuery, la validation jQuery et le plug-in de formulaire jQuery pour publier le formulaire via AJAX, avec l'API Recaptcha AJAX - 

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

Lorsque l'utilisateur soumet l'un des formulaires:

  1. intercepter la soumission - j'ai utilisé la propriété beforeSubmit de jQuery Form Plugin
  2. détruire toutes les entrées recaptcha existantes sur la page - j'ai utilisé la méthode $ .empty () de jQuery et Recaptcha.destroy ()
  3. appelez Recaptcha.create () pour créer un champ recaptcha pour le formulaire spécifique
  4. retourne faux. 

Ils peuvent ensuite remplir le formulaire recaptcha et soumettre à nouveau le formulaire. S'ils décident de soumettre un formulaire différent à la place, votre code vérifie les recaptchas existants de sorte que vous n'aurez qu'un seul recaptcha sur la page à la fois.

1
siliconrockstar

Je voudrais utiliser invisible recaptcha. Ensuite, sur votre bouton, utilisez une balise telle que "formname = 'yourformname" "pour spécifier le formulaire à soumettre et masquer une entrée de formulaire de soumission. 

L'avantage de cela est qu'il vous permet de garder la validation du formulaire html5 intacte, une interface recaptcha, mais plusieurs interfaces de bouton. Capturez simplement la valeur d'entrée "captcha" pour la clé de jeton générée par 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>

Je trouve cette FAR plus simple et plus facile à gérer. 

0
eatmeimadanish

C'est possible, écrasez simplement les rappels Recaptcha Ajax. Working jsfiddle: http://jsfiddle.net/Vanit/Qu6kn/

Vous n'avez même pas besoin d'un div de proxy car avec les écrasements, le code DOM ne s'exécutera pas. Appelez Recaptcha.reload () chaque fois que vous souhaitez déclencher à nouveau les rappels.

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
Vanit

Voici un bon guide pour faire exactement cela:

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

Fondamentalement, vous ajoutez quelques paramètres à l'appel api et rendez manuellement chaque 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: la méthode "grecaptcha.render" reçoit un identifiant

0
Marco

La méthode grecaptcha.getResponse() accepte un paramètre facultatif "widget_id" et utilise par défaut le premier widget créé s'il n'est pas spécifié. Un widget_id est renvoyé par la méthode grecaptcha.render() pour chaque widget créé, il n'est pas lié à l'attribut id du conteneur reCAPTCHA !!

Chaque reCAPTCHA a ses propres données de réponse. Vous devez donner un identifiant à la division reCAPTCHA et le transmettre à la méthode getResponse:

par exemple.

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

Réponse d'accès:

var reCaptchaResponse = grecaptcha.getResponse(0);

ou 

var reCaptchaResponse = grecaptcha.getResponse(1);
0
Black