Comment afficher plusieurs recaptchas sur une seule page?
j'ai 2 formulaires sur une seule page. Un des formulaires a une recaptcha affichant tout le temps. L'autre ne devrait afficher un recaptcha qu'après un certain événement tel que maxer les tentatives de connexion. Il y a donc des moments où j'aurais besoin de 2 recaptchas apparaître sur la même page. Est-ce possible? Je sais que je pourrais probablement utiliser un seul pour les deux, mais la façon dont j'ai la disposition, je préférerais beaucoup avoir 2. Grâce.
mise à Jour: eh bien, je imagine que ça peut ne pas être possible. Est-ce que quelqu'un peut 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.
mise à jour 2: que se passe-t-il si vous mettez chaque formulaire dans une iframe? Serait-ce une solution acceptable?
17 réponses
une question similaire a été posée à propos de faire cela sur une page ASP ( lien ) et le consensus là-bas était qu'il n'était pas possible de faire avec recaptcha. Il semble que plusieurs formulaires sur une même page doivent partager le captcha, à moins que vous ne soyez prêt à utiliser un captcha différent. Si vous n'êtes pas enfermé dans recaptcha, une bonne bibliothèque à consulter est le composant Zend Frameworks Zend_Captcha ( link ). Il contient quelques
avec la version actuelle de Recaptcha ( reCAPTCHA API version 2.0 ), vous pouvez avoir plusieurs recaptchas sur une seule page.
il n'est pas nécessaire de cloner le recaptcha ni d'essayer de contourner le problème. Vous avez juste à mettre plusieurs éléments div pour les recaptchas et rendre les recaptchas à l'intérieur d'eux explicitement.
c'est facile avec l'api Google recaptcha:
https://developers.google.com/recaptcha/docs/display#explicit_render
voici le code html de l'exemple:
<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, l'url de votre 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 ID à vos champs recaptcha, vous pouvez donner un nom de classe et boucler ces éléments avec votre sélecteur de classe et d'appel .render ()
Simple et simple:
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) maintenant appelez cela pour itérer au-dessus des champs et créer le 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>
cela est facilement accompli avec la fonction clone()
de jQuery.
donc vous devez créer deux divs d'emballage pour la recaptcha. Mon premier formulaire est 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 (ID 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));
});
N'a probablement pas besoin du second paramètre avec une valeur true
dans clone()
, mais ça ne fait pas de mal de l'avoir... Le seul problème avec cette méthode est que si vous soumettez votre formulaire via ajax, le problème est que vous avez deux éléments qui ont le même nom et vous devez moi un peu plus intelligent avec la façon dont vous capturez les valeurs de cet élément correct (les deux ids pour les éléments de reCaptcha sont #recaptcha_response_field
et #recaptcha_challenge_field juste au cas où quelqu'un a besoin d'eux)
je sais que cette question Est ancienne, mais au cas où quelqu'un la chercherait à l'avenir. Il est possible d'avoir deux captcha sur une page. Pink to documentation est ici: https://developers.google.com/recaptcha/docs/display Exemple ci-dessous est juste une copie du formulaire doc et vous n'avez pas à spécifier des mises en page différentes.
<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>
cette réponse est une extension de @raphadko 's answer .
si vous devez extraire manuellement le code captcha (comme dans les requêtes ajax) vous devez appeler:
grecaptcha.getResponse(widget_id)
mais comment récupérer le paramètre widget id?
j'utilise cette définition de CaptchaCallback pour stocker le widget id de chaque boîte g-recaptcha (comme 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'));
pour extraire le code.
il s'agit d'une version sans 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 itérer au-dessus des champs et créer le 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'});
}
};
j'ai le formulaire de contact dans le pied de page qui s'affiche toujours et aussi certaines pages, comme Create Account, peuvent avoir captcha aussi, donc c'est dynamique et j'utilise la prochaine façon 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>
en regardant le code source de la page j'ai pris la partie reCaptcha et changé le code un peu. 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é d'onglet javascript simple. Donc, je n'ai pas inclus ce code.
quand l'utilisateur cliquerait sur "demande D'Information" (#product_tabs_what)
alors JS vérifiera si recapExist
est false
ou a une certaine valeur. S'il a une valeur alors cela appellera Recaptcha.destroy();
pour détruire le vieux reCaptcha chargé et le recréera pour cet onglet. Sinon, cela créera simplement une reCaptcha et placera dans le #more_info_recaptcha_box
div. Identique à L'onglet" faire une offre " #product_tabs_wha
.
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>
une bonne option est de générer une entrée recaptcha pour chaque formulaire à la volée (Je l'ai fait avec deux, mais vous pourriez probablement faire trois formulaires ou plus). J'utilise jQuery, jQuery validation, et jQuery form plugin pour poster le formulaire via AJAX, avec L'API de Recaptcha AJAX -
https://developers.google.com/recaptcha/docs/display#recaptcha_methods
lorsque l'utilisateur soumet l'un des formulaires:
- intercepter la soumission - j'ai utilisé jQuery Formulaire du Plugin beforeSubmit propriété
- détruisez les entrées existantes de recaptcha sur la page - j'ai utilisé le $de jQuery.méthode empty () et Recaptcha.destroy ()
- appel Recaptcha.créer () pour créer un champ recaptcha pour le formulaire spécifique
- return false.
ensuite, ils peuvent remplir le recaptcha et soumettre de nouveau le formulaire. Si ils décidez de soumettre un formulaire différent à la place, bien, votre code vérifie pour les recaptchas existants de sorte que vous aurez seulement une recaptcha sur la page à la fois.
pour ajouter un peu à raphadko 's answer : depuis que vous avez plusieurs captchas (sur une page), vous ne pouvez pas utiliser le paramètre (universel) g-recaptcha-response
POST (parce qu'il contient une seule réponse captcha). Vous devez plutôt utiliser grecaptcha.getResponse(opt_widget_id)
pour chaque appel captcha. Voici mon code (pourvu que chaque captcha soit dans 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énement (Voir rafraîchir DOM après Ajouter l'élément ) à tous les éléments dynamiquement modifiés. Cela lie la réponse de chaque captha à son événement de forme submit
.
Voici une solution qui s'appuie sur plusieurs des excellentes réponses. Cette option est libre de jQuery, et dynamique, ne vous obligeant pas à cibler spécifiquement les éléments par id.
1) Ajoutez votre marqueur reCAPTCHA comme vous le feriez normalement:
<div class="g-recaptcha" data-sitekey="YOUR_KEY_HERE"></div>
2) ajouter ce qui suit dans le document. Il fonctionnera dans n'importe quel navigateur qui prend en charge le querySelectorAll API
<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>
il est possible, juste écraser les callbacks De Recaptcha Ajax. Working jsfiddle: http://jsfiddle.net/Vanit/Qu6kn /
vous n'avez même pas besoin d'un proxy div car avec les overwrites le code DOM ne sera pas exécuté. Appelle Recaptcha.recharger () chaque fois que vous voulez déclencher les callbacks à nouveau.
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");
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 rendre 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: Le "grecaptcha.le rendu de la" méthode reçoit un ID
j'utiliserais invisible recaptcha. Ensuite, sur votre bouton, utilisez une balise comme "formname=' yourformname '" pour spécifier le formulaire à soumettre et masquer une entrée de formulaire à soumettre.
l'avantage de ceci est qu'il vous permet de garder la validation du formulaire html5 intacte, Une recaptcha, mais des interfaces à boutons multiples. Il suffit de capturer la valeur d'entrée "captcha" pour la clé token 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 cela beaucoup plus simple et plus facile à gérer.
la méthode grecaptcha.getResponse()
accepte un paramètre optionnel "widget_id", et par défaut le premier widget créé si non spécifié. Un widget_id est retourné de la méthode grecaptcha.render()
pour chaque widget créé, il n'est pas lié à l'attribut id
du conteneur reCAPTCHA!!
chaque reCAPTCHA possède ses propres données de réponse.
Vous devez donner un ID de div de reCAPTCHA et le passer à la méthode getResponse
:
p.ex.
<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>
l'Accès de réponse:
var reCaptchaResponse = grecaptcha.getResponse(0);
ou
var reCaptchaResponse = grecaptcha.getResponse(1);