Is there a recaptcha v2 close event?

I am passing grecaptcha with code like this

let callback;
const p = new Promise((resolve) => callback = (result) => resolve(result));

grecaptcha.render(el, {
    sitekey: window.settings.recaptchaKey,
    size: "invisible",
    type: "image",
    callback: result => callback(result),
    badge: "inline"
});

const key = await p;

      

everything works fine, but if the user clicks on the background of the recaptcha modal, the recaptcha is closed and I cannot detect it, so I wait for an endless response

I need some kind of event or callback to detect when it closes

+3


source to share


2 answers


As a dirty workaround, we can set a timeout and wait for the iframe recaptcha to display and then wait for it to hide

I created a module that does all the manipulation

It depends on jquery and global recaptcha

and i use it like this



try {
    key = await captcha(elementToBind, 'yoursitekey');
}
catch (error) {
    console.log(error); // when recaptcha canceled it will print captcha canceled
}

      

bad part, it can break when google changes something in the html structure

module code

/* global grecaptcha */
import $ from "jquery";

let callback = () => {};
let hideCallback = () => {};

export default function captcha (el, sitekey) {
    const $el = $(el);
    el = $el[0];
    let captchaId = $el.attr("captcha-id");
    let wrapper;
    if (captchaId == null) {
        captchaId = grecaptcha.render(el, {
            sitekey,
            size: "invisible",
            type: "image",
            callback: result => callback(result),
            badge: "inline",
        });
        $(el).attr("captcha-id", captchaId);
    }
    else {
        grecaptcha.reset(captchaId);
    }
    const waitForWrapper = setInterval(() => {
        // first we search for recaptcha iframe
        const iframe = $("iframe").filter((idx, iframe) => iframe.src.includes("recaptcha/api2/bframe"));
        iframe.toArray().some(iframe => {
            const w = $(iframe).closest("body > *");
            // find the corresponding iframe for current captcha
            if (w[0] && !w[0].hasAttribute("captcha-id") || w.attr("captcha-id") == captchaId) {
                w.attr("captcha-id", captchaId);
                wrapper = w; // save iframe wrapper element
                clearInterval(waitForWrapper);
                return true;
            }
        });
    }, 100);
    const result = new Promise((resolve, reject) => {
        callback = (result) => {
            clearInterval(waitForHide);
            resolve(result);
        };
        hideCallback = (result) => {
            clearInterval(waitForHide);
            reject(result);
        };
    });
    grecaptcha.execute(captchaId);
    let shown = false;
    const waitForHide = setInterval(() => {
        if (wrapper) { // if we find iframe wrapper
            if (!shown) {
                // waiting for captcha to show
                if (wrapper.css("visibility") !== "hidden") {
                    shown = true;
                    console.log("shown");
                }
            }
            else {
                // now waiting for it to hide
                if (wrapper.css("visibility") === "hidden") {
                    console.log("hidden");
                    hideCallback(new Error("captcha canceled"));
                }
            }
        }
    }, 100);
    return result;
}

      

+1


source


reCAPTCHA v2 has a handler expired-callback

which might be what you are looking for.



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

-1


source







All Articles