albertcht / invisible-recaptcha

An invisible reCAPTCHA package for Laravel, Lumen, CI or native PHP.
MIT License
601 stars 162 forks source link

Patch, required due to missing g-recaptcha-response #126

Closed idoenk closed 4 years ago

idoenk commented 4 years ago

This patch is work-around in form using ajax.

Patch applied on: InvisibleReCaptcha.php::renderFooterJS#L131
    public function renderFooterJS($lang = null)
    {
        $html = '<script src="' . $this->getCaptchaJs($lang) . '" async defer></script>' . PHP_EOL;
        $html .= '<script>var _submitForm,_captchaForm,_captchaSubmit,_execute=true;</script>';
        $html .= "<script>window.addEventListener('load', _loadCaptcha);" . PHP_EOL;
        $html .= "function _loadCaptcha(){";
        if ($this->getOption('hideBadge', false)) {
            $html .= "document.querySelector('.grecaptcha-badge').style = 'display:none;!important'" . PHP_EOL;
        }
        $html .= '_captchaForm=document.querySelector("#_g-recaptcha").closest("form");';
        $html .= "_captchaSubmit=_captchaForm.querySelector('[type=submit]');";
        $html .= '_submitForm=function(t){if(typeof _submitEvent==="function"){_submitEvent(t);';
        $html .= 'grecaptcha.reset();}else{_captchaForm.submit();}};';
        $html .= "_captchaForm.addEventListener('submit',";
        $html .= "function(e){e.preventDefault();if(typeof _beforeSubmit==='function'){";
        $html .= "_execute=_beforeSubmit(e);}if(_execute){";
        $html .= "grecaptcha.execute().then(function(token){_submitForm(token)});}});";
        if ($this->getOption('debug', false)) {
            $html .= $this->renderDebug();
        }
        $html .= "}</script>" . PHP_EOL;
        return $html;
    }

Notes: grecaptcha.execute().then(function(token){_submitForm(token)});

By using promise, token value of g-recaptcha-response will be returned after callback then, then execute defined _submitForm above with param t which will be transfered to _submitEvent.

In your page containing form using recaptcha

/**
 * Use this to check mandatory field in form
 * @return mixed
 * false, submission should halted
 * true, continue submission
 */
_beforeSubmit = function(){};

/**
 * Main event submission
 */
_submitEvent = function(token){
  // Flag to avoid Bubble
  if (window['_submitEvent_hited']){
    console.log('Hit, exiting..');
    return !1;
  }
  window['_submitEvent_hited'] = true;

  var postdata = [];
  // Collect post data
  $form.find('[name]').each(function(){
    var $el = $(this),
        name = $el.attr('name')
    ;
    postdata[name] = $el.val();
  });

  if (token)
    postdata['g-recaptcha-response'] = token;

 // Do your xhr here...
 // $.ajax({.....})
 /*
  $.ajax({
    method: "POST",
    url: $form.attr('action'),
    data: postdata,
    dataType: "json",
    cache: !1
  })
  .done(function(data){ 
    console.log('xhr: done');
  })
  .fail(function(r){
    console.log('xhr: fail');
  })
  .always(function(r){
    // Dont forget to reset this state
    window['_submitEvent_hited'] = null;
  });
 */
};