如何在单个页面上显示多个recaptchas?
我在一个页面上有两个表单。 其中一种forms有一个显示所有时间的recaptcha。 另一个应该显示一个recaptcha只有在一定的事件,如最大限度的login尝试。 所以有时候我会需要2个recaptchas出现在同一页面上。 这可能吗? 我知道我可以使用一个单一的,但我有布局的方式,我更愿意有2.谢谢。
更新:以及我想这可能是不可能的。 任何人都可以推荐另一个捕获库与reCaptcha一起使用吗? 我真的希望能够在同一页上有2个validation码。
更新2:如果把每个表单放在iframe中怎么办? 这是一个可接受的解决scheme?
一个类似的问题被问及在ASP页面上做这件事情( 链接 ),那里的共识是,这是不可能与recaptcha。 看来,单个页面上的多个表单必须共享validation码,除非您愿意使用不同的validation码。 如果你没有lockingrecaptcha一个好的图书馆来看看是Zend框架Zend_Captcha组件( 链接 )。 它包含一些
使用当前版本的Recaptcha( reCAPTCHA API版本2.0 ),您可以在一个页面上拥有多个recaptchas。
不需要复制recaptcha,也不需要解决问题。 你只需要为recaptchas放置多个div元素,并在其中明确地呈现recaptchas。
谷歌recaptcha api很容易:
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定义一个callback函数:
<script type="text/javascript"> var CaptchaCallback = function() { grecaptcha.render('RecaptchaField1', {'sitekey' : '6Lc_your_site_key'}); grecaptcha.render('RecaptchaField2', {'sitekey' : '6Lc_your_site_key'}); }; </script>
在此之后,您的recaptcha脚本url应如下所示:
<script src="https://www.google.com/recaptcha/api.js?onload=CaptchaCallback&render=explicit" async defer></script>
简单而直接:
1)正常创build你的recaptcha字段:
<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)现在调用这个遍历字段并创buildrecaptchas:
<script type="text/javascript"> var CaptchaCallback = function() { $('.g-recaptcha').each(function(index, el) { grecaptcha.render(el, {'sitekey' : 'your_key'}); }); }; </script>
这很容易用jQuery的clone()
函数完成。
所以你必须为recaptcha创build两个包装div。 我的第一个表单的recaptcha div:
<div id="myrecap"> <?php require_once('recaptchalib.php'); $publickey = "XXXXXXXXXXX-XXXXXXXXXXX"; echo recaptcha_get_html($publickey); ?> </div>
第二种forms的div是空的(不同的ID)。 所以我的只是:
<div id="myraterecap"></div>
那么JavaScript很简单:
$(document).ready(function() { // Duplicate our reCapcha $('#myraterecap').html($('#myrecap').clone(true,true)); });
可能不需要第二个参数在clone()
有一个true
值,但不会伤害到它…这个方法唯一的问题是,如果你通过Ajax提交你的表单,问题是你有两个具有相同名称的元素,并且您必须更巧妙地捕获正确元素的值(reCaptcha元素的两个ID是#recaptcha_response_field
和#recaptcha_challenge_field,以防有人需要它们)
我知道这个问题是古老的,但如果有人会在未来寻找的话。 在一个页面上可以有两个validation码。 粉红到文档在这里: 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>
我有页脚的联系表单,总是显示,也有一些页面,如创build帐户,也可以validation码,所以它是dynamic的,我使用下一个方法与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>
看看页面的源代码,我拿了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选项卡function。 所以,没有包含那个代码。
当用户点击“请求信息” (#product_tabs_what)
JS会检查recapExist
是否为false
或具有一定的价值。 如果它有一个值,那么这将调用Recaptcha.destroy();
摧毁旧的加载reCaptcha并将重新创build此选项卡。 否则,这只会创build一个reCaptcha,并将放入#more_info_recaptcha_box
div。 与“出价” #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>
这个答案是@raphadko的答案的延伸。
如果您需要手动提取validation码(如在Ajax请求中),您必须调用:
grecaptcha.getResponse(widget_id)
但是,你怎么能检索小部件ID参数?
我使用CaptchaCallback的这个定义来存储每个g-recaptcha盒的widget id (作为一个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'));
提取代码。
这是由raphadko和名词提供的答案的JQuery免费版本。
1)正常创build你的recaptcha领域:
<div class="g-recaptcha"></div>
2)用这个加载脚本:
<script src="https://www.google.com/recaptcha/api.js?onload=CaptchaCallback&render=explicit" async defer></script>
3)现在调用这个遍历字段并创buildrecaptchas:
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'}); } };
一个不错的select是为每个表单生成一个recaptchainput(我已经做了两个,但你可能做三个或更多的forms)。 我正在使用jQuery,jQueryvalidation和jQuery表单插件通过AJAX发布表单以及Recaptcha AJAX API –
https://developers.google.com/recaptcha/docs/display#recaptcha_methods
当用户提交一个表单时:
- 拦截提交 – 我用jQuery表单插件的beforeSubmit属性
- 销毁页面上任何现有的recaptchainput – 我使用了jQuery的$ .empty()方法和Recaptcha.destroy()
- 调用Recaptcha.create()为特定的表单创build一个recaptcha字段
- 返回false。
然后,他们可以填写recaptcha并重新提交表格。 如果他们决定提交不同的表单,那么您的代码会检查现有的恢复代码,因此您一次只能在页面上进行一次恢复。
这是一个解决scheme,build立了许多优秀的答案。 这个选项是jQuery免费的,而且是dynamic的,不需要你通过id特别指定元素。
1)像往常一样添加reCAPTCHA标记:
<div class="g-recaptcha" data-sitekey="YOUR_KEY_HERE"></div>
2)将以下内容添加到文档中。 它将在任何支持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>
这是可能的,只是覆盖Recaptcha Ajaxcallback。 工作jsfiddle: http : //jsfiddle.net/Vanit/Qu6kn/
你甚至不需要代理div,因为覆盖DOM代码将不会执行。 只要你想再次触发callback,就调用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");
这里是一个很好的指导,做到这一点:
http://mycodde.blogspot.com.ar/2014/12/multiple-recaptcha-demo-same-page.html
基本上,你添加一些参数的API调用,并手动呈现每个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:“grecaptcha.render”方法收到一个ID
添加一点到raphadko的答案 :因为你有多个validation码(在一个页面上),你不能使用(通用) g-recaptcha-response
POST参数(因为它只包含一个validation码的响应)。 相反,您应该为每个validation码使用grecaptcha.getResponse(opt_widget_id)
调用。 这是我的代码(提供每个validation码都在其表单中):
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) + "\"}" }); }); };
请注意,我将事件委托(请参阅append元素后的刷新DOM )应用于所有dynamic修改的元素。 这将每个captha的响应绑定到表单submit
事件。
我会使用无形的recaptcha。 然后在你的button上使用“formname ='yourformname'”这样的标签来指定要提交哪个表单,并隐藏一个提交表单input。
这样做的好处是它允许你保持html5表单validation完整,一个recaptcha,但多个button接口。 只需捕获由recaptcha生成的令牌密钥的“validation码”input值即可。
<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>
我觉得这个FAR更简单,更容易pipe理。