2

I'm trying to migrate from using Google reCaptcha v2 to the invisible reCaptcha. I use Parsley.js for form validation and submit the form using the Malsup Ajax form plugin. my current code looks like this :

HTML:

<form action="send1.php" method="post" class="contact_form">        
<label for="name_1">Name</label>
<input type="text" name="name_1" id="name_1" value="" required />
<div class="g-recaptcha" data-sitekey="XXX"></div>
<input type="submit" class="button" value="">
</form>

JS:

$('.contact_form').parsley();
$('.contact_form').submit(function(){
    if($('.contact_form').parsley().validate()){
        $('.contact_form').ajaxSubmit(); 
    }
    return false;
});  

this successfully passes a g-recaptcha-response to send1.php, where the reCaptcha is validated.

How can i integrate Invisible reCaptcha with this script?

i tried using this:

    <div id='recaptcha' class="g-recaptcha"
          data-sitekey="XXX"
          data-callback="onSubmit"
          data-size="invisible"></div>
 </div>

But I'm not sure how to use the data-callback. If I add

grecaptcha.execute();

Before the ajaxSubmit() then the field g-recaptcha-response is added to the Ajax call, but it's value is blank...

Any help, please?

Shahar Shokrani
  • 7,598
  • 9
  • 48
  • 91
Dog
  • 647
  • 1
  • 9
  • 28

3 Answers3

5

(I Copied my answer from here)

For ParsleyJS you will to do a little workaround:

1.Add hidden input field, with data-parsley-required="true", value = "", like this:

<input id="myField" data-parsley-errors-container="#errorContainer" data-parsley-required="true" value="" type="text" style="display:none;">

2.Add error container (just below or under your g-recaptcha div):

<span id='errorContainer'></span>

3.Add this simple function somewhere in your js code:

function recaptchaCallback() {
    document.getElementById('myField').value = 'nonEmpty';
}

4.Add the attribute data-callback with value of custom function:

<div class="g-recaptcha" data-sitekey="***" data-callback="recaptchaCallback"></div>
Shahar Shokrani
  • 7,598
  • 9
  • 48
  • 91
  • that looks like a great solution to my problem... i will try adding it... thanks... – Dog Sep 03 '17 at 05:54
  • you welcome, its very simple and I'v already tried it, it works! – Shahar Shokrani Sep 03 '17 at 05:56
  • If you think this is correct, then flag it as a duplicate, not copy exactly the same answer again. –  Sep 03 '17 at 06:14
  • It's not duplicate question, only duplicate answer. – Shahar Shokrani Sep 03 '17 at 07:10
  • 1
    this is a follow up to my comment from the accepted answer, and is in addition to it... it prevents the recaptcha popping up again...thanks Shachar... – Dog Sep 04 '17 at 09:24
  • Can you explain a little what happens in your code? Trying to implement it, but I'm confused. Nowhere you call grecaptcha.execute(). – bart Nov 04 '17 at 04:55
  • Can't get it to work, the invisible div just shows upon submit :/ – bart Nov 04 '17 at 05:24
  • Hey @bart, you are right, i do not call grecaptcha.execute(), my answer was for the callback implementation. if you still have no success i will try to edit my answer. – Shahar Shokrani Nov 05 '17 at 05:37
  • @ShaharS Tried to implement it, but can't get it working, see: https://stackoverflow.com/questions/47111965/trying-to-implement-google-invisible-recaptcha-with-parsley-js – bart Nov 07 '17 at 00:43
2

I'll share with you how I got ParsleyJS and Invisible reCaptcha working for me. Below is the code I used. This was POC code only, not production; and I did not do an AJAX post. And please excuse any uglyness, because I had to strip out a lot of fluff:

<!DOCTYPE html>
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
        <script src="../node_modules/parsleyjs/dist/parsley.min.js"></script>
    </head>

    <body>
        <form action="#" data-parsley-validate class="js-validate">
            <div>
                <label for="input-first-name">First Name*</label>
                <input
                    type="text"
                    id="input-first-name"
                    name="first-name"
                    data-parsley-trigger="blur"
                    data-parsley-error-message="First Name is required"
                    required>
            </div>
            <div>

                <label for="input-last-name">Last Name*</label>
                <input
                    type="text"
                    name="last-name"
                    id="input-last-name"
                    data-parsley-trigger="blur"
                    data-parsley-error-message="Last Name is required"
                    required>
            </div>
            <div>   
                <button type="submit" id="theSubmitBtn">Submit</button> 
            </div>      

            <script src="https://www.google.com/recaptcha/api.js?render=explicit&onload=onScriptLoad" async defer></script>
            <script>
                function onScriptLoad() {
                    var htmlEl = document.querySelector('.g-recaptcha');

                    var captchaOptions = {
                        sitekey: 'Your_Site_Key',
                        size: 'invisible',
                        callback: function (token) {
                                $('.js-validate').submit();
                                console.log('test:   ',token);
                            }
                    };

                    recaptchaId = window.grecaptcha.render(htmlEl, captchaOptions, false);

                    $('#theSubmitBtn').click(function(e){
                        e.preventDefault();

                        if(grecaptcha.getResponse() != ''){
                            grecaptcha.reset();
                        }
                        grecaptcha.execute();
                    });
                }
            </script>
            <div id='recaptcha' class="g-recaptcha"></div>

        </form> 
    </body>
</html>

So if you want to do submit via AJAX, you can add a ParsleyJS event listener and do your Ajax call that way.

$('.js-validate').parsley().on('form:submit', function() {
    //AJAX post here    
    return false;
});

I based my solution mostly off this post (so credit to him): Invisible google Recaptcha and ajax form

Hope it helps, because I also looked for solutions for a while.

Community
  • 1
  • 1
  • 1
    great solution, thank you... my only problem is that if required fields aren't filled in correctly then the Recaptcha pops up every time the form is submitted... can you suggest a way so that the Recaptcha is only triggered after the parsley has been successfully validated? – Dog May 24 '17 at 08:12
0

I hope this will help you out, I haven't dealt with parsley, but the way reCaptcha integrates with it should be the same. Let me know if you have any questions!

I use a method like this to render my reCaptchas. This allows you to have multiple captchas on the same page, as well as validation.

For form validation, I've added your parsley validation to the below function. Notice that if the validation returns false, we reset the captcha... this is important. If that doesn't happen, the form cannot be re-submitted.

function renderRecaptcha() {
    for (var i = 0; i < document.forms.length; ++i) {
        var form = document.forms[i];
        var button = form.querySelector('[data-sitekey]');
        if (null === button) {
            continue;
        }

        (function (frm) {
            var sitekey = button.getAttribute("data-sitekey");
            var buttonId = grecaptcha.render(button, {
                "sitekey": sitekey,
                "size": "invisible",
                "badge": "inline",
                "callback": function (recaptchaToken) {
                    if ($(frm).parsley().validate()) {
                        $(frm).ajaxSubmit();
                        // HTMLFormElement.prototype.submit.call(frm);
                    } else {
                        grecaptcha.reset(buttonId);
                    }
                }
            });

            frm.onsubmit = function (evt) {
                evt.preventDefault();
                grecaptcha.execute(buttonId);
            };
        })(form);
    }
}

Your button will be what has the sitekey instead of a div. This simplifies things a lot.

<button type="submit" class="common-form__submit" data-sitekey="SITEKEY_HERE">Send Your Request</button>
Allen
  • 536
  • 7
  • 10
  • thanks for the suggestion, but it doesn't seem to work for me... i replaced my javascript code with yours, and replaced the button... the parsley validation works, but when all fields are correct the form submits but not with ajax... g-recaptcha-response is empty... i see nothing on the page that shows the recaptcha is there... am i supposed to call something to actually render the captcha in the first place? – Dog Apr 06 '17 at 16:27