From 6ab2b8e67bc0bf5cb5d8c928e16be17046b223c5 Mon Sep 17 00:00:00 2001 From: Matthew Wire Date: Mon, 10 Aug 2020 11:23:22 +0100 Subject: [PATCH 01/12] Re-work #164 so getTotalAmount works in all cases. --- Metadata/js/omnipay_PaypalRest.js | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/Metadata/js/omnipay_PaypalRest.js b/Metadata/js/omnipay_PaypalRest.js index 53dd9670b..b713ca59e 100644 --- a/Metadata/js/omnipay_PaypalRest.js +++ b/Metadata/js/omnipay_PaypalRest.js @@ -6,11 +6,10 @@ function renderPaypal() { paypal.Buttons({ - onInit: function(data, actions) { // Set up the buttons. if (form.valid()) { - actions.enable() + actions.enable(); } else { actions.disable(); @@ -18,7 +17,7 @@ form.on('blur keyup change', 'input', function (event) { if (form.valid()) { - actions.enable() + actions.enable(); } else { actions.disable(); @@ -28,23 +27,40 @@ createBillingAgreement: function (data, actions) { + // CRM.payment.getTotalAmount is implemented by webform_civicrm and mjwshared. The plan is to + // add CRM.payment.getTotalAmount() into CiviCRM core. This code allows it to work under any of + // these circumstances as well as if CRM.payment does not exist. + var totalAmount = 0.0; + if ((typeof CRM.payment !== 'undefined') && (CRM.payment.hasOwnProperty('getTotalAmount'))) { + totalAmount = CRM.payment.getTotalAmount(); + } + else if (typeof calculateTotalFee == 'function') { + // This is ONLY triggered in the following circumstances on a CiviCRM contribution page: + // - With a priceset that allows a 0 amount to be selected. + // - When we are the ONLY payment processor configured on the page. + totalAmount = parseFloat(calculateTotalFee()); + } + else if (document.getElementById('total_amount')) { + // The input#total_amount field exists on backend contribution forms + totalAmount = parseFloat(document.getElementById('total_amount').value); + } + var frequencyInterval = $('#frequency_interval').val() || 1; var frequencyUnit = $('#frequency_unit').val() ? $('#frequency_interval').val() : CRM.vars.omnipay.frequency_unit; - var paymentAmount = calculateTotalFee(); var isRecur = $('#is_recur').is(":checked"); var recurText = isRecur ? ' recurring' : ''; return new Promise(function (resolve, reject) { CRM.api3('PaymentProcessor', 'preapprove', { 'payment_processor_id': CRM.vars.omnipay.paymentProcessorId, - 'amount': paymentAmount, + 'amount': totalAmount, 'currencyID' : CRM.vars.omnipay.currency, 'qf_key': qfKey, 'is_recur' : isRecur, 'installments' : $('#installments').val(), 'frequency_unit' : frequencyUnit, 'frequency_interval' : frequencyInterval, - 'description' : CRM.vars.omnipay.title + ' ' + CRM.formatMoney(paymentAmount) + recurText, + 'description' : CRM.vars.omnipay.title + ' ' + CRM.formatMoney(totalAmount) + recurText, } ).then(function (result) { if (result['is_error'] === 1) { From d94e0d98508768fa95bc6ace4353583ff10c8a9d Mon Sep 17 00:00:00 2001 From: Matthew Wire Date: Mon, 10 Aug 2020 11:23:47 +0100 Subject: [PATCH 02/12] Load PaypalRest js via URL and cache code --- Metadata/omnipay_PaypalRest.mgd.php | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/Metadata/omnipay_PaypalRest.mgd.php b/Metadata/omnipay_PaypalRest.mgd.php index 4cc26e3bb..33f2dbc05 100644 --- a/Metadata/omnipay_PaypalRest.mgd.php +++ b/Metadata/omnipay_PaypalRest.mgd.php @@ -53,6 +53,9 @@ * database as appropriate. For more details, see "hook_civicrm_managed" at: * http://wiki.civicrm.org/confluence/display/CRMDOC/Hook+Reference */ + +use CRM_Omnipaymultiprocessor_ExtensionUtil as E; + return [ [ 'name' => 'PayPal Checkout', @@ -114,16 +117,8 @@ 'regions' => [ //'billing-block-post' => [], 'billing-block' => [ - [ - 'markup' => '
', - 'name' => 'paypal_button', - 'weight' => 400, - ], - [ - 'name' => 'paypal_script', - 'weight' => 500, - 'script' => file_get_contents(__DIR__ . '/js/omnipay_PaypalRest.js'), - ], + ['markup' => '
', 'name' => 'paypal_button', 'weight' => 400], + ['name' => 'paypal_script', 'weight' => 500, 'scriptUrl' => \Civi::resources()->addCacheCode(E::url('Metadata/js/omnipay_PaypalRest.js'))] ], ], ], From 5e08090b1d328e2080a4e5f9e56a4b6b9c35c604 Mon Sep 17 00:00:00 2001 From: Matthew Wire Date: Thu, 13 Aug 2020 19:09:18 +0100 Subject: [PATCH 03/12] Add fallback to load CRM.vars.omnipay if not loaded via html-header region --- CRM/Core/Payment/OmnipayMultiProcessor.php | 8 ++++++- Metadata/omnipay_PaypalRest.mgd.php | 1 + .../Form/OmnipayResource.tpl | 23 +++++++++++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 templates/CRM/Omnipaymultiprocessor/Form/OmnipayResource.tpl diff --git a/CRM/Core/Payment/OmnipayMultiProcessor.php b/CRM/Core/Payment/OmnipayMultiProcessor.php index 8db2f5710..054eda29a 100644 --- a/CRM/Core/Payment/OmnipayMultiProcessor.php +++ b/CRM/Core/Payment/OmnipayMultiProcessor.php @@ -325,7 +325,13 @@ public function buildForm(&$form) { $jsVariables[$clientSideKey] = $this->_paymentProcessor[$key]; } } - CRM_Core_Resources::singleton()->addVars('omnipay', $jsVariables); + + \Civi::resources()->addVars('omnipay', $jsVariables); + // Assign to smarty so we can add via tpl for drupal webform / default processor on contribution page because addVars doesn't work in that context + // until https://github.com/civicrm/civicrm-core/pull/18141 is merged + // Then we can set 'billing-block' above and remove the assign/tpl + $form->assign('omnipayJSVars', $jsVariables); + if (is_array($regions)) { foreach ($regions as $region => $additions) { foreach ($additions as $addition) { diff --git a/Metadata/omnipay_PaypalRest.mgd.php b/Metadata/omnipay_PaypalRest.mgd.php index 33f2dbc05..a9b5ea933 100644 --- a/Metadata/omnipay_PaypalRest.mgd.php +++ b/Metadata/omnipay_PaypalRest.mgd.php @@ -118,6 +118,7 @@ //'billing-block-post' => [], 'billing-block' => [ ['markup' => '
', 'name' => 'paypal_button', 'weight' => 400], + ['template' => E::path('templates/CRM/Omnipaymultiprocessor/Form/OmnipayResource.tpl'), 'region' => 'billing-block', 'weight' => -1], ['name' => 'paypal_script', 'weight' => 500, 'scriptUrl' => \Civi::resources()->addCacheCode(E::url('Metadata/js/omnipay_PaypalRest.js'))] ], ], diff --git a/templates/CRM/Omnipaymultiprocessor/Form/OmnipayResource.tpl b/templates/CRM/Omnipaymultiprocessor/Form/OmnipayResource.tpl new file mode 100644 index 000000000..bb2489db8 --- /dev/null +++ b/templates/CRM/Omnipaymultiprocessor/Form/OmnipayResource.tpl @@ -0,0 +1,23 @@ +{* + +--------------------------------------------------------------------+ + | Copyright CiviCRM LLC. All rights reserved. | + | | + | This work is published under the GNU AGPLv3 license with some | + | permitted exceptions and without any warranty. For full license | + | and copyright information, see https://civicrm.org/licensing | + +--------------------------------------------------------------------+ +*} +{* Manually create the CRM.vars.omnipay here for cases where \Civi::resources()->addVars() does not work (eg. drupal webform_civicrm, contribution page paypal checkout is default *} +{literal} + +{/literal} From 65f903e88e9e6dbf2014c1ceb47f51fb2d77eee4 Mon Sep 17 00:00:00 2001 From: Matthew Wire Date: Thu, 13 Aug 2020 19:10:02 +0100 Subject: [PATCH 04/12] Log message if CRM.vars.omnipay are not defined instead of trying to load checkout --- Metadata/js/omnipay_PaypalRest.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Metadata/js/omnipay_PaypalRest.js b/Metadata/js/omnipay_PaypalRest.js index b713ca59e..f6534eab5 100644 --- a/Metadata/js/omnipay_PaypalRest.js +++ b/Metadata/js/omnipay_PaypalRest.js @@ -3,6 +3,11 @@ var form = $('#billing-payment-block').closest('form'); var qfKey = $('[name=qfKey]', form).val(); + if (typeof CRM.vars.omnipay === 'undefined') { + console.log('CRM.vars.omnipay not defined! Not a Omnipay processor?'); + return; + } + function renderPaypal() { paypal.Buttons({ From ff545a821cb5d3a814d965aa540ff5d4da7edf04 Mon Sep 17 00:00:00 2001 From: Matthew Wire Date: Wed, 23 Sep 2020 19:08:06 +0100 Subject: [PATCH 05/12] Don't crash if crm-submit-buttons element does not exist (eg. on webform_civicrm) --- Metadata/js/omnipay_PaypalRest.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Metadata/js/omnipay_PaypalRest.js b/Metadata/js/omnipay_PaypalRest.js index f6534eab5..4320275ed 100644 --- a/Metadata/js/omnipay_PaypalRest.js +++ b/Metadata/js/omnipay_PaypalRest.js @@ -91,7 +91,10 @@ } document.getElementById('paypal-button-container').style.visibility = "hidden"; - document.getElementById('crm-submit-buttons').style.display = 'block'; + var crmSubmitButtons = document.getElementById('crm-submit-buttons'); + if (crmSubmitButtons) { + crmSubmitButtons.style.display = 'block'; + } document.getElementById('PayerID').value = data['payerID']; document.getElementById('payment_token').value = paymentToken; form.submit(); From af22c8a02d0aab9519b41713e8479d467e1be683 Mon Sep 17 00:00:00 2001 From: Matthew Wire Date: Fri, 14 Oct 2022 16:47:12 +0100 Subject: [PATCH 06/12] Multiple fixes to PaypalRest JS - requires CRM.payment library from mjwshared --- CRM/Omnipaymultiprocessor/Check.php | 124 ++++++++++++++++++++++++++++ Metadata/js/omnipay_PaypalRest.js | 47 +++++++++-- omnipaymultiprocessor.php | 15 +++- 3 files changed, 175 insertions(+), 11 deletions(-) create mode 100644 CRM/Omnipaymultiprocessor/Check.php diff --git a/CRM/Omnipaymultiprocessor/Check.php b/CRM/Omnipaymultiprocessor/Check.php new file mode 100644 index 000000000..0957703f1 --- /dev/null +++ b/CRM/Omnipaymultiprocessor/Check.php @@ -0,0 +1,124 @@ +messages = $messages; + } + + public function checkRequirements() { + $this->checkExtensionMjwshared(); + return $this->messages; + } + + /** + * @param string $extensionName + * @param string $minVersion + * @param string $actualVersion + */ + private function requireExtensionMinVersion($extensionName, $minVersion, $actualVersion) { + $actualVersionModified = $actualVersion; + if (substr($actualVersion, -4) === '-dev') { + $message = new CRM_Utils_Check_Message( + __FUNCTION__ . $extensionName . E::SHORT_NAME . '_requirements_dev', + E::ts('You are using a development version of %1 extension.', + [1 => $extensionName]), + E::ts('%1: Development version', [1 => $extensionName]), + \Psr\Log\LogLevel::WARNING, + 'fa-code' + ); + $this->messages[] = $message; + $actualVersionModified = substr($actualVersion, 0, -4); + } + + if (version_compare($actualVersionModified, $minVersion) === -1) { + $message = new CRM_Utils_Check_Message( + __FUNCTION__ . $extensionName . E::SHORT_NAME . '_requirements', + E::ts('The %1 extension requires the %2 extension version %3 or greater but your system has version %4.', + [ + 1 => ucfirst(E::SHORT_NAME), + 2 => $extensionName, + 3 => $minVersion, + 4 => $actualVersion + ]), + E::ts('%1: Missing Requirements', [1 => ucfirst(E::SHORT_NAME)]), + \Psr\Log\LogLevel::ERROR, + 'fa-exclamation-triangle' + ); + $message->addAction( + E::ts('Upgrade now'), + NULL, + 'href', + ['path' => 'civicrm/admin/extensions', 'query' => ['action' => 'update', 'id' => $extensionName, 'key' => $extensionName]] + ); + $this->messages[] = $message; + } + } + + /** + * @throws \CiviCRM_API3_Exception + */ + private function checkExtensionMjwshared() { + // mjwshared: required. Requires min version + $extensionName = 'mjwshared'; + $extensions = civicrm_api3('Extension', 'get', [ + 'full_name' => $extensionName, + ]); + + if (empty($extensions['count']) || ($extensions['values'][$extensions['id']]['status'] !== 'installed')) { + $message = new CRM_Utils_Check_Message( + __FUNCTION__ . E::SHORT_NAME . '_requirements', + E::ts('The %1 extension requires the Payment Shared extension which is not installed. See details for more information.', + [ + 1 => ucfirst(E::SHORT_NAME), + 2 => 'https://civicrm.org/extensions/mjwshared', + ] + ), + E::ts('%1: Missing Requirements', [1 => ucfirst(E::SHORT_NAME)]), + \Psr\Log\LogLevel::ERROR, + 'fa-money' + ); + $message->addAction( + E::ts('Install now'), + NULL, + 'href', + ['path' => 'civicrm/admin/extensions', 'query' => ['action' => 'update', 'id' => $extensionName, 'key' => $extensionName]] + ); + $this->messages[] = $message; + return; + } + if (isset($extensions['id']) && $extensions['values'][$extensions['id']]['status'] === 'installed') { + $this->requireExtensionMinVersion($extensionName, self::MIN_VERSION_MJWSHARED, $extensions['values'][$extensions['id']]['version']); + } + } + +} diff --git a/Metadata/js/omnipay_PaypalRest.js b/Metadata/js/omnipay_PaypalRest.js index 4320275ed..0fe4dd3e3 100644 --- a/Metadata/js/omnipay_PaypalRest.js +++ b/Metadata/js/omnipay_PaypalRest.js @@ -1,10 +1,9 @@ // @see https://developer.paypal.com/docs/checkout/integrate/ (function($) { - var form = $('#billing-payment-block').closest('form'); - var qfKey = $('[name=qfKey]', form).val(); + var scriptName = 'omnipayPaypal'; if (typeof CRM.vars.omnipay === 'undefined') { - console.log('CRM.vars.omnipay not defined! Not a Omnipay processor?'); + CRM.payment.debugging(scriptName, 'CRM.vars.omnipay not defined! Not a Omnipay processor?'); return; } @@ -12,16 +11,46 @@ paypal.Buttons({ onInit: function(data, actions) { + + $('[type="submit"][formnovalidate="1"]', + '[type="submit"][formnovalidate="formnovalidate"]', + '[type="submit"].cancel', + '[type="submit"].webform-previous' + ).on('click', function() { + CRM.payment.debugging(scriptName, 'adding submitdontprocess: ' + this.id); + CRM.payment.form.dataset.submitdontprocess = 'true'; + }); + + $(CRM.payment.getBillingSubmit()).on('click', function() { + CRM.payment.debugging(scriptName, 'clearing submitdontprocess'); + CRM.payment.form.dataset.submitdontprocess = 'false'; + }); + + $(CRM.payment.form).on('submit', function(event) { + if (CRM.payment.form.dataset.submitdontprocess === 'true') { + CRM.payment.debugging(scriptName, 'non-payment submit detected - not submitting payment'); + event.preventDefault(); + return true; + } + if (document.getElementById('payment_token') && (document.getElementById('payment_token').value !== 'Authorisation token') && + document.getElementById('PayerID') && (document.getElementById('PayerID').value !== 'Payer ID')) { + return true; + } + CRM.payment.debugging(scriptName, 'Unable to submit - paypal not executed'); + event.preventDefault(); + return true; + }); + // Set up the buttons. - if (form.valid()) { + if ($(CRM.payment.form).valid()) { actions.enable(); } else { actions.disable(); } - form.on('blur keyup change', 'input', function (event) { - if (form.valid()) { + $(CRM.payment.form).on('blur keyup change', 'input', function (event) { + if ($(CRM.payment.form).valid()) { actions.enable(); } else { @@ -54,6 +83,7 @@ var frequencyUnit = $('#frequency_unit').val() ? $('#frequency_interval').val() : CRM.vars.omnipay.frequency_unit; var isRecur = $('#is_recur').is(":checked"); var recurText = isRecur ? ' recurring' : ''; + var qfKey = $('[name=qfKey]', $(CRM.payment.form)).val(); return new Promise(function (resolve, reject) { CRM.api3('PaymentProcessor', 'preapprove', { @@ -97,11 +127,12 @@ } document.getElementById('PayerID').value = data['payerID']; document.getElementById('payment_token').value = paymentToken; - form.submit(); + + // CRM.$(CRM.payment.getBillingSubmit()).click(); }, onError: function(err) { - console.log(err); + CRM.payment.debugging(scriptName, err); alert('Site is not correctly configured to process payments'); } diff --git a/omnipaymultiprocessor.php b/omnipaymultiprocessor.php index 55af69157..974a87e68 100644 --- a/omnipaymultiprocessor.php +++ b/omnipaymultiprocessor.php @@ -104,7 +104,7 @@ function omnipaymultiprocessor_civicrm_preProcess($formName, &$form) { $form->assign('isJsValidate', TRUE); if (!empty($form->_values['is_recur'])) { $recurOptions = [ - 'is_recur_interval' => $form->_values['is_recur_interval'], + 'is_recur_interval' => $form->_values['is_recur_interval'], 'frequency_unit' => $form->_values['recur_frequency_unit'], 'is_recur_installments' => $form->_values['is_recur_installments'], ]; @@ -112,10 +112,19 @@ function omnipaymultiprocessor_civicrm_preProcess($formName, &$form) { if (!$recurOptions['is_recur_interval']) { $recurOptions['frequency_interval'] = 1; } - CRM_Core_Resources::singleton()->addVars( + CRM_Core_Resources::singleton()->addVars( 'omnipay', $recurOptions - ); + ); } } +} +/** + * Implements hook_civicrm_check(). + * + * @throws \CiviCRM_API3_Exception + */ +function omnipaymultiprocessor_civicrm_check(&$messages) { + $checks = new CRM_Omnipaymultiprocessor_Check($messages); + $messages = $checks->checkRequirements(); } From 8c46db6e03938dead753a7ed782b88572649d120 Mon Sep 17 00:00:00 2001 From: Matthew Wire Date: Thu, 24 Sep 2020 17:08:37 +0100 Subject: [PATCH 07/12] Automatically submit form once paypal completes --- Metadata/js/omnipay_PaypalRest.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Metadata/js/omnipay_PaypalRest.js b/Metadata/js/omnipay_PaypalRest.js index 0fe4dd3e3..1030f1e84 100644 --- a/Metadata/js/omnipay_PaypalRest.js +++ b/Metadata/js/omnipay_PaypalRest.js @@ -128,7 +128,7 @@ document.getElementById('PayerID').value = data['payerID']; document.getElementById('payment_token').value = paymentToken; - // CRM.$(CRM.payment.getBillingSubmit()).click(); + CRM.$(CRM.payment.getBillingSubmit()).click(); }, onError: function(err) { From 43d690329e942b83e088e7f1ed9093009a79f0e9 Mon Sep 17 00:00:00 2001 From: Matthew Wire Date: Thu, 24 Sep 2020 17:09:05 +0100 Subject: [PATCH 08/12] Change paypal billing mode to 1 as required by webform_civicrm --- Metadata/omnipay_PaypalRest.mgd.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Metadata/omnipay_PaypalRest.mgd.php b/Metadata/omnipay_PaypalRest.mgd.php index a9b5ea933..4dd386790 100644 --- a/Metadata/omnipay_PaypalRest.mgd.php +++ b/Metadata/omnipay_PaypalRest.mgd.php @@ -74,7 +74,7 @@ 'url_site_test_default' => 'http://unused.com', 'url_recur_test_default' => 'http://unused.com', 'url_api_test_default' => 'http://unused.com', - 'billing_mode' => 4, + 'billing_mode' => 1, 'payment_type' => 1, 'is_recur' => 1, ], From 09309fa3adba51a446f2f5dd574b8fd72e211ba9 Mon Sep 17 00:00:00 2001 From: Matthew Wire Date: Thu, 24 Sep 2020 21:38:51 +0100 Subject: [PATCH 09/12] Set paymentToken when not on a contributionpage --- CRM/Core/Payment/OmnipayMultiProcessor.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CRM/Core/Payment/OmnipayMultiProcessor.php b/CRM/Core/Payment/OmnipayMultiProcessor.php index 054eda29a..0afa3a19a 100644 --- a/CRM/Core/Payment/OmnipayMultiProcessor.php +++ b/CRM/Core/Payment/OmnipayMultiProcessor.php @@ -162,6 +162,12 @@ public function doPayment(&$params, $component = 'contribute') { $this->initialize($params); $this->saveBillingAddressIfRequired($params); + // "token" only gets set when coming in via a contribution page. + // Otherwise we need to set it from the actual parameter that's set on the form + if (!empty($params['paymentToken']) && empty($params['token'])) { + $params['token'] = $params['paymentToken']; + } + try { if (!empty($params['token'])) { $response = $this->doTokenPayment($params); From d08326cb88994cccf9e942168632d55b6d19004d Mon Sep 17 00:00:00 2001 From: Matthew Wire Date: Thu, 24 Sep 2020 21:40:52 +0100 Subject: [PATCH 10/12] Minor tweaks to js formatting --- Metadata/js/omnipay_PaypalRest.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Metadata/js/omnipay_PaypalRest.js b/Metadata/js/omnipay_PaypalRest.js index 1030f1e84..1f0095627 100644 --- a/Metadata/js/omnipay_PaypalRest.js +++ b/Metadata/js/omnipay_PaypalRest.js @@ -114,9 +114,9 @@ onApprove: function (data, actions) { var isRecur = 1; - var paymentToken = data['billingToken']; + var paymentToken = data.billingToken; if (!paymentToken) { - paymentToken = data['paymentID']; + paymentToken = data.paymentID; isRecur = 0; } @@ -125,7 +125,7 @@ if (crmSubmitButtons) { crmSubmitButtons.style.display = 'block'; } - document.getElementById('PayerID').value = data['payerID']; + document.getElementById('PayerID').value = data.payerID; document.getElementById('payment_token').value = paymentToken; CRM.$(CRM.payment.getBillingSubmit()).click(); From 9d5c28226a3964cda9d9a026b23f10163d23faf9 Mon Sep 17 00:00:00 2001 From: Matthew Wire Date: Thu, 24 Sep 2020 21:41:02 +0100 Subject: [PATCH 11/12] Don't add any billing fields --- Metadata/omnipay_PaypalRest.mgd.php | 1 + 1 file changed, 1 insertion(+) diff --git a/Metadata/omnipay_PaypalRest.mgd.php b/Metadata/omnipay_PaypalRest.mgd.php index 4dd386790..c32977c40 100644 --- a/Metadata/omnipay_PaypalRest.mgd.php +++ b/Metadata/omnipay_PaypalRest.mgd.php @@ -81,6 +81,7 @@ 'metadata' => [ 'suppress_submit_button' => 1, 'supports_preapproval' => 1, + 'fields' => ['billing_fields' => []], 'payment_fields' => ['payment_token', 'PayerID', 'post_authorize'], 'pass_through_fields' => [ 'referrerCode' => 'CiviCRM_SP', From d488480fafd4621329e846834497bbf77054bd83 Mon Sep 17 00:00:00 2001 From: Matthew Wire Date: Fri, 25 Sep 2020 10:58:31 +0100 Subject: [PATCH 12/12] Hide the submit button on webform as it's triggered automatically --- Metadata/js/omnipay_PaypalRest.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Metadata/js/omnipay_PaypalRest.js b/Metadata/js/omnipay_PaypalRest.js index 1f0095627..7c1a93e7e 100644 --- a/Metadata/js/omnipay_PaypalRest.js +++ b/Metadata/js/omnipay_PaypalRest.js @@ -12,6 +12,11 @@ onInit: function(data, actions) { + // On webform, hide the submit button as it's triggered automatically + if (CRM.$('[type="submit"].webform-submit').length !== 0) { + $('[type="submit"].webform-submit').hide(); + } + $('[type="submit"][formnovalidate="1"]', '[type="submit"][formnovalidate="formnovalidate"]', '[type="submit"].cancel',