From b1709d2dfa2d1134f343d53b1807b9aee9977754 Mon Sep 17 00:00:00 2001
From: Matthew Wire <mjw@mjwconsult.co.uk>
Date: Sat, 27 Jun 2020 11:46:07 +0100
Subject: [PATCH] Fix #210 If there are multiple reCaptcha on the page check
 and validate the one on the Stripe billing form only

---
 docs/releasenotes.md |  4 ++++
 js/civicrm_stripe.js | 48 ++++++++++++++++++++++++++++++++++----------
 2 files changed, 41 insertions(+), 11 deletions(-)

diff --git a/docs/releasenotes.md b/docs/releasenotes.md
index e0fac2db..25943743 100644
--- a/docs/releasenotes.md
+++ b/docs/releasenotes.md
@@ -9,6 +9,10 @@ Where:
 * minor: Breaking change in some circumstances, or a new feature. Read carefully and make sure you understand the impact of the change.
 * incremental: A "safe" change / improvement. Should *always* be safe to upgrade.
 
+## Release 6.4.2 - not yet released
+
+* Fix [#210](https://lab.civicrm.org/extensions/stripe/-/issues/210): If there are multiple reCaptcha on the page check and validate the one on the Stripe billing form only.
+
 ## Release 6.4.1
 **This release REQUIRES that you upgrade mjwshared to 0.8.**
 
diff --git a/js/civicrm_stripe.js b/js/civicrm_stripe.js
index 551da276..cc15f39e 100644
--- a/js/civicrm_stripe.js
+++ b/js/civicrm_stripe.js
@@ -482,16 +482,7 @@ CRM.$(function($) {
         return false;
       }
 
-      if (!(typeof grecaptcha === 'undefined' || (grecaptcha && grecaptcha.getResponse().length !== 0))) {
-        debugging('recaptcha active and not valid');
-        $('div#card-errors').hide();
-        swalFire({
-          icon: 'warning',
-          text: '',
-          title: ts('Please complete the reCaptcha'),
-        }, '.recaptcha-section', true);
-        triggerEvent('crmBillingFormNotValid');
-        form.dataset.submitted = 'false';
+      if (!validateReCaptcha()) {
         return false;
       }
 
@@ -583,6 +574,41 @@ CRM.$(function($) {
     }
   }
 
+  /**
+   * Validate a reCaptcha if it exists on the form.
+   * Ideally we would use grecaptcha.getResponse() but the reCaptcha is already render()ed by CiviCRM
+   *   so we don't have clientID and can't be sure we are checking the reCaptcha that is on our form.
+   *
+   * @returns {boolean}
+   */
+  function validateReCaptcha() {
+    if (typeof grecaptcha === 'undefined') {
+      // No reCaptcha library loaded
+      debugging('reCaptcha library not loaded');
+      return true;
+    }
+    if ($(form).find('[name=g-recaptcha-response]').length === 0) {
+      // no reCaptcha on form - we check this first because there could be reCaptcha on another form on the same page that we don't want to validate
+      debugging('no reCaptcha on form');
+      return true;
+    }
+    if ($(form).find('[name=g-recaptcha-response]').val().length > 0) {
+      // We can't use grecaptcha.getResponse because there might be multiple reCaptchas on the page and we might not be the first one.
+      debugging('recaptcha is valid');
+      return true;
+    }
+    debugging('recaptcha active and not valid');
+    $('div#card-errors').hide();
+    swalFire({
+      icon: 'warning',
+      text: '',
+      title: ts('Please complete the reCaptcha'),
+    }, '.recaptcha-section', true);
+    triggerEvent('crmBillingFormNotValid');
+    form.dataset.submitted = 'false';
+    return false;
+  }
+
   function getIsDrupalWebform() {
     // form class for drupal webform: webform-client-form (drupal 7); webform-submission-form (drupal 8)
     if (form !== null) {
@@ -713,7 +739,7 @@ CRM.$(function($) {
         // If the auto_renew field exists as a hidden field, then we force a
         // recurring contribution (the value isn't useful since it depends on
         // the locale - e.g.  "Please renew my membership")
-        isRecur = true;;
+        isRecur = true;
       }
       else {
         isRecur = Boolean($('input[name="auto_renew"]').checked);
-- 
GitLab