Couldn't find grecaptcha with $.getScript in v2.0

1,640 views
Skip to first unread message

TY C

unread,
Feb 14, 2015, 5:17:57 AM2/14/15
to reca...@googlegroups.com
In v1.0, it's possible to retrieve the source js code from http://www.google.com/recaptcha/api/js/recaptcha_ajax.js with $.getScript, and all the functions inside are avaible to be called. But in v2.0, there seems to be no way to do something similar. For example, I've tried $.getScript('https://www.google.com/recaptcha/api.js'), but I couldn't load functions like grecaptcha.getResponse(). If I tried to render the widget explicitly with $.getScript('https://www.google.com/recaptcha/api.js$onload=onloadCallback&render=explicit'), neither this line would fire the function onloadCallback().

Was there anything wrong when I do this? Or I have to load the source code using <script src> rather than $.getScript()?

Thanks.

TY C

unread,
Feb 14, 2015, 6:25:14 AM2/14/15
to reca...@googlegroups.com
An update:

So I tried
$.getScript('https://www.google.com/recaptcha/api.js', function(){
try
{
 grecaptcha.getResponse();
}
catch(e)
{
 console.log(e)
}});

and I found that the error message throw back was 'Invalid ReCaptcha client id'. Does it have something to do with my Site Key? Because I'm sure that I used the correct key...

TY C於 2015年2月14日星期六 UTC+8下午6時17分57秒寫道:

TY C

unread,
Feb 14, 2015, 7:46:45 AM2/14/15
to reca...@googlegroups.com
Alright, I finally managed to solve the problem.

The thing is that when you call $.getScript('https://www.google.com/recaptcha/api.js'), it's not only loading api.js per se; it only detects the language of your browser/environment, and then it will load another language-specific core api script. So, the problem is that although $.getScript('https://www.google.com/recaptcha/api.js') is asynchronous, the core api script has not been fully loaded when api.js is done, and the grecaptcha functions in the core api script cannot be called right after $.getScript('https://www.google.com/recaptcha/api.js'). Since I'm building a Meteor project, I solve the problem by putting $.getScript('https://www.google.com/recaptcha/api.js') in a Meteor.startup(function() {}), such as:

Metoer.startup(function() {
    $.getScript('https://www.google.com/recaptcha/api.js');
    //Everything else you want to do when the project starts
})

Therefore, the core api script should have enough time to be fully load before other scripts call grecaptha functions. Of course, this is yet the real solution, because I haven't found a way to implement $.getScript on the core api script yet, which will hold the program until the core api script is fully loaded as well. I'll keep working on it.

TY C於 2015年2月14日星期六 UTC+8下午6時17分57秒寫道:

Jay P

unread,
Mar 22, 2015, 12:48:52 AM3/22/15
to reca...@googlegroups.com
I'm having this same problem. In the callback in $.getScript, grecaptcha is not defined.

Although your solution may work, it's not guaranteed to work by just hoping enough time has passed. I also tried your solution but it didn't work for me.

Did you end up finding a better solution? I'm wondering if there's a way to "waitOn" the ACTUAL script attainment and not just the language script...

Jay P

unread,
Mar 22, 2015, 1:28:57 AM3/22/15
to reca...@googlegroups.com
Well, I figured out a simple hack to make it work. It's not good practice at all, because I think I end up loading the script twice. 

$.getScript("https://www.google.com/recaptcha/api.js", function(){
//we do not have grecaptcha
//now we have grecaptcha
})
})

Like you said, the first script is necessary because it is not only a reference to the actual bulk of the code. I think it contains some initialization functions which make the variables available. But since we don't have access to the time when functions like grecaptcha become available, we can explicitly load the final script within the callback of loading the first script. This way, we can pin point the moment when grecaptcha becomes available.

Let me know fi theres a cleaner solution, this ones very dirty.

Jay P

unread,
Mar 22, 2015, 2:07:07 AM3/22/15
to reca...@googlegroups.com
Does anyone know if $.getScript or something similar has an option for "following redirects" I know that the lower level Http.get (or equivalents) have functionality to follow redirected URLs. TY C, perhaps we can try to implement a function like $.getScript for the Meteor client side which follows redirects. For this use case, I think we'd just have to get the initial source code, and then get the source code of the redirected url and then load them both at once. 

Would it work also to manually create a file in our code which is script1+script2 and then put that entire thing in our Meteor.startup? I dont see why not. But then the code would be static and we would not get updates from google. Then our code would break if google makes drastic changes to their API.

We should try all of these things.

Recaptcha Captcha

unread,
Mar 22, 2015, 3:36:04 AM3/22/15
to reCAPTCHA
Hi Jay,

Please take a look at the onload callback documented on https://developers.google.com/recaptcha/docs/display#config. That's exactly what you need.

Thanks,
reCAPTCHA support

--
You received this message because you are subscribed to the Google Groups "reCAPTCHA" group.
To unsubscribe from this group and stop receiving emails from it, send an email to recaptcha+...@googlegroups.com.
To post to this group, send email to reca...@googlegroups.com.
Visit this group at http://groups.google.com/group/recaptcha.
For more options, visit https://groups.google.com/d/optout.



--
reCAPTCHA: stop spam, read books
http://www.google.com/recaptcha

Jay P

unread,
Mar 22, 2015, 4:03:24 AM3/22/15
to reca...@googlegroups.com

I've tried the default onload which does work but it only lets you have one captcha per page.

Also I don't think this plays well with high level meteor code. Meteor is a bit quirky and I've seen inconsistency in the captcha rendering depending on how I accessed the page.

By calling router.go,
By refreshing the browser,
By a hot code reload,
By clicking an anchor tag.

The only consistent way I've come across is by running the nested $.getScript on startup and setting a session variable in the innermost callback, and then having my outermost wrapper layout template render the desired child template IFF the session variable has been set, else render a loading template which says "waiting on Google's killer-robot protection".

The problem with this solution is that my entire app ends up waiting on Google's script to load.

I'm considering increasing the wait scope to the captcha level and not the layout level so that users can still see my app sans-captcha for a few seconds.

Else, I could manually send the script from my own server as part of my app, and then run a cron job on my server every 5 days to update what I send down to the clients. This might be the best thing to do.

Else, I could simply redesign my app to make sure that only one captcha per page is necessary and then use the solution you proposed.

Please let me know if there's a way to include more than one captcha per page using the implicit onload render type.

Thanks.

You received this message because you are subscribed to a topic in the Google Groups "reCAPTCHA" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/recaptcha/gkrnRkbSTmA/unsubscribe.
To unsubscribe from this group and all its topics, send an email to recaptcha+...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages