From ec022878580e581215e845f418797dddf416a325 Mon Sep 17 00:00:00 2001 From: eileenmcnaugton Date: Thu, 27 Aug 2015 00:22:22 +1200 Subject: [PATCH] CRM-16808 paypal express follow up fixes --- CRM/Contribute/Form/Contribution/Main.php | 27 +---- CRM/Core/Form.php | 33 +++++++ CRM/Core/Payment.php | 26 ++++- CRM/Core/Payment/PayPalImpl.php | 13 ++- CRM/Event/Form/Registration/Confirm.php | 4 + CRM/Event/Form/Registration/Register.php | 114 ++++++++++------------ 6 files changed, 127 insertions(+), 90 deletions(-) diff --git a/CRM/Contribute/Form/Contribution/Main.php b/CRM/Contribute/Form/Contribution/Main.php index eeb94c6fcf..0832bd9aa4 100644 --- a/CRM/Contribute/Form/Contribution/Main.php +++ b/CRM/Contribute/Form/Contribution/Main.php @@ -1294,7 +1294,7 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu $this->set('invoiceID', $invoiceID); $params['invoiceID'] = $invoiceID; $params['description'] = ts('Online Contribution') . ': ' . (($this->_pcpInfo['title']) ? $this->_pcpInfo['title'] : $this->_values['title']); - + $params['button'] = $this->controller->getButtonName(); // required only if is_monetary and valid positive amount if ($this->_values['is_monetary'] && is_array($this->_paymentProcessor) && @@ -1346,31 +1346,6 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu } - /** - * Handle pre approval for processors. - * - * This fits with the flow where a pre-approval is done and then confirmed in the next stage when confirm is hit. - * - * This applies to processors that - * @param array $params - */ - protected function handlePreApproval(&$params) { - try { - $payment = Civi\Payment\System::singleton()->getByProcessor($this->_paymentProcessor); - $params['component'] = 'contribute'; - $result = $payment->doPreApproval($params); - } - catch (\Civi\Payment\Exception\PaymentProcessorException $e) { - CRM_Core_Error::displaySessionError($e->getMessage()); - CRM_Utils_System::redirect($params['cancelURL']); - } - - $this->set('pre_approval_parameters', $result['pre_approval_parameters']); - if (!empty($result['redirect_url'])) { - CRM_Utils_System::redirect($result['redirect_url']); - } - } - /** * Process confirm function and pass browser to the thank you page. */ diff --git a/CRM/Core/Form.php b/CRM/Core/Form.php index 932c1d8184..f39bdf09c6 100644 --- a/CRM/Core/Form.php +++ b/CRM/Core/Form.php @@ -740,6 +740,39 @@ class CRM_Core_Form extends HTML_QuickForm_Page { $this->assign('paymentProcessorID', $this->_paymentProcessorID); } + /** + * Handle pre approval for processors. + * + * This fits with the flow where a pre-approval is done and then confirmed in the next stage when confirm is hit. + * + * This function is shared between contribution & event forms & this is their common class. + * + * However, this should be seen as an in-progress refactor, the end goal being to also align the + * backoffice forms that action payments. + * + * @param array $params + */ + protected function handlePreApproval(&$params) { + try { + $payment = Civi\Payment\System::singleton()->getByProcessor($this->_paymentProcessor); + $params['component'] = 'contribute'; + $result = $payment->doPreApproval($params); + if (empty($result)) { + // This could happen, for example, when paypal looks at the button value & decides it is not paypal express. + return; + } + } + catch (\Civi\Payment\Exception\PaymentProcessorException $e) { + CRM_Core_Error::displaySessionError($e->getMessage()); + CRM_Utils_System::redirect($params['cancelURL']); + } + + $this->set('pre_approval_parameters', $result['pre_approval_parameters']); + if (!empty($result['redirect_url'])) { + CRM_Utils_System::redirect($result['redirect_url']); + } + } + /** * Setter function for options. * diff --git a/CRM/Core/Payment.php b/CRM/Core/Payment.php index 39f5aa34a2..8dde6f3fe3 100644 --- a/CRM/Core/Payment.php +++ b/CRM/Core/Payment.php @@ -82,6 +82,25 @@ abstract class CRM_Core_Payment { protected $_paymentProcessor; + /** + * Base url of the calling form. + * + * This is used for processors that need to return the browser back to the CiviCRM site. + * + * @var string + */ + protected $baseReturnUrl; + + /** + * Set Base return URL. + * + * @param string $url + * Url of site to return browser to. + */ + public function setBaseReturnUrl($url) { + $this->baseReturnUrl = $url; + } + /** * Opportunity for the payment processor to override the entire form build. * @@ -539,9 +558,14 @@ abstract class CRM_Core_Payment { /** * Get base url dependent on component. * - * @return string|void + * (or preferably set it using the setter function). + * + * @return string */ protected function getBaseReturnUrl() { + if ($this->baseReturnUrl) { + return $this->baseReturnUrl; + } if ($this->_component == 'event') { $baseURL = 'civicrm/event/register'; } diff --git a/CRM/Core/Payment/PayPalImpl.php b/CRM/Core/Payment/PayPalImpl.php index a811b09675..e513bace19 100644 --- a/CRM/Core/Payment/PayPalImpl.php +++ b/CRM/Core/Payment/PayPalImpl.php @@ -25,6 +25,8 @@ +--------------------------------------------------------------------+ */ +use Civi\Payment\Exception\PaymentProcessorException; + /** * * @package CRM @@ -88,7 +90,7 @@ class CRM_Core_Payment_PayPalImpl extends CRM_Core_Payment { * @return bool */ protected function supportsPreApproval() { - if ($this->_processorName == ts('PayPal Express')) { + if ($this->_processorName == ts('PayPal Express') || $this->_processorName == ts('PayPal Pro')) { return TRUE; } return FALSE; @@ -226,7 +228,7 @@ class CRM_Core_Payment_PayPalImpl extends CRM_Core_Payment { * @return array */ public function getPreApprovalDetails($storedDetails) { - return $this->getExpressCheckoutDetails($storedDetails['token']); + return empty($storedDetails['token']) ? array() : $this->getExpressCheckoutDetails($storedDetails['token']); } /** @@ -427,7 +429,9 @@ class CRM_Core_Payment_PayPalImpl extends CRM_Core_Payment { * @throws \Civi\Payment\Exception\PaymentProcessorException */ public function doPayment(&$params, $component = 'contribute') { - if ($this->_paymentProcessor['payment_processor_type'] != 'PayPal_Express') { + if ($this->_paymentProcessor['payment_processor_type'] != 'PayPal_Express' + && (!empty($params['credit_card_number']) && empty($params['token'])) + ) { return parent::doPayment($params, $component); } $this->_component = $component; @@ -741,6 +745,9 @@ class CRM_Core_Payment_PayPalImpl extends CRM_Core_Payment { * - redirect_url (if set the browser will be redirected to this. */ public function doPreApproval(&$params) { + if (!isset($params['button']) || !stristr($params['button'], 'express')) { + return array(); + } $this->_component = $params['component']; $token = $this->setExpressCheckOut($params); return array( diff --git a/CRM/Event/Form/Registration/Confirm.php b/CRM/Event/Form/Registration/Confirm.php index eaf024563d..bcafb74ea1 100644 --- a/CRM/Event/Form/Registration/Confirm.php +++ b/CRM/Event/Form/Registration/Confirm.php @@ -582,6 +582,10 @@ class CRM_Event_Form_Registration_Confirm extends CRM_Event_Form_Registration { if (is_array($this->_paymentProcessor)) { $payment = $this->_paymentProcessor['object']; } + if (!empty($this->_paymentProcessor) && $this->_paymentProcessor['object']->supports('preApproval')) { + $preApprovalParams = $this->_paymentProcessor['object']->getPreApprovalDetails($this->get('pre_approval_parameters')); + $value = array_merge($value, $preApprovalParams); + } $result = NULL; if (!empty($value['is_pay_later']) || diff --git a/CRM/Event/Form/Registration/Register.php b/CRM/Event/Form/Registration/Register.php index 7362870b6f..00367dada8 100644 --- a/CRM/Event/Form/Registration/Register.php +++ b/CRM/Event/Form/Registration/Register.php @@ -912,7 +912,11 @@ class CRM_Event_Form_Registration_Register extends CRM_Event_Form_Registration { } /** - * Check if profiles are complete when event registration occurs(CRM-9587) + * Check if profiles are complete when event registration occurs(CRM-9587). + * + * @param array $fields + * @param array $errors + * @param int $eventId */ public static function checkProfileComplete($fields, &$errors, $eventId) { $email = ''; @@ -1066,6 +1070,7 @@ class CRM_Event_Form_Registration_Register extends CRM_Event_Form_Registration { if (is_array($this->_paymentProcessor)) { $payment = $this->_paymentProcessor['object']; + $payment->setBaseReturnUrl('civicrm/event/register'); } // default mode is direct $this->set('contributeMode', 'direct'); @@ -1091,6 +1096,8 @@ class CRM_Event_Form_Registration_Register extends CRM_Event_Form_Registration { $params['invoiceID'] = $invoiceID; } $this->_params = $this->get('params'); + // Set the button so we know what + $params['button'] = $this->controller->getButtonName(); if (!empty($this->_params) && is_array($this->_params)) { $this->_params[0] = $params; } @@ -1099,77 +1106,66 @@ class CRM_Event_Form_Registration_Register extends CRM_Event_Form_Registration { $this->_params[] = $params; } $this->set('params', $this->_params); - if ($this->_paymentProcessor && - $this->_paymentProcessor['billing_mode'] & CRM_Core_Payment::BILLING_MODE_BUTTON + $this->_paymentProcessor['object']->supports('preApproval') + && !$this->_allowWaitlist && + !$this->_requireApproval ) { - //get the button name - $buttonName = $this->controller->getButtonName(); - if (in_array($buttonName, - array( - $this->_expressButtonName, - $this->_expressButtonName . '_x', - $this->_expressButtonName . '_y', - ) - ) && empty($params['is_pay_later']) && - !$this->_allowWaitlist && - !$this->_requireApproval - ) { - $this->set('contributeMode', 'express'); - // Send Event Name & Id in Params - $params['eventName'] = $this->_values['event']['title']; - $params['eventId'] = $this->_values['event']['id']; - - $params['cancelURL'] = CRM_Utils_System::url('civicrm/event/register', - "_qf_Register_display=1&qfKey={$this->controller->_key}", - TRUE, NULL, FALSE - ); - if (CRM_Utils_Array::value('additional_participants', $params, FALSE)) { - $urlArgs = "_qf_Participant_1_display=1&rfp=1&qfKey={$this->controller->_key}"; - } - else { - $urlArgs = "_qf_Confirm_display=1&rfp=1&qfKey={$this->controller->_key}"; - } - $params['returnURL'] = CRM_Utils_System::url('civicrm/event/register', - $urlArgs, - TRUE, NULL, FALSE - ); - $params['invoiceID'] = $invoiceID; + $this->handlePreApproval($params); - $params['component'] = 'event'; - $token = $payment->doPreApproval($params); - if (is_a($token, 'CRM_Core_Error')) { - CRM_Core_Error::displaySessionError($token); - CRM_Utils_System::redirect($params['cancelURL']); - } + $this->set('contributeMode', 'express'); - $this->set('token', $token); + // Send Event Name & Id in Params + $params['eventName'] = $this->_values['event']['title']; + $params['eventId'] = $this->_values['event']['id']; - $paymentURL = $this->_paymentProcessor['url_site'] . "/cgi-bin/webscr?cmd=_express-checkout&token=$token"; + $params['cancelURL'] = CRM_Utils_System::url('civicrm/event/register', + "_qf_Register_display=1&qfKey={$this->controller->_key}", + TRUE, NULL, FALSE + ); + if (CRM_Utils_Array::value('additional_participants', $params, FALSE)) { + $urlArgs = "_qf_Participant_1_display=1&rfp=1&qfKey={$this->controller->_key}"; + } + else { + $urlArgs = "_qf_Confirm_display=1&rfp=1&qfKey={$this->controller->_key}"; + } + $params['returnURL'] = CRM_Utils_System::url('civicrm/event/register', + $urlArgs, + TRUE, NULL, FALSE + ); + $params['invoiceID'] = $invoiceID; - CRM_Utils_System::redirect($paymentURL); + $params['component'] = 'event'; + $token = $payment->doPreApproval($params); + if (is_a($token, 'CRM_Core_Error')) { + CRM_Core_Error::displaySessionError($token); + CRM_Utils_System::redirect($params['cancelURL']); } + + $this->set('token', $token); + + $paymentURL = $this->_paymentProcessor['url_site'] . "/cgi-bin/webscr?cmd=_express-checkout&token=$token"; + CRM_Utils_System::redirect($paymentURL); } elseif ($this->_paymentProcessor && $this->_paymentProcessor['billing_mode'] & CRM_Core_Payment::BILLING_MODE_NOTIFY ) { $this->set('contributeMode', 'notify'); } - } - else { - $session = CRM_Core_Session::singleton(); - $params['description'] = ts('Online Event Registration') . ' ' . $this->_values['event']['title']; + else { + $params['description'] = ts('Online Event Registration') . ' ' . $this->_values['event']['title']; - $this->_params = array(); - $this->_params[] = $params; - $this->set('params', $this->_params); + $this->_params = array(); + $this->_params[] = $params; + $this->set('params', $this->_params); - if ( - empty($params['additional_participants']) - && !$this->_values['event']['is_confirm_enabled'] // CRM-11182 - Optional confirmation screen - ) { - self::processRegistration($this->_params); + if ( + empty($params['additional_participants']) + && !$this->_values['event']['is_confirm_enabled'] // CRM-11182 - Optional confirmation screen + ) { + self::processRegistration($this->_params); + } } } @@ -1186,8 +1182,6 @@ class CRM_Event_Form_Registration_Register extends CRM_Event_Form_Registration { * @param array $params * Form values. * @param int $contactID - * - * @return void */ public function processRegistration($params, $contactID = NULL) { $session = CRM_Core_Session::singleton(); @@ -1313,7 +1307,7 @@ class CRM_Event_Form_Registration_Register extends CRM_Event_Form_Registration { $primaryContactId, $isTest, TRUE ); - //lets carry all paticipant params w/ values. + //lets carry all participant params w/ values. foreach ($additionalIDs as $participantID => $contactId) { $participantNum = NULL; if ($participantID == $registerByID) { @@ -1366,7 +1360,7 @@ class CRM_Event_Form_Registration_Register extends CRM_Event_Form_Registration { * * @param array $fields * The input form values(anonymous user). - * @param array $self + * @param CRM_Event_Form_Registration_Register $self * Event data. * @param bool $isAdditional * Treat isAdditional participants a bit differently. -- 2.25.1