From dbc654ec81263616178d32782adbc45c088d9473 Mon Sep 17 00:00:00 2001 From: eileen Date: Mon, 11 Mar 2019 13:04:57 +1300 Subject: [PATCH] Support calling ContributionPage.validate in POST context. Because the validation data is buried deep within the form we need to load the form in order to validate - but currently the validKey check borks in post requests. Note the validity of credit card details is not checked when submitting this form, other than possibly the luhn validation. A likely use case for the validation is when the is being submitted and some handling is to be done before processing but the validity of input needs to be checked first. For example Paypal Checkout will replace the confirm button with it's own but we are able to validate before paypal launches it's modal. In this case the is post but we need validation to succeed. --- api/v3/ContributionPage.php | 20 +++++++++++++++++++ tests/phpunit/api/v3/ContributionPageTest.php | 16 +++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/api/v3/ContributionPage.php b/api/v3/ContributionPage.php index 393dfa75f3..1a1e822b6e 100644 --- a/api/v3/ContributionPage.php +++ b/api/v3/ContributionPage.php @@ -114,6 +114,13 @@ function civicrm_api3_contribution_page_submit($params) { * API result array */ function civicrm_api3_contribution_page_validate($params) { + // If we are calling this as a result of a POST action (e.g validating a form submission before first getting payment + // authorization from a payment processor like Paypal checkout) the lack of a qfKey will not result in a valid + // one being generated so we generate one first. + $qfKey = CRM_Utils_Array::value('qfKey', $_REQUEST); + if (!$qfKey) { + $_REQUEST['qfKey'] = CRM_Core_Key::get('CRM_Core_Controller', TRUE); + } $form = new CRM_Contribute_Form_Contribution_Main(); $form->controller = new CRM_Core_Controller(); $form->set('id', $params['id']); @@ -125,6 +132,19 @@ function civicrm_api3_contribution_page_validate($params) { return civicrm_api3_create_success($errors, $params, 'ContributionPage', 'validate'); } +/** + * Metadata for validate action. + * + * @param array $params + */ +function _civicrm_api3_contribution_page_validate_spec(&$params) { + $params['id'] = [ + 'title' => ts('Contribution Page ID'), + 'api.required' => TRUE, + 'type' => CRM_Utils_Type::T_INT, + ]; +} + /** * Set default getlist parameters. * diff --git a/tests/phpunit/api/v3/ContributionPageTest.php b/tests/phpunit/api/v3/ContributionPageTest.php index 6232aceb7d..6b96a7f5e6 100644 --- a/tests/phpunit/api/v3/ContributionPageTest.php +++ b/tests/phpunit/api/v3/ContributionPageTest.php @@ -1922,6 +1922,22 @@ class api_v3_ContributionPageTest extends CiviUnitTestCase { $this->assertEmpty($errors); } + /** + * Test validating a contribution page submit in POST context. + * + * A likely use case for the validation is when the is being submitted and some handling is + * to be done before processing but the validity of input needs to be checked first. + * + * For example Paypal Checkout will replace the confirm button with it's own but we are able to validate + * before paypal launches it's modal. In this case the $_REQUEST is post but we need validation to succeed. + */ + public function testValidatePost() { + $_SERVER['REQUEST_METHOD'] = 'POST'; + $this->setUpContributionPage(); + $errors = $this->callAPISuccess('ContributionPage', 'validate', array_merge($this->getBasicSubmitParams(), ['action' => 'submit']))['values']; + $this->assertEmpty($errors); + } + /** * Implements hook_civicrm_alterPaymentProcessorParams(). * -- 2.25.1